diff options
| author | Tannin <devnull@localhost> | 2014-11-21 15:07:31 +0100 |
|---|---|---|
| committer | Tannin <devnull@localhost> | 2014-11-21 15:07:31 +0100 |
| commit | 45a46778fb9c7195cb09fbba4a2c502dca6bca13 (patch) | |
| tree | c304a6ffa3412fa66edab50fd293cc7fd13faaa9 /src | |
| parent | cfb863f6c3ae7406028b9e167a3115250fefbca3 (diff) | |
| parent | f2f9e11fdd876821107cff0c1c5b9d8ecf66691f (diff) | |
Merge
Diffstat (limited to 'src')
69 files changed, 11063 insertions, 9891 deletions
diff --git a/src/ModOrganizer.pro b/src/ModOrganizer.pro index 9907d086..a8f7f53e 100644 --- a/src/ModOrganizer.pro +++ b/src/ModOrganizer.pro @@ -1,6 +1,5 @@ TEMPLATE = subdirs
-
SUBDIRS = bsatk \
shared \
uibase \
@@ -13,9 +12,11 @@ SUBDIRS = bsatk \ nxmhandler \
BossDummy \
pythonRunner \
+ loot_cli \
esptk
-plugins.depends = pythonRunner
+pythonRunner.depends = uibase
+plugins.depends = pythonRunner uibase
hookdll.depends = shared
organizer.depends = shared uibase plugins
@@ -30,7 +31,7 @@ DLLSPATH = $${DESTDIR}\\dlls otherlibs.path = $$DLLSPATH
otherlibs.files += $${STATICDATAPATH}\\7z.dll \
- $$(BOOSTPATH)\\stage\\lib\\boost_python-vc*-mt-1*.dll
+ $${BOOSTPATH}\\stage\\lib\\boost_python-vc*-mt-1*.dll
qtlibs.path = $$DLLSPATH
diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp index b5bfeb04..d7749187 100644 --- a/src/aboutdialog.cpp +++ b/src/aboutdialog.cpp @@ -36,12 +36,11 @@ AboutDialog::AboutDialog(const QString &version, QWidget *parent) m_LicenseFiles[LICENSE_CCBY3] = "by-sa3.txt";
m_LicenseFiles[LICENSE_ZLIB] = "zlib.txt";
- addLicense("Qt 4.8.5", LICENSE_LGPL3);
+ addLicense("Qt 5.3", LICENSE_LGPL3);
addLicense("Qt Json", LICENSE_GPL3);
addLicense("Boost Library", LICENSE_BOOST);
addLicense("7-zip", LICENSE_LGPL3);
addLicense("ZLib", LICENSE_ZLIB);
- addLicense("NIF File Format Library", LICENSE_BSD3);
addLicense("Tango Icon Theme", LICENSE_NONE);
addLicense("RRZE Icon Set", LICENSE_CCBY3);
addLicense("Icons by Lorc, Delapouite and sbed available on http://game-icons.net", LICENSE_CCBY3);
diff --git a/src/bbcode.cpp b/src/bbcode.cpp index 18f2beb1..0f9170d4 100644 --- a/src/bbcode.cpp +++ b/src/bbcode.cpp @@ -39,7 +39,7 @@ public: return s_Instance;
}
- QString convertTag(const QString &input, int &length)
+ QString convertTag(QString input, int &length)
{
// extract the tag name
m_TagNameExp.indexIn(input, 1, QRegExp::CaretAtOffset);
@@ -50,29 +50,52 @@ public: if (tagName.endsWith('=')) {
tagName.chop(1);
}
- QString closeTag = tagName == "*" ? "<br/>"
- : QString("[/%1]").arg(tagName);
- int closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive);
- //qDebug("close tag %s at %d", closeTag.toUtf8().constData(), closeTagPos);
+ int closeTagPos = 0;
+ int closeTagLength = 0;
+ if (tagName == "*") {
+ // ends at the next bullet point
+ closeTagPos = input.indexOf(QRegExp("(\\[\\*\\]|</ul>)", Qt::CaseInsensitive), 3);
+ // leave closeTagLength at 0 because we don't want to "eat" the next bullet point
+ } else if (tagName == "line") {
+ // ends immediately after the tag
+ closeTagPos = 6;
+ // leave closeTagLength at 0 because there is no close tag to skip over
+ } else {
+ QString closeTag = QString("[/%1]").arg(tagName);
+ closeTagPos = input.indexOf(closeTag, 0, Qt::CaseInsensitive);
+ if (closeTagPos == -1) {
+ // workaround to improve compatibility: add fake closing tag
+ input.append(closeTag);
+ closeTagPos = input.size() - closeTag.size();
+ }
+ closeTagLength = closeTag.size();
+ }
if (closeTagPos > -1) {
- length = closeTagPos + closeTag.length();
+ length = closeTagPos + closeTagLength;
QString temp = input.mid(0, length);
if (tagIter->second.first.indexIn(temp) == 0) {
if (tagIter->second.second.isEmpty()) {
if (tagName == "color") {
QString color = tagIter->second.first.cap(1);
QString content = tagIter->second.first.cap(2);
- auto colIter = m_ColorMap.find(color.toLower());
- if (colIter != m_ColorMap.end()) {
- color = colIter->second;
+ if (color.at(0) == "#") {
+ return temp.replace(tagIter->second.first, QString("<font style=\"color: %1;\">%2</font>").arg(color, content));
+ } else {
+ auto colIter = m_ColorMap.find(color.toLower());
+ if (colIter != m_ColorMap.end()) {
+ color = colIter->second;
+ }
+ return temp.replace(tagIter->second.first, QString("<font style=\"color: #%1;\">%2</font>").arg(color, content));
}
- return temp.replace(tagIter->second.first, QString("<font style=\"color: #%1;\">%2</font>").arg(color, content));
} else {
qWarning("don't know how to deal with tag %s", qPrintable(tagName));
}
} else {
+ if (tagName == "*") {
+ temp.remove(QRegExp("(\\[/\\*\\])?(<br/>)?$"));
+ }
return temp.replace(tagIter->second.first, tagIter->second.second);
}
} else {
@@ -112,7 +135,7 @@ private: m_TagMap["color="] = std::make_pair(QRegExp("\\[color=([^\\]]*)\\](.*)\\[/color\\]"),
"");
m_TagMap["font="] = std::make_pair(QRegExp("\\[font=([^\\]]*)\\](.*)\\[/font\\]"),
- "<font face=\\1>\\2</font>");
+ "<font style=\"font-family: \\1;\">\\2</font>");
m_TagMap["center"] = std::make_pair(QRegExp("\\[center\\](.*)\\[/center\\]"),
"<div align=\"center\">\\1</div>");
m_TagMap["quote"] = std::make_pair(QRegExp("\\[quote\\](.*)\\[/quote\\]"),
@@ -123,6 +146,8 @@ private: "<pre>\\1</pre>");
m_TagMap["heading"]= std::make_pair(QRegExp("\\[heading\\](.*)\\[/heading\\]"),
"<h2><strong>\\1</strong></h2>");
+ m_TagMap["line"] = std::make_pair(QRegExp("\\[line\\]"),
+ "<hr>");
// lists
m_TagMap["list"] = std::make_pair(QRegExp("\\[list\\](.*)\\[/list\\]"),
@@ -135,8 +160,6 @@ private: "<ol>\\1</ol>");
m_TagMap["li"] = std::make_pair(QRegExp("\\[li\\](.*)\\[/li\\]"),
"<li>\\1</li>");
- m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)<br/>"),
- "<li>\\1</li>");
// tables
m_TagMap["table"] = std::make_pair(QRegExp("\\[table\\](.*)\\[/table\\]"),
@@ -153,13 +176,26 @@ private: "<a href=\"\\1\">\\1</a>");
m_TagMap["url="] = std::make_pair(QRegExp("\\[url=([^\\]]*)\\](.*)\\[/url\\]"),
"<a href=\"\\1\">\\2</a>");
- m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"), " ");
- m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"), " ");
+ m_TagMap["img"] = std::make_pair(QRegExp("\\[img\\](.*)\\[/img\\]"),
+ "<img src=\"\\1\">");
+ m_TagMap["img="] = std::make_pair(QRegExp("\\[img=([^\\]]*)\\](.*)\\[/img\\]"),
+ "<img src=\"\\2\" alt=\"\\1\">");
m_TagMap["email="] = std::make_pair(QRegExp("\\[email=\"?([^\\]]*)\"?\\](.*)\\[/email\\]"),
"<a href=\"mailto:\\1\">\\2</a>");
m_TagMap["youtube"] = std::make_pair(QRegExp("\\[youtube\\](.*)\\[/youtube\\]"),
"<a href=\"http://www.youtube.com/v/\\1\">http://www.youtube.com/v/\\1</a>");
+
+ // make all patterns non-greedy and case-insensitive
+ for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
+ iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
+ iter->second.first.setMinimal(true);
+ }
+
+ // this tag is in fact greedy
+ m_TagMap["*"] = std::make_pair(QRegExp("\\[\\*\\](.*)"),
+ "<li>\\1</li>");
+
m_ColorMap.insert(std::make_pair<QString, QString>("red", "FF0000"));
m_ColorMap.insert(std::make_pair<QString, QString>("green", "00FF00"));
m_ColorMap.insert(std::make_pair<QString, QString>("blue", "0000FF"));
@@ -170,13 +206,13 @@ private: m_ColorMap.insert(std::make_pair<QString, QString>("cyan", "00FFFF"));
m_ColorMap.insert(std::make_pair<QString, QString>("magenta", "FF00FF"));
m_ColorMap.insert(std::make_pair<QString, QString>("brown", "A52A2A"));
- m_ColorMap.insert(std::make_pair<QString, QString>("orange", "FFCC00"));
-
- // make all patterns non-greedy and case-insensitive
- for (TagMap::iterator iter = m_TagMap.begin(); iter != m_TagMap.end(); ++iter) {
- iter->second.first.setCaseSensitivity(Qt::CaseInsensitive);
- iter->second.first.setMinimal(true);
- }
+ m_ColorMap.insert(std::make_pair<QString, QString>("orange", "FFA500"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("gold", "FFD700"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("deepskyblue", "00BFFF"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("salmon", "FA8072"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("dodgerblue", "1E90FF"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("greenyellow", "ADFF2F"));
+ m_ColorMap.insert(std::make_pair<QString, QString>("peru", "CD853F"));
}
private:
@@ -199,7 +235,6 @@ QString convertToHTML(const QString &inputParam) QString input = inputParam.mid(0).replace("\r\n", "<br/>");
input.replace("\\\"", "\"").replace("\\'", "'");
-
QString result;
int lastBlock = 0;
int pos = 0;
@@ -209,18 +244,23 @@ QString convertToHTML(const QString &inputParam) // append everything between the previous tag-block and the current one
result.append(input.midRef(lastBlock, pos - lastBlock));
- // convert the tag and content if necessary
- int length = -1;
- QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
- if (length != 0) {
- QString temp = convertToHTML(replacement);
- result.append(temp);
- // length contains the number of characters in the original tag
- pos += length;
+ if ((pos < (input.size() - 1)) && (input.at(pos + 1) == '/')) {
+ // skip invalid end tag
+ int tagEnd = input.indexOf(']', pos) + 1;
+ pos = tagEnd;
} else {
- // nothing replaced
- result.append('[');
- ++pos;
+ // convert the tag and content if necessary
+ int length = -1;
+ QString replacement = BBCodeMap::instance().convertTag(input.mid(pos), length);
+ if (length != 0) {
+ result.append(convertToHTML(replacement));
+ // length contains the number of characters in the original tag
+ pos += length;
+ } else {
+ // nothing replaced
+ result.append('[');
+ ++pos;
+ }
}
lastBlock = pos;
}
diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp index 521459d0..933b4bc0 100644 --- a/src/browserdialog.cpp +++ b/src/browserdialog.cpp @@ -22,10 +22,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "messagedialog.h"
#include "report.h"
-#include "json.h"
#include "persistentcookiejar.h"
#include <gameinfo.h>
+#include "json.h"
#include <utility.h>
#include <gameinfo.h>
@@ -202,7 +202,6 @@ void BrowserDialog::unsupportedContent(QNetworkReply *reply) return;
}
- qDebug("unsupported: %s - %s", view->url().toString().toUtf8().constData(), reply->url().toString().toUtf8().constData());
emit requestDownload(view->url(), reply);
} catch (const std::exception &e) {
if (isVisible()) {
diff --git a/src/categories.cpp b/src/categories.cpp index 4c851338..57e18a28 100644 --- a/src/categories.cpp +++ b/src/categories.cpp @@ -104,7 +104,11 @@ void CategoryFactory::reset() {
m_Categories.clear();
m_IDMap.clear();
- addCategory(0, "None", MakeVector<int>(2, 28, 87), 0);
+ // 28 =
+ // 43 = Savegames (makes no sense to install them through MO)
+ // 45 = Videos and trailers
+ // 87 = Miscelanous
+ addCategory(0, "None", MakeVector<int>(4, 28, 43, 45, 87), 0);
}
@@ -189,24 +193,38 @@ void CategoryFactory::loadDefaultCategories() // mods appear in the combo box
addCategory(1, "Animations", MakeVector<int>(1, 51), 0);
addCategory(2, "Armour", MakeVector<int>(1, 54), 0);
- addCategory(3, "Audio", MakeVector<int>(1, 61), 0);
+ addCategory(3, "Sound & Music", MakeVector<int>(1, 61), 0);
addCategory(5, "Clothing", MakeVector<int>(1, 60), 0);
addCategory(6, "Collectables", MakeVector<int>(1, 92), 0);
- addCategory(7, "Creatures", MakeVector<int>(2, 83, 65), 0);
+ addCategory(28, "Companions", MakeVector<int>(2, 66, 96), 0);
+ addCategory(7, "Creatures & Mounts", MakeVector<int>(2, 83, 65), 0);
addCategory(8, "Factions", MakeVector<int>(1, 25), 0);
addCategory(9, "Gameplay", MakeVector<int>(1, 24), 0);
addCategory(10, "Hair", MakeVector<int>(1, 26), 0);
addCategory(11, "Items", MakeVector<int>(2, 27, 85), 0);
- addCategory(19, "Weapons", MakeVector<int>(2, 36, 55), 11);
+ addCategory(32, "Mercantile", MakeVector<int>(1, 69), 0);
+ addCategory(19, "Weapons", MakeVector<int>(1, 55), 11);
+ addCategory(36, "Weapon & Armour Sets", MakeVector<int>(1, 39), 11);
addCategory(12, "Locations", MakeVector<int>(7, 22, 30, 70, 88, 89, 90, 91), 0);
+ addCategory(31, "Landscape Changes", MakeVector<int>(1, 58), 0);
addCategory(4, "Cities", MakeVector<int>(1, 53), 12);
+ addCategory(29, "Environment", MakeVector<int>(1, 74), 0);
+ addCategory(30, "Immersion", MakeVector<int>(1, 78), 0);
+ addCategory(25, "Castles & Mansions", MakeVector<int>(1, 68), 23);
addCategory(20, "Magic", MakeVector<int>(3, 75, 93, 94), 0);
addCategory(21, "Models & Textures", MakeVector<int>(1, 29), 0);
+ addCategory(33, "Modders resources", MakeVector<int>(1, 82), 0);
addCategory(13, "NPCs", MakeVector<int>(1, 33), 0);
addCategory(14, "Patches", MakeVector<int>(2, 79, 84), 0);
+ addCategory(24, "Bugfixes", MakeVector<int>(1, 95), 0);
+ addCategory(35, "Utilities", MakeVector<int>(1, 39), 0);
+ addCategory(26, "Cheats", MakeVector<int>(1, 40), 0);
+ addCategory(23, "Player Homes", MakeVector<int>(1, 67), 0);
addCategory(15, "Quests", MakeVector<int>(1, 35), 0);
addCategory(16, "Races & Classes", MakeVector<int>(1, 34), 0);
+ addCategory(27, "Combat", MakeVector<int>(1, 77), 0);
addCategory(22, "Skills", MakeVector<int>(1, 73), 0);
+ addCategory(34, "Stealth", MakeVector<int>(1, 76), 0);
addCategory(17, "UI", MakeVector<int>(1, 42), 0);
addCategory(18, "Visuals", MakeVector<int>(1, 62), 0);
}
@@ -214,7 +232,7 @@ void CategoryFactory::loadDefaultCategories() int CategoryFactory::getParentID(unsigned int index) const
{
- if ((index < 0) || (index >= m_Categories.size())) {
+ if (index >= m_Categories.size()) {
throw MyException(QObject::tr("invalid index %1").arg(index));
}
@@ -249,7 +267,7 @@ bool CategoryFactory::isDecendantOf(int id, int parentID) const bool CategoryFactory::hasChildren(unsigned int index) const
{
- if ((index < 0) || (index >= m_Categories.size())) {
+ if (index >= m_Categories.size()) {
throw MyException(QObject::tr("invalid index %1").arg(index));
}
@@ -259,7 +277,7 @@ bool CategoryFactory::hasChildren(unsigned int index) const QString CategoryFactory::getCategoryName(unsigned int index) const
{
- if ((index < 0) || (index >= m_Categories.size())) {
+ if (index >= m_Categories.size()) {
throw MyException(QObject::tr("invalid index %1").arg(index));
}
@@ -269,7 +287,7 @@ QString CategoryFactory::getCategoryName(unsigned int index) const int CategoryFactory::getCategoryID(unsigned int index) const
{
- if ((index < 0) || (index >= m_Categories.size())) {
+ if (index >= m_Categories.size()) {
throw MyException(QObject::tr("invalid index %1").arg(index));
}
diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 2186f9a5..24fda501 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -83,8 +83,12 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure foreach (const QString &archive, archives) {
QFileInfo fileInfo(archive);
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
- directoryStructure->addFromBSA(ToWString(modName), directoryW,
- ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
+ try {
+ directoryStructure->addFromBSA(ToWString(modName), directoryW,
+ ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
+ } catch (const std::exception &e) {
+ throw MyException(tr("failed to parse bsa %1: %2").arg(archive, e.what()));
+ }
}
}
}
@@ -143,7 +147,7 @@ void DirectoryRefresher::refresh() try {
addModToStructure(m_DirectoryStructure, iter->modName, i, iter->absolutePath, iter->stealFiles, iter->archives);
} catch (const std::exception &e) {
- emit error(tr("failed to read bsa: %1").arg(e.what()));
+ emit error(tr("failed to read mod (%1): %2").arg(iter->modName, e.what()));
}
emit progress((i * 100) / m_Mods.size() + 1);
}
diff --git a/src/dlls.manifest.debug.qt5 b/src/dlls.manifest.debug.qt5 index 6cc0a83d..1bbdf691 100644 --- a/src/dlls.manifest.debug.qt5 +++ b/src/dlls.manifest.debug.qt5 @@ -8,7 +8,10 @@ <file name="Qt5Declaratived.dll"/>
<file name="Qt5Quickd.dll"/>
<file name="Qt5Guid.dll"/>
+ <file name="Qt5Multimediad.dll"/>
+ <file name="Qt5MultimediaWidgetsd.dll"/>
<file name="Qt5Networkd.dll"/>
+ <file name="Qt5OpenGLd.dll"/>
<file name="Qt5Scriptd.dll"/>
<file name="Qt5Sqld.dll"/>
<file name="Qt5Widgetsd.dll"/>
diff --git a/src/dlls.manifest.qt5 b/src/dlls.manifest.qt5 index 5a22c2a8..59918f2b 100644 --- a/src/dlls.manifest.qt5 +++ b/src/dlls.manifest.qt5 @@ -7,12 +7,20 @@ <file name="Qt5Core.dll"/>
<file name="Qt5Declarative.dll"/>
<file name="Qt5Gui.dll"/>
- <file name="Qt5Quick.dll"/>
+ <file name="Qt5Multimedia.dll"/>
+ <file name="Qt5MultimediaWidgets.dll"/>
<file name="Qt5Network.dll"/>
+ <file name="Qt5OpenGL.dll"/>
+ <file name="Qt5Positioning.dll"/>
+ <file name="Qt5PrintSupport.dll"/>
+ <file name="Qt5Qml.dll"/>
+ <file name="Qt5Quick.dll"/>
+ <file name="Qt5Sensors.dll"/>
<file name="Qt5Script.dll"/>
<file name="Qt5Sql.dll"/>
<file name="Qt5Svg.dll"/>
+ <file name="Qt5WebKit.dll"/>
+ <file name="Qt5WebKitWidgets.dll"/>
<file name="Qt5Widgets.dll"/>
- <file name="Qt5Xml.dll"/>
<file name="Qt5XmlPatterns.dll"/>
</assembly>
\ No newline at end of file diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp index 856ca79c..b803d170 100644 --- a/src/downloadmanager.cpp +++ b/src/downloadmanager.cpp @@ -331,7 +331,9 @@ bool DownloadManager::addDownload(const QStringList &URLs, fileName = "unknown";
}
- QNetworkRequest request(URLs.first());
+ 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);
}
@@ -606,7 +608,7 @@ void DownloadManager::pauseDownload(int index) DownloadInfo *info = m_ActiveDownloads.at(index);
if (info->m_State == STATE_DOWNLOADING) {
- if (info->m_Reply->isRunning()) {
+ if ((info->m_Reply != NULL) && (info->m_Reply->isRunning())) {
setState(info, STATE_PAUSING);
} else {
setState(info, STATE_PAUSED);
@@ -644,7 +646,7 @@ void DownloadManager::resumeDownloadInt(int index) info->m_CurrentUrl = (info->m_CurrentUrl + 1) % info->m_Urls.count();
}
qDebug("request resume from url %s", qPrintable(info->currentURL()));
- QNetworkRequest request(info->currentURL());
+ QNetworkRequest request(QUrl::fromEncoded(info->currentURL().toLocal8Bit()));
info->m_ResumePos = info->m_Output.size();
qDebug("resume at %lld bytes", info->m_ResumePos);
QByteArray rangeHeader = "bytes=" + QByteArray::number(info->m_ResumePos) + "-";
@@ -685,7 +687,7 @@ void DownloadManager::queryInfo(int index) return;
}
- if (info->m_FileInfo->modID == 0UL) {
+ if (info->m_FileInfo->modID <= 0) {
QString fileName = getFileName(index);
QString ignore;
NexusInterface::interpretNexusFileName(fileName, ignore, info->m_FileInfo->modID, true);
@@ -1198,47 +1200,34 @@ void DownloadManager::nxmFileInfoAvailable(int modID, int fileID, QVariant userD m_RequestIDs.insert(m_NexusInterface->requestDownloadURL(modID, fileID, this, qVariantFromValue(test), QString()));
}
-
-// sort function to sort by best download server
-bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferredServers, const QVariant &LHS, const QVariant &RHS)
+int evaluateFileInfoMap(const QVariantMap &map, const std::map<QString, int> &preferredServers)
{
- int LHSVal = 0;
- int RHSVal = 0;
+ int result = 0;
- QVariantMap LHSMap = LHS.toMap();
- QVariantMap RHSMap = RHS.toMap();
-
- int LHSUsers = LHSMap["ConnectedUsers"].toInt();
- int RHSUsers = RHSMap["ConnectedUsers"].toInt();
+ int users = map["ConnectedUsers"].toInt();
// 0 users is probably a sign that the server is offline. Since there is currently no
// mechanism to try a different server, we avoid those without users
- if (LHSUsers == 0) {
- LHSVal -= 500;
- } else {
- LHSVal -= LHSUsers;
- }
- if (RHSUsers == 0) {
- RHSVal -= 500;
+ if (users == 0) {
+ result -= 500;
} else {
- RHSVal -= RHSUsers;
+ result -= users;
}
- // user preference. This is a bit silly because the more servers on the preferred list the higher the boost
- auto LHSPreference = preferredServers.find(LHSMap["Name"].toString());
- auto RHSPreference = preferredServers.find(RHSMap["Name"].toString());
+ auto preference = preferredServers.find(map["Name"].toString());
- if (LHSPreference != preferredServers.end()) {
- LHSVal += 100 + LHSPreference->second * 20;
- }
- if (RHSPreference != preferredServers.end()) {
- RHSVal += 100 + RHSPreference->second * 20;
+ if (preference != preferredServers.end()) {
+ result += 100 + preference->second * 20;
}
- // premium isn't valued high because premium servers already get a massive boost for having few users online
- if (LHSMap["IsPremium"].toBool()) LHSVal += 5;
- if (RHSMap["IsPremium"].toBool()) RHSVal += 5;
+ if (map["IsPremium"].toBool()) result += 5;
+
+ return result;
+}
- return RHSVal < LHSVal;
+// sort function to sort by best download server
+bool DownloadManager::ServerByPreference(const std::map<QString, int> &preferredServers, const QVariant &LHS, const QVariant &RHS)
+{
+ return evaluateFileInfoMap(LHS.toMap(), preferredServers) > evaluateFileInfoMap(RHS.toMap(), preferredServers);
}
int DownloadManager::startDownloadURLs(const QStringList &urls)
diff --git a/src/editexecutablesdialog.cpp b/src/editexecutablesdialog.cpp index 02abf30e..3cc749d6 100644 --- a/src/editexecutablesdialog.cpp +++ b/src/editexecutablesdialog.cpp @@ -1,289 +1,287 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "editexecutablesdialog.h"
-#include "ui_editexecutablesdialog.h"
-#include "filedialogmemory.h"
-#include <QMessageBox>
-#include <Shellapi.h>
-#include <utility.h>
-
-
-using namespace MOBase;
-using namespace MOShared;
-
-EditExecutablesDialog::EditExecutablesDialog(const ExecutablesList &executablesList, QWidget *parent)
- : TutorableDialog("EditExecutables", parent),
- ui(new Ui::EditExecutablesDialog), m_CurrentItem(NULL), m_ExecutablesList(executablesList)
-{
- ui->setupUi(this);
-
- refreshExecutablesWidget();
-}
-
-EditExecutablesDialog::~EditExecutablesDialog()
-{
- delete ui;
-}
-
-ExecutablesList EditExecutablesDialog::getExecutablesList() const
-{
- ExecutablesList newList;
- for (int i = 0; i < ui->executablesListBox->count(); ++i) {
- newList.addExecutable(ui->executablesListBox->item(i)->data(Qt::UserRole).value<Executable>());
- }
- return newList;
-}
-
-void EditExecutablesDialog::refreshExecutablesWidget()
-{
- QListWidget *executablesWidget = findChild<QListWidget*>("executablesListBox");
-
- executablesWidget->clear();
- std::vector<Executable>::const_iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
-
- for(; current != end; ++current) {
- QListWidgetItem *newItem = new QListWidgetItem(current->m_Title);
- QVariant temp;
- temp.setValue(*current);
- newItem->setData(Qt::UserRole, temp);
- newItem->setTextColor(current->m_Custom ? QColor(Qt::black) : QColor(Qt::darkGray));
- executablesWidget->addItem(newItem);
- }
-
- ui->addButton->setEnabled(false);
- ui->removeButton->setEnabled(false);
-}
-
-
-void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &arg1)
-{
- QFileInfo fileInfo(arg1);
- ui->addButton->setEnabled(fileInfo.exists() && fileInfo.isFile());
-}
-
-void EditExecutablesDialog::resetInput()
-{
- ui->binaryEdit->setText("");
- ui->titleEdit->setText("");
- ui->workingDirEdit->clear();
- ui->argumentsEdit->setText("");
- ui->appIDOverwriteEdit->clear();
- ui->overwriteAppIDBox->setChecked(false);
- ui->closeCheckBox->setChecked(false);
- m_CurrentItem = NULL;
-}
-
-
-void EditExecutablesDialog::saveExecutable()
-{
- m_ExecutablesList.addExecutable(ui->titleEdit->text(), QDir::fromNativeSeparators(ui->binaryEdit->text()),
- ui->argumentsEdit->text(), QDir::fromNativeSeparators(ui->workingDirEdit->text()),
- (ui->closeCheckBox->checkState() == Qt::Checked) ? DEFAULT_CLOSE : DEFAULT_STAY,
- ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "",
- true, false);
-}
-
-
-void EditExecutablesDialog::delayedRefresh()
-{
- int index = ui->executablesListBox->currentIndex().row();
- resetInput();
- refreshExecutablesWidget();
- ui->executablesListBox->setCurrentRow(index);
-}
-
-
-void EditExecutablesDialog::on_addButton_clicked()
-{
- saveExecutable();
-
- resetInput();
- refreshExecutablesWidget();
-}
-
-void EditExecutablesDialog::on_browseButton_clicked()
-{
- QString binaryName = FileDialogMemory::getOpenFileName("editExecutableBinary", this,
- tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar"));
-
- if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) {
- QString binaryPath;
- { // try to find java automatically
- std::wstring binaryNameW = ToWString(binaryName);
- WCHAR buffer[MAX_PATH];
- if (::FindExecutableW(binaryNameW.c_str(), NULL, buffer) > (HINSTANCE)32) {
- DWORD binaryType = 0UL;
- if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) {
- qDebug("failed to determine binary type: %lu", ::GetLastError());
- } else if (binaryType == SCS_32BIT_BINARY) {
- binaryPath = ToQString(buffer);
- }
- }
- }
- if (binaryPath.isEmpty()) {
- QSettings javaReg("HKEY_LOCAL_MACHINE\\Software\\JavaSoft\\Java Runtime Environment", QSettings::NativeFormat);
- if (javaReg.contains("CurrentVersion")) {
- QString currentVersion = javaReg.value("CurrentVersion").toString();
- binaryPath = javaReg.value(QString("%1/JavaHome").arg(currentVersion)).toString().append("\\bin\\javaw.exe");
- }
- }
- if (binaryPath.isEmpty()) {
- QMessageBox::information(this, tr("Java (32-bit) required"),
- tr("MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe "
- "from that installation as the binary."));
- } else {
- ui->binaryEdit->setText(binaryPath);
- }
-
- ui->workingDirEdit->setText(QDir::toNativeSeparators(QFileInfo(binaryName).absolutePath()));
- ui->argumentsEdit->setText("-jar \"" + QDir::toNativeSeparators(binaryName) + "\"");
- } else {
- ui->binaryEdit->setText(QDir::toNativeSeparators(binaryName));
- }
-}
-
-void EditExecutablesDialog::on_browseDirButton_clicked()
-{
- QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this,
- tr("Select a directory"));
-
- ui->workingDirEdit->setText(dirName);
-}
-
-void EditExecutablesDialog::on_removeButton_clicked()
-{
-// QLineEdit *binaryEdit = findChild<QLineEdit*>("binaryEdit");
-
- if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- m_ExecutablesList.remove(ui->titleEdit->text());
- }
-
- resetInput();
- refreshExecutablesWidget();
-}
-
-void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1)
-{
- QPushButton *addButton = findChild<QPushButton*>("addButton");
- QPushButton *removeButton = findChild<QPushButton*>("removeButton");
-
- QListWidget *executablesWidget = findChild<QListWidget*>("executablesListBox");
-
- QList<QListWidgetItem*> existingItems = executablesWidget->findItems(arg1, Qt::MatchFixedString);
-
- addButton->setEnabled(arg1.length() != 0);
-
- if (existingItems.count() == 0) {
- addButton->setText(tr("Add"));
- removeButton->setEnabled(false);
- } else {
- // existing item. is it a custom one?
- addButton->setText(tr("Modify"));
- removeButton->setEnabled(true);
- }
-}
-
-
-bool EditExecutablesDialog::executableChanged()
-{
- if (m_CurrentItem != NULL) {
- const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>();
-
- return selectedExecutable.m_Arguments != ui->argumentsEdit->text()
- || selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text()
- || selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text())
- || selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text())
- || (selectedExecutable.m_CloseMO == DEFAULT_CLOSE) != ui->closeCheckBox->isChecked();
- } else {
- return false;
- }
-}
-
-
-void EditExecutablesDialog::on_executablesListBox_currentItemChanged(QListWidgetItem *current, QListWidgetItem*)
-{
- if (current == NULL) {
- resetInput();
- return;
- }
-
- if (executableChanged()) {
- QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"),
- tr("You made changes to the current executable, do you want to save them?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- if (res == QMessageBox::Cancel) {
- return;
- } else if (res == QMessageBox::Yes) {
- // this invalidates the item passed as a a parameter
- saveExecutable();
-
- QTimer::singleShot(50, this, SLOT(delayedRefresh()));
- return;
- }
- }
-
- m_CurrentItem = current;
-
- const Executable &selectedExecutable = current->data(Qt::UserRole).value<Executable>();
-
- ui->titleEdit->setText(selectedExecutable.m_Title);
- ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath()));
- ui->argumentsEdit->setText(selectedExecutable.m_Arguments);
- ui->workingDirEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_WorkingDirectory));
- ui->closeCheckBox->setChecked(selectedExecutable.m_CloseMO == DEFAULT_CLOSE);
- if (selectedExecutable.m_CloseMO == NEVER_CLOSE) {
- ui->closeCheckBox->setEnabled(false);
- ui->closeCheckBox->setToolTip(tr("MO must be kept running or this application will not work correctly."));
- } else {
- ui->closeCheckBox->setEnabled(true);
- ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run."));
- }
- ui->removeButton->setEnabled(selectedExecutable.m_Custom);
- ui->overwriteAppIDBox->setChecked(selectedExecutable.m_SteamAppID != 0);
- if (selectedExecutable.m_SteamAppID != 0) {
- ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID);
- } else {
- ui->appIDOverwriteEdit->clear();
- }
-}
-
-
-void EditExecutablesDialog::on_overwriteAppIDBox_toggled(bool checked)
-{
- ui->appIDOverwriteEdit->setEnabled(checked);
-}
-
-void EditExecutablesDialog::on_closeButton_clicked()
-{
- if (executableChanged()) {
- QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"),
- tr("You made changes to the current executable, do you want to save them?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
- if (res == QMessageBox::Cancel) {
- return;
- } else if (res == QMessageBox::Yes) {
- saveExecutable();
- }
- }
- this->accept();
-}
-
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "editexecutablesdialog.h" +#include "ui_editexecutablesdialog.h" +#include "filedialogmemory.h" +#include <QMessageBox> +#include <Shellapi.h> +#include <utility.h> + + +using namespace MOBase; +using namespace MOShared; + +EditExecutablesDialog::EditExecutablesDialog(const ExecutablesList &executablesList, QWidget *parent) + : TutorableDialog("EditExecutables", parent), + ui(new Ui::EditExecutablesDialog), m_CurrentItem(NULL), m_ExecutablesList(executablesList) +{ + ui->setupUi(this); + + refreshExecutablesWidget(); +} + +EditExecutablesDialog::~EditExecutablesDialog() +{ + delete ui; +} + +ExecutablesList EditExecutablesDialog::getExecutablesList() const +{ + ExecutablesList newList; + for (int i = 0; i < ui->executablesListBox->count(); ++i) { + newList.addExecutable(ui->executablesListBox->item(i)->data(Qt::UserRole).value<Executable>()); + } + return newList; +} + +void EditExecutablesDialog::refreshExecutablesWidget() +{ + ui->executablesListBox->clear(); + std::vector<Executable>::const_iterator current, end; + m_ExecutablesList.getExecutables(current, end); + + for(; current != end; ++current) { + QListWidgetItem *newItem = new QListWidgetItem(current->m_Title); + QVariant temp; + temp.setValue(*current); + newItem->setData(Qt::UserRole, temp); + newItem->setTextColor(current->m_Custom ? QColor(Qt::black) : QColor(Qt::darkGray)); + ui->executablesListBox->addItem(newItem); + } + + ui->addButton->setEnabled(false); + ui->removeButton->setEnabled(false); +} + + +void EditExecutablesDialog::on_binaryEdit_textChanged(const QString &arg1) +{ + QFileInfo fileInfo(arg1); + ui->addButton->setEnabled(fileInfo.exists() && fileInfo.isFile()); +} + +void EditExecutablesDialog::resetInput() +{ + ui->binaryEdit->setText(""); + ui->titleEdit->setText(""); + ui->workingDirEdit->clear(); + ui->argumentsEdit->setText(""); + ui->appIDOverwriteEdit->clear(); + ui->overwriteAppIDBox->setChecked(false); + ui->closeCheckBox->setChecked(false); + m_CurrentItem = NULL; +} + + +void EditExecutablesDialog::saveExecutable() +{ + m_ExecutablesList.addExecutable(ui->titleEdit->text(), QDir::fromNativeSeparators(ui->binaryEdit->text()), + ui->argumentsEdit->text(), QDir::fromNativeSeparators(ui->workingDirEdit->text()), + (ui->closeCheckBox->checkState() == Qt::Checked) ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE + : ExecutableInfo::CloseMOStyle::DEFAULT_STAY, + ui->overwriteAppIDBox->isChecked() ? ui->appIDOverwriteEdit->text() : "", + true, false); +} + + +void EditExecutablesDialog::delayedRefresh() +{ + int index = ui->executablesListBox->currentIndex().row(); + resetInput(); + refreshExecutablesWidget(); + ui->executablesListBox->setCurrentRow(index); +} + + +void EditExecutablesDialog::on_addButton_clicked() +{ + saveExecutable(); + + resetInput(); + refreshExecutablesWidget(); +} + +void EditExecutablesDialog::on_browseButton_clicked() +{ + QString binaryName = FileDialogMemory::getOpenFileName("editExecutableBinary", this, + tr("Select a binary"), QString(), tr("Executable (%1)").arg("*.exe *.bat *.jar")); + + if (binaryName.endsWith(".jar", Qt::CaseInsensitive)) { + QString binaryPath; + { // try to find java automatically + std::wstring binaryNameW = ToWString(binaryName); + WCHAR buffer[MAX_PATH]; + if (::FindExecutableW(binaryNameW.c_str(), NULL, buffer) > (HINSTANCE)32) { + DWORD binaryType = 0UL; + if (!::GetBinaryTypeW(binaryNameW.c_str(), &binaryType)) { + qDebug("failed to determine binary type of \"%ls\": %lu", binaryNameW.c_str(), ::GetLastError()); + } else if (binaryType == SCS_32BIT_BINARY) { + binaryPath = ToQString(buffer); + } + } + } + if (binaryPath.isEmpty()) { + QSettings javaReg("HKEY_LOCAL_MACHINE\\Software\\JavaSoft\\Java Runtime Environment", QSettings::NativeFormat); + if (javaReg.contains("CurrentVersion")) { + QString currentVersion = javaReg.value("CurrentVersion").toString(); + binaryPath = javaReg.value(QString("%1/JavaHome").arg(currentVersion)).toString().append("\\bin\\javaw.exe"); + } + } + if (binaryPath.isEmpty()) { + QMessageBox::information(this, tr("Java (32-bit) required"), + tr("MO requires 32-bit java to run this application. If you already have it installed, select javaw.exe " + "from that installation as the binary.")); + } else { + ui->binaryEdit->setText(binaryPath); + } + + ui->workingDirEdit->setText(QDir::toNativeSeparators(QFileInfo(binaryName).absolutePath())); + ui->argumentsEdit->setText("-jar \"" + QDir::toNativeSeparators(binaryName) + "\""); + } else { + ui->binaryEdit->setText(QDir::toNativeSeparators(binaryName)); + } +} + +void EditExecutablesDialog::on_browseDirButton_clicked() +{ + QString dirName = FileDialogMemory::getExistingDirectory("editExecutableDirectory", this, + tr("Select a directory")); + + ui->workingDirEdit->setText(dirName); +} + +void EditExecutablesDialog::on_removeButton_clicked() +{ +// QLineEdit *binaryEdit = findChild<QLineEdit*>("binaryEdit"); + + if (QMessageBox::question(this, tr("Confirm"), tr("Really remove \"%1\" from executables?").arg(ui->titleEdit->text()), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + m_ExecutablesList.remove(ui->titleEdit->text()); + } + + resetInput(); + refreshExecutablesWidget(); +} + +void EditExecutablesDialog::on_titleEdit_textChanged(const QString &arg1) +{ + QPushButton *addButton = findChild<QPushButton*>("addButton"); + QPushButton *removeButton = findChild<QPushButton*>("removeButton"); + + QListWidget *executablesWidget = findChild<QListWidget*>("executablesListBox"); + + QList<QListWidgetItem*> existingItems = executablesWidget->findItems(arg1, Qt::MatchFixedString); + + addButton->setEnabled(arg1.length() != 0); + + if (existingItems.count() == 0) { + addButton->setText(tr("Add")); + removeButton->setEnabled(false); + } else { + // existing item. is it a custom one? + addButton->setText(tr("Modify")); + removeButton->setEnabled(true); + } +} + + +bool EditExecutablesDialog::executableChanged() +{ + if (m_CurrentItem != NULL) { + const Executable &selectedExecutable = m_CurrentItem->data(Qt::UserRole).value<Executable>(); + + return selectedExecutable.m_Arguments != ui->argumentsEdit->text() + || selectedExecutable.m_SteamAppID != ui->appIDOverwriteEdit->text() + || selectedExecutable.m_WorkingDirectory != QDir::fromNativeSeparators(ui->workingDirEdit->text()) + || selectedExecutable.m_BinaryInfo.absoluteFilePath() != QDir::fromNativeSeparators(ui->binaryEdit->text()) + || (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE) != ui->closeCheckBox->isChecked(); + } else { + return false; + } +} + + +void EditExecutablesDialog::on_executablesListBox_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) +{ + if (current == NULL) { + resetInput(); + return; + } + + if (executableChanged()) { + QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"), + tr("You made changes to the current executable, do you want to save them?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (res == QMessageBox::Cancel) { + return; + } else if (res == QMessageBox::Yes) { + // this invalidates the item passed as a a parameter + saveExecutable(); + + QTimer::singleShot(50, this, SLOT(delayedRefresh())); + return; + } + } + + m_CurrentItem = current; + + const Executable &selectedExecutable = current->data(Qt::UserRole).value<Executable>(); + + ui->titleEdit->setText(selectedExecutable.m_Title); + ui->binaryEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_BinaryInfo.absoluteFilePath())); + ui->argumentsEdit->setText(selectedExecutable.m_Arguments); + ui->workingDirEdit->setText(QDir::toNativeSeparators(selectedExecutable.m_WorkingDirectory)); + ui->closeCheckBox->setChecked(selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE); + if (selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::NEVER_CLOSE) { + ui->closeCheckBox->setEnabled(false); + ui->closeCheckBox->setToolTip(tr("MO must be kept running or this application will not work correctly.")); + } else { + ui->closeCheckBox->setEnabled(true); + ui->closeCheckBox->setToolTip(tr("If checked, MO will be closed once the specified executable is run.")); + } + ui->removeButton->setEnabled(selectedExecutable.m_Custom); + ui->overwriteAppIDBox->setChecked(selectedExecutable.m_SteamAppID != 0); + if (selectedExecutable.m_SteamAppID != 0) { + ui->appIDOverwriteEdit->setText(selectedExecutable.m_SteamAppID); + } else { + ui->appIDOverwriteEdit->clear(); + } +} + + +void EditExecutablesDialog::on_overwriteAppIDBox_toggled(bool checked) +{ + ui->appIDOverwriteEdit->setEnabled(checked); +} + +void EditExecutablesDialog::on_closeButton_clicked() +{ + if (executableChanged()) { + QMessageBox::StandardButton res = QMessageBox::question(this, tr("Save Changes?"), + tr("You made changes to the current executable, do you want to save them?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + if (res == QMessageBox::Cancel) { + return; + } else if (res == QMessageBox::Yes) { + saveExecutable(); + } + } + this->accept(); +} diff --git a/src/editexecutablesdialog.ui b/src/editexecutablesdialog.ui index 4f0462db..8e70c1c0 100644 --- a/src/editexecutablesdialog.ui +++ b/src/editexecutablesdialog.ui @@ -28,6 +28,9 @@ <property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
</widget>
</item>
<item>
diff --git a/src/executableslist.cpp b/src/executableslist.cpp index 2c6754d7..11158c5b 100644 --- a/src/executableslist.cpp +++ b/src/executableslist.cpp @@ -31,8 +31,14 @@ using namespace MOShared; QDataStream &operator<<(QDataStream &out, const Executable &obj)
{
- out << obj.m_Title << obj.m_BinaryInfo.absoluteFilePath() << obj.m_Arguments << obj.m_CloseMO
- << obj.m_SteamAppID << obj.m_WorkingDirectory << obj.m_Custom << obj.m_Toolbar;
+ out << obj.m_Title
+ << obj.m_BinaryInfo.absoluteFilePath()
+ << obj.m_Arguments
+ << static_cast<std::underlying_type<ExecutableInfo::CloseMOStyle>::type>(obj.m_CloseMO)
+ << obj.m_SteamAppID
+ << obj.m_WorkingDirectory
+ << obj.m_Custom
+ << obj.m_Toolbar;
return out;
}
@@ -43,7 +49,7 @@ QDataStream &operator>>(QDataStream &in, Executable &obj) in >> obj.m_Title >> binaryTemp >> obj.m_Arguments >> closeStyleTemp
>> obj.m_SteamAppID >> obj.m_WorkingDirectory >> obj.m_Custom >> obj.m_Toolbar;
- obj.m_CloseMO = (CloseMOStyle)closeStyleTemp;
+ obj.m_CloseMO = static_cast<ExecutableInfo::CloseMOStyle>(closeStyleTemp);
obj.m_BinaryInfo.setFile(binaryTemp);
return in;
}
@@ -64,14 +70,16 @@ ExecutablesList::~ExecutablesList() {
}
-void ExecutablesList::init()
+void ExecutablesList::init(IPluginGame *game)
{
- std::vector<ExecutableInfo> executables = GameInfo::instance().getExecutables();
- for (std::vector<ExecutableInfo>::const_iterator iter = executables.begin(); iter != executables.end(); ++iter) {
- addExecutableInternal(ToQString(iter->title),
- QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())).append("/").append(ToQString(iter->binary)),
- ToQString(iter->arguments), ToQString(iter->workingDirectory),
- iter->closeMO, ToQString(iter->steamAppID));
+ m_Executables.clear();
+ for (const ExecutableInfo &info : game->executables()) {
+ addExecutableInternal(info.title(),
+ info.binary().absoluteFilePath(),
+ info.arguments().join(" "),
+ info.workingDirectory().absolutePath(),
+ info.closeMO(),
+ info.steamAppID());
}
}
@@ -143,7 +151,7 @@ void ExecutablesList::addExecutable(const Executable &executable) void ExecutablesList::addExecutable(const QString &title, const QString &executableName, const QString &arguments,
- const QString &workingDirectory, CloseMOStyle closeMO, const QString &steamAppID,
+ const QString &workingDirectory, ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID,
bool custom, bool toolbar)
{
QFileInfo file(executableName);
@@ -185,7 +193,7 @@ void ExecutablesList::remove(const QString &title) void ExecutablesList::addExecutableInternal(const QString &title, const QString &executableName,
const QString &arguments, const QString &workingDirectory,
- CloseMOStyle closeMO, const QString &steamAppID)
+ ExecutableInfo::CloseMOStyle closeMO, const QString &steamAppID)
{
QFileInfo file(executableName);
if (file.exists()) {
diff --git a/src/executableslist.h b/src/executableslist.h index 6f7771e5..207190c4 100644 --- a/src/executableslist.h +++ b/src/executableslist.h @@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QFileInfo>
#include <QMetaType>
#include <gameinfo.h>
+#include <iplugingame.h>
/*!
@@ -34,7 +35,7 @@ struct Executable { QString m_Title;
QFileInfo m_BinaryInfo;
QString m_Arguments;
- MOShared::CloseMOStyle m_CloseMO;
+ MOBase::ExecutableInfo::CloseMOStyle m_CloseMO;
QString m_SteamAppID;
QString m_WorkingDirectory;
@@ -64,7 +65,7 @@ public: /**
* @brief initialise the list with the executables preconfigured for this game
**/
- void init();
+ void init(MOBase::IPluginGame *game);
/**
* @brief retrieve an executable by index
@@ -114,7 +115,9 @@ public: * @param arguments arguments to pass to the executable
* @param closeMO if true, MO will be closed when the binary is started
**/
- void addExecutable(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, MOShared::CloseMOStyle closeMO, const QString &steamAppID, bool custom, bool toolbar);
+ void addExecutable(const QString &title, const QString &executableName, const QString &arguments,
+ const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO,
+ const QString &steamAppID, bool custom, bool toolbar);
/**
* @brief remove the executable with the specified file name. This needs to be an absolute file path
@@ -144,7 +147,9 @@ private: Executable *findExe(const QString &title);
- void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments, const QString &workingDirectory, MOShared::CloseMOStyle closeMO, const QString &steamAppID);
+ void addExecutableInternal(const QString &title, const QString &executableName, const QString &arguments,
+ const QString &workingDirectory, MOBase::ExecutableInfo::CloseMOStyle closeMO,
+ const QString &steamAppID);
private:
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index 29914b65..0fb1b78d 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -67,9 +67,8 @@ template <typename T> T resolveFunction(QLibrary &lib, const char *name) }
-InstallationManager::InstallationManager(QWidget *parent)
- : QObject(parent), m_ParentWidget(parent),
- m_InstallationProgress(parent), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod")("001"))
+InstallationManager::InstallationManager()
+ : m_InstallationProgress(nullptr), m_SupportedExtensions(boost::assign::list_of("zip")("rar")("7z")("fomod")("001"))
{
QLibrary archiveLib("dlls\\archive.dll");
if (!archiveLib.load()) {
@@ -92,6 +91,14 @@ InstallationManager::~InstallationManager() delete m_CurrentArchive;
}
+void InstallationManager::setParentWidget(QWidget *widget)
+{
+ m_InstallationProgress.setParent(widget);
+ for (IPluginInstaller *installer : m_Installers) {
+ installer->setParentWidget(widget);
+ }
+}
+
void InstallationManager::queryPassword(LPSTR password)
{
@@ -257,7 +264,7 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::dummyProgressFile),
new MethodCallback<InstallationManager, void, LPCWSTR>(this, &InstallationManager::report7ZipError))) {
m_InstallationProgress.hide();
- throw std::runtime_error("extracting failed");
+ throw MyException(QString("extracting failed (%1)").arg(m_CurrentArchive->getLastError()));
}
m_InstallationProgress.hide();
@@ -542,7 +549,7 @@ bool InstallationManager::doInstall(GuessedValue<QString> &modName, int modID, if (m_CurrentArchive->getLastError() == Archive::ERROR_EXTRACT_CANCELLED) {
return false;
} else {
- throw std::runtime_error("extracting failed");
+ throw MyException(QString("extracting failed (%1)").arg(m_CurrentArchive->getLastError()));
}
}
diff --git a/src/installationmanager.h b/src/installationmanager.h index d430c065..cd20f0dd 100644 --- a/src/installationmanager.h +++ b/src/installationmanager.h @@ -53,9 +53,11 @@ public: *
* @param parent parent object.
**/
- explicit InstallationManager(QWidget *parent);
+ explicit InstallationManager();
- ~InstallationManager();
+ virtual ~InstallationManager();
+
+ void setParentWidget(QWidget *widget);
/**
* @brief update the directory where mods are to be installed
diff --git a/src/iuserinterface.h b/src/iuserinterface.h new file mode 100644 index 00000000..76d4c75a --- /dev/null +++ b/src/iuserinterface.h @@ -0,0 +1,39 @@ +#ifndef IUSERINTERFACE_H
+#define IUSERINTERFACE_H
+
+
+#include "modinfo.h"
+#include <iplugintool.h>
+#include <ipluginmodpage.h>
+
+
+class IUserInterface
+{
+public:
+
+ void storeSettings(QSettings &settings);
+
+ virtual HANDLE startApplication(const QString &executable, const QStringList &args = QStringList(), const QString &cwd = "", const QString &profile = "") = 0;
+
+ virtual bool waitForProcessOrJob(HANDLE processHandle, LPDWORD exitCode = NULL) = 0;
+
+ virtual void registerPluginTool(MOBase::IPluginTool *tool) = 0;
+ virtual void registerModPage(MOBase::IPluginModPage *modPage) = 0;
+
+ virtual void installTranslator(const QString &name) = 0;
+
+ virtual void disconnectPlugins() = 0;
+
+ virtual bool close() = 0;
+
+ virtual void setEnabled(bool enabled) = 0;
+
+ virtual void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab) = 0;
+
+ virtual void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives) = 0;
+
+ virtual bool saveArchiveList() = 0;
+
+};
+
+#endif // IUSERINTERFACE_H
diff --git a/src/main.cpp b/src/main.cpp index 4dbf9ff9..0e112873 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,6 +42,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <inject.h>
#include <appconfig.h>
#include <utility.h>
+#include <scopeguard.h>
#include <stdexcept>
#include "mainwindow.h"
#include "report.h"
@@ -321,6 +322,10 @@ int main(int argc, char *argv[]) );
application.setProperty("dataPath", dataPath);
+#if QT_VERSION >= 0x050000
+ qDebug("ssl support: %d", QSslSocket::supportsSsl());
+#endif
+
qDebug("data path: %s", qPrintable(dataPath));
if (!QDir(dataPath).exists()) {
if (!QDir().mkpath(dataPath)) {
@@ -329,7 +334,7 @@ int main(int argc, char *argv[]) }
}
- application.addLibraryPath(application.applicationDirPath() + "/dlls");
+ application.setLibraryPaths(QStringList() << (application.applicationDirPath() + "/dlls"));
SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
@@ -395,6 +400,11 @@ int main(int argc, char *argv[]) QSettings settings(dataPath + "/ModOrganizer.ini", QSettings::IniFormat);
+ OrganizerCore organizer(settings);
+
+ PluginContainer pluginContainer(&organizer);
+ pluginContainer.loadPlugins();
+
QString gamePath = QString::fromUtf8(settings.value("gamePath", "").toByteArray());
bool done = false;
@@ -452,14 +462,9 @@ int main(int argc, char *argv[]) settings.setValue("gamePath", gamePath.toUtf8().constData());
}
- int edition = 0;
- if (settings.contains("game_edition")) {
- edition = settings.value("game_edition").toInt();
- } else {
+ if (!settings.contains("game_edition")) {
std::vector<std::wstring> editions = GameInfo::instance().getSteamVariants();
- if (editions.size() < 2) {
- edition = 0;
- } else {
+ if (editions.size() > 1) {
SelectionDialog selection(QObject::tr("Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)"), NULL);
int index = 0;
for (auto iter = editions.begin(); iter != editions.end(); ++iter) {
@@ -472,12 +477,10 @@ int main(int argc, char *argv[]) }
}
}
-
+#pragma message("edition isn't used?")
qDebug("managing game at %s", qPrintable(QDir::toNativeSeparators(gamePath)));
- ExecutablesList executablesList;
-
- executablesList.init();
+ organizer.updateExecutablesList(settings);
if (!bootstrap()) { // requires gameinfo to be initialised!
return -1;
@@ -485,24 +488,6 @@ int main(int argc, char *argv[]) cleanupDir();
- qDebug("setting up configured executables");
-
- int numCustomExecutables = settings.beginReadArray("customExecutables");
- for (int i = 0; i < numCustomExecutables; ++i) {
- settings.setArrayIndex(i);
- CloseMOStyle closeMO = settings.value("closeOnStart").toBool() ? DEFAULT_CLOSE : DEFAULT_STAY;
- executablesList.addExecutable(settings.value("title").toString(),
- settings.value("binary").toString(),
- settings.value("arguments").toString(),
- settings.value("workingDirectory", "").toString(),
- closeMO,
- settings.value("steamAppID", "").toString(),
- settings.value("custom", true).toBool(),
- settings.value("toolbar", false).toBool());
- }
-
- settings.endArray();
-
qDebug("initializing tutorials");
TutorialManager::init(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getTutorialDir())).append("/"));
@@ -514,11 +499,11 @@ int main(int argc, char *argv[]) int res = 1;
{ // scope to control lifetime of mainwindow
// set up main window and its data structures
- MainWindow mainWindow(argv[0], settings);
+ MainWindow mainWindow(argv[0], settings, organizer, pluginContainer);
+
QObject::connect(&mainWindow, SIGNAL(styleChanged(QString)), &application, SLOT(setStyleFile(QString)));
- QObject::connect(&instance, SIGNAL(messageSent(QString)), &mainWindow, SLOT(externalMessage(QString)));
+ QObject::connect(&instance, SIGNAL(messageSent(QString)), &organizer, SLOT(externalMessage(QString)));
- mainWindow.setExecutablesList(executablesList);
mainWindow.readSettings();
QString selectedProfileName = QString::fromUtf8(settings.value("selected_profile", "").toByteArray());
@@ -573,7 +558,7 @@ int main(int argc, char *argv[]) if ((arguments.size() > 1) &&
(isNxmLink(arguments.at(1)))) {
qDebug("starting download from command line: %s", qPrintable(arguments.at(1)));
- mainWindow.externalMessage(arguments.at(1));
+ organizer.externalMessage(arguments.at(1));
}
splash.finish(&mainWindow);
res = application.exec();
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 481e3275..4762358e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -16,10 +16,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifndef Q_MOC_RUN
#include "mainwindow.h"
#include "ui_mainwindow.h"
-#include <archive.h>
#include "spawn.h"
#include "report.h"
#include "modlist.h"
@@ -61,14 +61,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "aboutdialog.h"
#include "safewritefile.h"
#include "organizerproxy.h"
+#include <archive.h>
#include <gameinfo.h>
#include <appconfig.h>
#include <utility.h>
#include <ipluginproxy.h>
#include <questionboxmemory.h>
+#include <util.h>
+#endif // Q_MOC_RUN
#include <map>
#include <ctime>
-#include <util.h>
#include <wchar.h>
#include <utility.h>
#include <QTime>
@@ -97,15 +99,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QtPlugin>
#include <QIdentityProxyModel>
#include <QClipboard>
-#include <boost/bind.hpp>
-#include <boost/foreach.hpp>
-#include <boost/assign.hpp>
#include <Psapi.h>
#include <shlobj.h>
#include <ShellAPI.h>
#include <TlHelp32.h>
#include <QNetworkInterface>
#include <QNetworkProxy>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonValue>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtConcurrent/QtConcurrentRun>
#else
@@ -114,9 +117,15 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QCoreApplication>
#include <QProgressDialog>
#include <scopeguard.h>
+#ifndef Q_MOC_RUN
#include <boost/thread.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/assign.hpp>
+#endif
#include <regex>
+#include <functional>
#ifdef TEST_MODELS
#include "modeltest.h"
@@ -130,46 +139,28 @@ using namespace MOShared; -static bool isOnline()
-{
- QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
-
- bool connected = false;
- for (auto iter = interfaces.begin(); iter != interfaces.end() && !connected; ++iter) {
- if ( (iter->flags() & QNetworkInterface::IsUp) &&
- (iter->flags() & QNetworkInterface::IsRunning) &&
- !(iter->flags() & QNetworkInterface::IsLoopBack)) {
- auto addresses = iter->addressEntries();
- if (addresses.count() == 0) {
- continue;
- }
- qDebug("interface %s seems to be up (address: %s)",
- qPrintable(iter->humanReadableName()),
- qPrintable(addresses[0].ip().toString()));
- connected = true;
- }
- }
-
- return connected;
-}
-
-
-MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent)
- : QMainWindow(parent), ui(new Ui::MainWindow), m_Tutorial(this, "MainWindow"),
- m_ExeName(exeName), m_OldProfileIndex(-1),
- m_DirectoryStructure(new DirectoryEntry(L"data", NULL, 0)),
- m_ModList(this), m_ModListGroupingProxy(NULL), m_ModListSortProxy(NULL),
- m_PluginList(this), m_OldExecutableIndex(-1), m_GamePath(ToQString(GameInfo::instance().getGameDirectory())),
- m_DownloadManager(NexusInterface::instance(), this), m_InstallationManager(this),
- m_Updater(NexusInterface::instance(), this), m_CategoryFactory(CategoryFactory::instance()),
- m_CurrentProfile(NULL), m_AskForNexusPW(false),
- m_ArchivesInit(false), m_DirectoryUpdate(false), m_ContextItem(NULL), m_ContextAction(NULL), m_CurrentSaveView(NULL),
- m_GameInfo(new GameInfoImpl()), m_AboutToRun(), m_ModInstalled(), m_DidUpdateMasterList(false)
+MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, OrganizerCore &organizerCore, PluginContainer &pluginContainer, QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+ , m_Tutorial(this, "MainWindow")
+ , m_ExeName(exeName)
+ , m_OldProfileIndex(-1)
+ , m_ModListGroupingProxy(nullptr)
+ , m_ModListSortProxy(nullptr)
+ , m_OldExecutableIndex(-1)
+ , m_GamePath(ToQString(GameInfo::instance().getGameDirectory()))
+ , m_CategoryFactory(CategoryFactory::instance())
+ , m_ContextItem(nullptr)
+ , m_ContextAction(nullptr)
+ , m_CurrentSaveView(nullptr)
+ , m_OrganizerCore(organizerCore)
+ , m_PluginContainer(pluginContainer)
+ , m_DidUpdateMasterList(false)
{
ui->setupUi(this);
- this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_Updater.getVersion().displayString());
+ this->setWindowTitle(ToQString(GameInfo::instance().getGameName()) + " Mod Organizer v" + m_OrganizerCore.getVersion().displayString());
- languageChange(m_Settings.language());
+ languageChange(m_OrganizerCore.settings().language());
ui->logList->setModel(LogBuffer::instance());
ui->logList->setColumnWidth(0, 100);
@@ -196,16 +187,8 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget updateToolBar();
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
-
// set up mod list
- m_ModListSortProxy = new ModListSortProxy(m_CurrentProfile, this);
- m_ModListSortProxy->setSourceModel(&m_ModList);
-
-#ifdef TEST_MODELS
- new ModelTest(&m_ModList, this);
- new ModelTest(m_ModListSortProxy, this);
-#endif //TEST_MODELS
+ m_ModListSortProxy = m_OrganizerCore.createModListProxyModel();
ui->modList->setModel(m_ModListSortProxy);
@@ -215,7 +198,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->modList->setItemDelegateForColumn(ModList::COL_FLAGS, new ModFlagIconDelegate(ui->modList));
ui->modList->setItemDelegateForColumn(ModList::COL_CONTENT, contentDelegate);
//ui->modList->setAcceptDrops(true);
- ui->modList->header()->installEventFilter(&m_ModList);
+ ui->modList->header()->installEventFilter(m_OrganizerCore.modList());
if (initSettings.contains("mod_list_state")) {
ui->modList->header()->restoreState(initSettings.value("mod_list_state").toByteArray());
@@ -230,11 +213,10 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget }
ui->modList->header()->setSectionHidden(ModList::COL_NAME, false); // prevent the name-column from being hidden
- ui->modList->installEventFilter(&m_ModList);
+ ui->modList->installEventFilter(m_OrganizerCore.modList());
// set up plugin list
- m_PluginListSortProxy = new PluginListSortProxy(this);
- m_PluginListSortProxy->setSourceModel(&m_PluginList);
+ m_PluginListSortProxy = m_OrganizerCore.createPluginListProxyModel();
ui->espList->setModel(m_PluginListSortProxy);
ui->espList->sortByColumn(PluginList::COL_PRIORITY, Qt::AscendingOrder);
@@ -242,7 +224,7 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget if (initSettings.contains("plugin_list_state")) {
ui->espList->header()->restoreState(initSettings.value("plugin_list_state").toByteArray());
}
- ui->espList->installEventFilter(&m_PluginList);
+ ui->espList->installEventFilter(m_OrganizerCore.pluginList());
ui->bsaList->setLocalMoveOnly(true);
@@ -259,72 +241,50 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget ui->listOptionsBtn->setMenu(modListContextMenu());
- m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory());
- m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
-
- NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory());
- NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion());
-
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory());
-
updateDownloadListDelegate();
ui->savegameList->installEventFilter(this);
ui->savegameList->setMouseTracking(true);
- connect(&m_DownloadManager, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString)));
- connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int)));
- connect(&m_DownloadManager, SIGNAL(downloadAdded()), ui->downloadView, SLOT(scrollToBottom()));
connect(ui->savegameList, SIGNAL(itemEntered(QListWidgetItem*)), this, SLOT(saveSelectionChanged(QListWidgetItem*)));
- connect(&m_ModList, SIGNAL(modorder_changed()), this, SLOT(modorder_changed()));
- connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString)));
- connect(&m_ModList, SIGNAL(showMessage(QString)), this, SLOT(showMessage(QString)));
- connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), this, SLOT(modRenamed(QString,QString)));
- connect(&m_ModList, SIGNAL(modUninstalled(QString)), this, SLOT(modRemoved(QString)));
- connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), this, SLOT(modlistChanged(QModelIndex, int)));
- connect(&m_ModList, SIGNAL(removeSelectedMods()), this, SLOT(removeMod_clicked()));
- connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), this, SLOT(displayColumnSelection(QPoint)));
- connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), this, SLOT(fileMoved(QString, QString, QString)));
- connect(ui->modList, SIGNAL(dropModeUpdate(bool)), &m_ModList, SLOT(dropModeUpdate(bool)));
+ connect(ui->modList, SIGNAL(dropModeUpdate(bool)), m_OrganizerCore.modList(), SLOT(dropModeUpdate(bool)));
connect(ui->modList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(modlistSelectionChanged(QModelIndex,QModelIndex)));
connect(m_ModListSortProxy, SIGNAL(filterActive(bool)), this, SLOT(modFilterActive(bool)));
connect(ui->modFilterEdit, SIGNAL(textChanged(QString)), m_ModListSortProxy, SLOT(updateFilter(QString)));
connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), m_PluginListSortProxy, SLOT(updateFilter(QString)));
connect(ui->espFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(espFilterChanged(QString)));
- connect(&m_PluginList, SIGNAL(saveTimer()), this, SLOT(savePluginList()));
+ connect(m_OrganizerCore.pluginList(), SIGNAL(saveTimer()), this, SLOT(savePluginList()));
connect(ui->bsaList, SIGNAL(itemsMoved()), this, SLOT(bsaList_itemMoved()));
connect(ui->dataTree, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(expandDataTreeItem(QTreeWidgetItem*)));
- connect(&m_DirectoryRefresher, SIGNAL(refreshed()), this, SLOT(directory_refreshed()));
- connect(&m_DirectoryRefresher, SIGNAL(progress(int)), this, SLOT(refresher_progress(int)));
- connect(&m_DirectoryRefresher, SIGNAL(error(QString)), this, SLOT(showError(QString)));
+ connect(m_OrganizerCore.directoryRefresher(), SIGNAL(refreshed()), this, SLOT(directory_refreshed()));
+ connect(m_OrganizerCore.directoryRefresher(), SIGNAL(progress(int)), this, SLOT(refresher_progress(int)));
+ connect(m_OrganizerCore.directoryRefresher(), SIGNAL(error(QString)), this, SLOT(showError(QString)));
connect(&m_SavesWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(refreshSavesIfOpen()));
- connect(&m_Settings, SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString)));
- connect(&m_Settings, SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString)));
-
- connect(&m_Updater, SIGNAL(restart()), this, SLOT(close()));
- connect(&m_Updater, SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
- connect(&m_Updater, SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
+ connect(&m_OrganizerCore.settings(), SIGNAL(languageChanged(QString)), this, SLOT(languageChange(QString)));
+ connect(&m_OrganizerCore.settings(), SIGNAL(styleChanged(QString)), this, SIGNAL(styleChanged(QString)));
-// connect(ExitProxy::instance(), SIGNAL(exit()), this, SLOT(close()));
+ connect(m_OrganizerCore.updater(), SIGNAL(restart()), this, SLOT(close()));
+ connect(m_OrganizerCore.updater(), SIGNAL(updateAvailable()), this, SLOT(updateAvailable()));
+ connect(m_OrganizerCore.updater(), SIGNAL(motdAvailable(QString)), this, SLOT(motdReceived(QString)));
- connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
- connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
connect(NexusInterface::instance(), SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString)));
connect(NexusInterface::instance(), SIGNAL(nxmDownloadURLsAvailable(int,int,QVariant,QVariant,int)), this, SLOT(nxmDownloadURLs(int,int,QVariant,QVariant,int)));
connect(NexusInterface::instance(), SIGNAL(needLogin()), this, SLOT(nexusLogin()));
+ connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
connect(&TutorialManager::instance(), SIGNAL(windowTutorialFinished(QString)), this, SLOT(windowTutorialFinished(QString)));
connect(ui->modList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(modListSortIndicatorChanged(int,Qt::SortOrder)));
connect(ui->toolBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(toolBar_customContextMenuRequested(QPoint)));
+ connect(&m_OrganizerCore, &OrganizerCore::modInstalled, this, &MainWindow::modInstalled);
+
connect(&m_IntegratedBrowser, SIGNAL(requestDownload(QUrl,QNetworkReply*)), this, SLOT(requestDownload(QUrl,QNetworkReply*)));
connect(this, SIGNAL(styleChanged(QString)), this, SLOT(updateStyle(QString)));
@@ -339,40 +299,44 @@ MainWindow::MainWindow(const QString &exeName, QSettings &initSettings, QWidget connect(&m_SaveMetaTimer, SIGNAL(timeout()), this, SLOT(saveModMetas()));
m_SaveMetaTimer.start(5000);
- m_DirectoryRefresher.moveToThread(&m_RefresherThread);
- m_RefresherThread.start();
-
- m_AskForNexusPW = initSettings.value("ask_for_nexuspw", true).toBool();
setCategoryListVisible(initSettings.value("categorylist_visible", true).toBool());
FileDialogMemory::restore(initSettings);
fixCategories();
- if (isOnline() && !m_Settings.offlineMode()) {
- m_Updater.testForUpdate();
- } else {
- qDebug("user doesn't seem to be connected to the internet");
- }
-
m_StartTime = QTime::currentTime();
- m_Tutorial.expose("modList", &m_ModList);
- m_Tutorial.expose("espList", &m_PluginList);
+ m_Tutorial.expose("modList", m_OrganizerCore.modList());
+ m_Tutorial.expose("espList", m_OrganizerCore.pluginList());
// before we start loading plugins we, add the dll path to the dll search order
::SetDllDirectoryW(ToWString(QDir::toNativeSeparators(qApp->applicationDirPath() + "/dlls")).c_str());
- loadPlugins();
+
+ m_OrganizerCore.setUserInterface(this, this);
+
+ for (const QString &fileName : m_PluginContainer.pluginFileNames()) {
+ installTranslator(QFileInfo(fileName).baseName());
+ }
+
+ refreshExecutablesList();
+ updateToolBar();
}
MainWindow::~MainWindow()
{
- m_RefresherThread.exit();
- m_RefresherThread.wait();
+ m_PluginContainer.setUserInterface(nullptr, nullptr);
+ m_OrganizerCore.setUserInterface(nullptr, nullptr);
m_IntegratedBrowser.close();
delete ui;
- delete m_GameInfo;
- delete m_DirectoryStructure;
+}
+
+
+void MainWindow::disconnectPlugins()
+{
+ if (ui->actionTool->menu() != NULL) {
+ ui->actionTool->menu()->clear();
+ }
}
@@ -393,6 +357,13 @@ void MainWindow::resizeLists(bool modListCustom, bool pluginListCustom) #endif
}
+ // ensure the columns aren't so small you can't see them any more
+ for (int i = 0; i < ui->modList->header()->count(); ++i) {
+ if (ui->modList->header()->sectionSize(i) < 10) {
+ ui->modList->header()->resizeSection(i, 10);
+ }
+ }
+
if (!pluginListCustom) {
// resize plugin list to fit content
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
@@ -524,7 +495,7 @@ void MainWindow::updateToolBar() ui->toolBar->insertWidget(action, spacer);
std::vector<Executable>::iterator begin, end;
- m_ExecutablesList.getExecutables(begin, end);
+ m_OrganizerCore.executablesList()->getExecutables(begin, end);
for (auto iter = begin; iter != end; ++iter) {
if (iter->m_Toolbar) {
QAction *exeAction = new QAction(iconForExecutable(iter->m_BinaryInfo.filePath()),
@@ -610,7 +581,7 @@ bool MainWindow::errorReported(QString &logFile) int MainWindow::checkForProblems()
{
int numProblems = 0;
- foreach (IPluginDiagnose *diagnose, m_DiagnosisPlugins) {
+ for (IPluginDiagnose *diagnose : m_PluginContainer.plugins<IPluginDiagnose>()) {
numProblems += diagnose->activeProblems().size();
}
return numProblems;
@@ -618,7 +589,7 @@ int MainWindow::checkForProblems() void MainWindow::about()
{
- AboutDialog dialog(m_Updater.getVersion().displayString(), this);
+ AboutDialog dialog(m_OrganizerCore.getVersion().displayString(), this);
dialog.exec();
}
@@ -688,47 +659,10 @@ void MainWindow::createHelpWidget() }
-bool MainWindow::saveArchiveList()
-{
- if (m_ArchivesInit) {
- SafeWriteFile archiveFile(m_CurrentProfile->getArchivesFileName());
- for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
- QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i);
- for (int j = 0; j < tlItem->childCount(); ++j) {
- QTreeWidgetItem *item = tlItem->child(j);
- if (item->checkState(0) == Qt::Checked) {
- // in managed mode, "register" all enabled archives, otherwise register only the files registered in the ini
- if (ui->manageArchivesBox->isChecked()
- || item->data(0, Qt::UserRole).toBool()) {
- archiveFile->write(item->text(0).toUtf8().append("\r\n"));
- }
- }
- }
- }
- if (archiveFile.commitIfDifferent(m_ArchiveListHash)) {
- qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName())));
- return true;
- }
- } else {
- qWarning("archive list not initialised");
- }
- return false;
-}
-
-void MainWindow::savePluginList()
-{
- m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(),
- m_CurrentProfile->getLoadOrderFileName(),
- m_CurrentProfile->getLockedOrderFileName(),
- m_CurrentProfile->getDeleterFileName(),
- m_Settings.hideUncheckedPlugins());
- m_PluginList.saveLoadOrder(*m_DirectoryStructure);
-}
-
void MainWindow::modFilterActive(bool filterActive)
{
if (filterActive) {
- m_ModList.setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
+ m_OrganizerCore.modList()->setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
ui->modList->setStyleSheet("QTreeView { border: 2px ridge #f00; }");
} else if (ui->groupCombo->currentIndex() != 0) {
ui->modList->setStyleSheet("QTreeView { border: 2px ridge #337733; }");
@@ -768,22 +702,6 @@ void MainWindow::expandModList(const QModelIndex &index) }
}
-bool MainWindow::saveCurrentLists()
-{
- if (m_DirectoryUpdate) {
- qWarning("not saving lists during directory update");
- return false;
- }
-
- try {
- savePluginList();
- saveArchiveList();
- } catch (const std::exception &e) {
- reportError(tr("failed to save load order: %1").arg(e.what()));
- }
-
- return true;
-}
bool MainWindow::addProfile()
{
@@ -821,7 +739,7 @@ void MainWindow::hookUpWindowTutorials() QString firstLine = QString::fromUtf8(file.readLine());
if (firstLine.startsWith("//WIN")) {
QString windowName = firstLine.mid(6).trimmed();
- if (!m_Settings.directInterface().value("CompletedWindowTutorials/" + windowName, false).toBool()) {
+ if (!m_OrganizerCore.settings().directInterface().value("CompletedWindowTutorials/" + windowName, false).toBool()) {
TutorialManager::instance().activateTutorial(windowName, fileName);
}
}
@@ -837,7 +755,7 @@ void MainWindow::showEvent(QShowEvent *event) hookUpWindowTutorials();
- if (m_Settings.directInterface().value("first_start", true).toBool()) {
+ if (m_OrganizerCore.settings().directInterface().value("first_start", true).toBool()) {
QString firstStepsTutorial = ToQString(AppConfig::firstStepsTutorial());
if (TutorialManager::instance().hasTutorial(firstStepsTutorial)) {
if (QMessageBox::question(this, tr("Show tutorial?"),
@@ -856,45 +774,35 @@ void MainWindow::showEvent(QShowEvent *event) QObject::tr("Please use \"Help\" from the toolbar to get usage instructions to all elements"));
}
- m_Settings.directInterface().setValue("first_start", false);
+ m_OrganizerCore.settings().directInterface().setValue("first_start", false);
}
// this has no visible impact when called before the ui is visible
- int grouping = m_Settings.directInterface().value("group_state").toInt();
+ int grouping = m_OrganizerCore.settings().directInterface().value("group_state").toInt();
ui->groupCombo->setCurrentIndex(grouping);
allowListResize();
- m_Settings.registerAsNXMHandler(false);
+ m_OrganizerCore.settings().registerAsNXMHandler(false);
}
void MainWindow::closeEvent(QCloseEvent* event)
{
- if (m_DownloadManager.downloadsInProgress()) {
+ if (m_OrganizerCore.downloadManager()->downloadsInProgress()) {
if (QMessageBox::question(this, tr("Downloads in progress"),
tr("There are still downloads in progress, do you really want to quit?"),
QMessageBox::Yes | QMessageBox::Cancel) == QMessageBox::Cancel) {
event->ignore();
return;
} else {
- m_DownloadManager.pauseAll();
+ m_OrganizerCore.downloadManager()->pauseAll();
}
}
setCursor(Qt::WaitCursor);
m_IntegratedBrowser.close();
-
- storeSettings();
-
- // profile has to be cleaned up before the modinfo-buffer is cleared
- delete m_CurrentProfile;
- m_CurrentProfile = NULL;
-
- ModInfo::clear();
- LogBuffer::cleanQuit();
- m_ModList.setProfile(NULL);
}
@@ -936,7 +844,7 @@ SaveGameGamebryo *MainWindow::getSaveGame(QListWidgetItem *item) void MainWindow::displaySaveGameInfo(const SaveGameGamebryo *save, QPoint pos)
{
if (m_CurrentSaveView == NULL) {
- m_CurrentSaveView = new SaveGameInfoWidgetGamebryo(save, &m_PluginList, this);
+ m_CurrentSaveView = new SaveGameInfoWidgetGamebryo(save, m_OrganizerCore.pluginList(), this);
} else {
m_CurrentSaveView->setSave(save);
}
@@ -996,53 +904,6 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) }
-bool MainWindow::testForSteam()
-{
- DWORD processIDs[1024];
- DWORD bytesReturned;
- if (!::EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned)) {
- qWarning("failed to determine if steam is running");
- return true;
- }
-
- TCHAR processName[MAX_PATH];
- for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) {
- memset(processName, '\0', sizeof(TCHAR) * MAX_PATH);
- if (processIDs[i] != 0) {
- HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
-
- if (process != NULL) {
- HMODULE module;
- DWORD ignore;
-
- // first module in a process is always the binary
- if (EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
- GetModuleBaseName(process, module, processName, MAX_PATH);
- if ((_tcsicmp(processName, TEXT("steam.exe")) == 0) ||
- (_tcsicmp(processName, TEXT("steamservice.exe")) == 0)) {
- return true;
- }
- }
- }
- }
- }
-
- return false;
-}
-
-
-bool MainWindow::verifyPlugin(IPlugin *plugin)
-{
- if (plugin == NULL) {
- return false;
- } else if (!plugin->init(new OrganizerProxy(this, plugin->name()))) {
- qWarning("plugin failed to initialize");
- return false;
- }
- return true;
-}
-
-
void MainWindow::toolPluginInvoke()
{
QAction *triggeredAction = qobject_cast<QAction*>(sender());
@@ -1057,55 +918,6 @@ void MainWindow::toolPluginInvoke() }
-void MainWindow::requestDownload(const QUrl &url, QNetworkReply *reply)
-{
- QToolButton *browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
- if (browserBtn->menu() != NULL) {
- // go through modpage plugins, find one to handle the download.
- QList<QAction*> browserActions = browserBtn->menu()->actions();
- foreach (QAction *action, browserActions) {
- // the nexus action doesn't have a plugin connected currently
- if (action->data().isValid()) {
- IPluginModPage *plugin = qobject_cast<IPluginModPage*>(qvariant_cast<QObject*>(action->data()));
- if (plugin == NULL) {
- qCritical("invalid mod page. This is a bug");
- continue;
- }
- ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
- if (plugin->handlesDownload(url, reply->url(), *fileInfo)) {
- fileInfo->repository = plugin->name();
- m_DownloadManager.addDownload(reply, fileInfo);
- return;
- }
- }
- }
- }
-
- // no mod found that could handle the download. Is it a nexus mod?
- if (url.host() == "www.nexusmods.com") {
- int modID = 0;
- int fileID = 0;
- QRegExp modExp("mods/(\\d+)");
- if (modExp.indexIn(url.toString()) != -1) {
- modID = modExp.cap(1).toInt();
- }
- QRegExp fileExp("fid=(\\d+)");
- if (fileExp.indexIn(reply->url().toString()) != -1) {
- fileID = fileExp.cap(1).toInt();
- }
- m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID));
- } else {
- if (QMessageBox::question(this, tr("Download?"),
- tr("A download has been started but no installed page plugin recognizes it.\n"
- "If you download anyway no information (i.e. version) will be associated with the download.\n"
- "Continue?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
- }
- }
-}
-
-
void MainWindow::modPagePluginInvoke()
{
QAction *triggeredAction = qobject_cast<QAction*>(sender());
@@ -1118,6 +930,7 @@ void MainWindow::modPagePluginInvoke() }
}
+
void MainWindow::registerPluginTool(IPluginTool *tool)
{
QAction *action = new QAction(tool->icon(), tool->displayName(), ui->toolBar);
@@ -1132,7 +945,6 @@ void MainWindow::registerPluginTool(IPluginTool *tool) void MainWindow::registerModPage(IPluginModPage *modPage)
{
- QToolButton *browserBtn = NULL;
// turn the browser action into a drop-down menu if necessary
if (ui->actionNexus->menu() == NULL) {
QAction *nexusAction = ui->actionNexus;
@@ -1142,10 +954,8 @@ void MainWindow::registerModPage(IPluginModPage *modPage) ui->toolBar->removeAction(nexusAction);
actionToToolButton(ui->actionNexus);
- browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
+ QToolButton *browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
browserBtn->menu()->addAction(nexusAction);
- } else {
- browserBtn = qobject_cast<QToolButton*>(ui->toolBar->widgetForAction(ui->actionNexus));
}
QAction *action = new QAction(modPage->icon(), modPage->displayName(), ui->toolBar);
@@ -1158,309 +968,24 @@ void MainWindow::registerModPage(IPluginModPage *modPage) }
-bool MainWindow::registerPlugin(QObject *plugin, const QString &fileName)
-{
- { // generic treatment for all plugins
- IPlugin *pluginObj = qobject_cast<IPlugin*>(plugin);
- if (pluginObj == NULL) {
- qDebug("not an IPlugin");
- return false;
- }
- plugin->setProperty("filename", fileName);
- m_Settings.registerPlugin(pluginObj);
- installTranslator(QFileInfo(fileName).baseName());
- }
-
- { // diagnosis plugins
- IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
- if (diagnose != NULL) {
- m_DiagnosisPlugins.push_back(diagnose);
- diagnose->onInvalidated([&] () { this->scheduleUpdateButton(); });
- }
- }
- { // mod page plugin
- IPluginModPage *modPage = qobject_cast<IPluginModPage*>(plugin);
- if (verifyPlugin(modPage)) {
- registerModPage(modPage);
- return true;
- }
- }
- { // tool plugins
- IPluginTool *tool = qobject_cast<IPluginTool*>(plugin);
- if (verifyPlugin(tool)) {
- registerPluginTool(tool);
- return true;
- }
- }
- { // installer plugins
- IPluginInstaller *installer = qobject_cast<IPluginInstaller*>(plugin);
- if (verifyPlugin(installer)) {
- installer->setParentWidget(this);
- m_InstallationManager.registerInstaller(installer);
- return true;
- }
- }
- { // preview plugins
- IPluginPreview *preview = qobject_cast<IPluginPreview*>(plugin);
- if (verifyPlugin(preview)) {
- m_PreviewGenerator.registerPlugin(preview);
- }
- }
- { // proxy plugins
- IPluginProxy *proxy = qobject_cast<IPluginProxy*>(plugin);
- if (verifyPlugin(proxy)) {
- proxy->setParentWidget(this);
- QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
- foreach (const QString &pluginName, pluginNames) {
- try {
- QObject *proxiedPlugin = proxy->instantiate(pluginName);
- if (proxiedPlugin != NULL) {
- if (registerPlugin(proxiedPlugin, pluginName)) {
- qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
- } else {
- qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
- }
- }
- } catch (const std::exception &e) {
- reportError(tr("failed to init plugin %1: %2").arg(pluginName).arg(e.what()));
- }
- }
- return true;
- }
- }
-
- { // dummy plugins
- // only initialize these, no processing otherwise
- IPlugin *dummy = qobject_cast<IPlugin*>(plugin);
- if (verifyPlugin(dummy)) {
- return true;
- }
- }
-
- qDebug("no matching plugin interface");
-
- return false;
-}
-
-
-void MainWindow::loadPlugins()
-{
- m_DiagnosisPlugins.clear();
-
- m_Settings.clearPlugins();
-
- foreach (QObject *plugin, QPluginLoader::staticInstances()) {
- registerPlugin(plugin, "");
- }
-
- QFile loadCheck(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp");
- if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
- // oh, there was a failed plugin load last time. Find out which plugin was loaded last
- QString fileName;
- while (!loadCheck.atEnd()) {
- fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
- }
- if (QMessageBox::question(this, tr("Plugin error"),
- tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
- "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
- "The plugin may be able to recover from the problem)").arg(fileName),
- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
- m_Settings.addBlacklistPlugin(fileName);
- }
- loadCheck.close();
- }
-
- loadCheck.open(QIODevice::WriteOnly);
-
- QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
- qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
- QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
-
- while (iter.hasNext()) {
- iter.next();
- if (m_Settings.pluginBlacklisted(iter.fileName())) {
- qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName()));
- continue;
- }
- loadCheck.write(iter.fileName().toUtf8());
- loadCheck.write("\n");
- loadCheck.flush();
- QString pluginName = iter.filePath();
- if (QLibrary::isLibrary(pluginName)) {
- QPluginLoader pluginLoader(pluginName);
- if (pluginLoader.instance() == NULL) {
- m_UnloadedPlugins.push_back(pluginName);
- qCritical("failed to load plugin %s: %s",
- qPrintable(pluginName), qPrintable(pluginLoader.errorString()));
- } else {
- if (registerPlugin(pluginLoader.instance(), pluginName)) {
- qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
- } else {
- m_UnloadedPlugins.push_back(pluginName);
- qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
- }
- }
- }
- }
-
- // remove the load check file on success
- loadCheck.remove();
-
- m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions());
-
- m_DiagnosisPlugins.push_back(this);
-}
-
-
-void MainWindow::startSteam()
-{
- QSettings steamSettings("HKEY_CURRENT_USER\\Software\\Valve\\Steam",
- QSettings::NativeFormat);
- QString exe = steamSettings.value("SteamExe", "").toString();
- if (!exe.isEmpty()) {
- QString temp = QString("\"%1\"").arg(exe);
- if (!QProcess::startDetached(temp)) {
- reportError(tr("Failed to start \"%1\"").arg(temp));
- } else {
- QMessageBox::information(this, tr("Waiting"), tr("Please press OK once you're logged into steam."));
- }
- }
-}
-
-
-HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName,
- const QDir ¤tDirectory, const QString &steamAppID)
-{
- storeSettings();
-
- if (!binary.exists()) {
- reportError(tr("Executable \"%1\" not found").arg(binary.fileName()));
- return INVALID_HANDLE_VALUE;
- }
-
- if (!steamAppID.isEmpty()) {
- ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(steamAppID).c_str());
- } else {
- ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(m_Settings.getSteamAppID()).c_str());
- }
-
- if ((GameInfo::instance().requiresSteam()) &&
- (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) {
- if (!testForSteam()) {
- if (QuestionBoxMemory::query(this->isVisible() ? this : NULL,
- "steamQuery", tr("Start Steam?"),
- tr("Steam is required to be running already to correctly start the game. "
- "Should MO try to start steam now?"),
- QDialogButtonBox::Yes | QDialogButtonBox::No) == QDialogButtonBox::Yes) {
- startSteam();
- }
- }
- }
-
- while (m_DirectoryUpdate) {
- ::Sleep(100);
- QCoreApplication::processEvents();
- }
-
- // need to make sure all data is saved before we start the application
- if (m_CurrentProfile != nullptr) {
- m_CurrentProfile->writeModlistNow(true);
- }
-
- // TODO: should also pass arguments
- if (m_AboutToRun(binary.absoluteFilePath())) {
- return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true);
- } else {
- qDebug("start of \"%s\" canceled by plugin", qPrintable(binary.absoluteFilePath()));
- return INVALID_HANDLE_VALUE;
- }
-}
-
-
-void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID)
-{
- LockedDialog *dialog = new LockedDialog(this);
- dialog->show();
- ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); });
-
- HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID);
- if (processHandle != INVALID_HANDLE_VALUE) {
- if (closeAfterStart) {
- close();
- } else {
- this->setEnabled(false);
- // re-enable the locked dialog because what'd be the point otherwise?
- dialog->setEnabled(true);
-
- QCoreApplication::processEvents();
-
- DWORD retLen;
- JOBOBJECT_BASIC_PROCESS_ID_LIST info;
-
- bool isJobHandle = true;
-
- DWORD res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
- while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
- if (isJobHandle) {
- if (::QueryInformationJobObject(processHandle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
- if (info.NumberOfProcessIdsInList == 0) {
- break;
- }
- } else {
- // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
- // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
- // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
- // the right to break out.
- if (::GetLastError() != ERROR_MORE_DATA) {
- isJobHandle = false;
- }
- }
- }
-
- // keep processing events so the app doesn't appear dead
- QCoreApplication::processEvents();
-
- res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
- }
- ::CloseHandle(processHandle);
-
- this->setEnabled(true);
- refreshDirectoryStructure();
- // need to remove our stored load order because it may be outdated if a foreign tool changed the
- // file time. After removing that file, refreshESPList will use the file time as the order
- if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
- QFile::remove(m_CurrentProfile->getLoadOrderFileName());
- refreshESPList();
- }
- }
- }
-}
-
-
void MainWindow::startExeAction()
{
QAction *action = qobject_cast<QAction*>(sender());
if (action != NULL) {
Executable selectedExecutable = action->data().value<Executable>();
- spawnBinary(selectedExecutable.m_BinaryInfo,
- selectedExecutable.m_Arguments,
- selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory
- : selectedExecutable.m_BinaryInfo.absolutePath(),
- selectedExecutable.m_CloseMO == DEFAULT_CLOSE,
- selectedExecutable.m_SteamAppID);
+ m_OrganizerCore.spawnBinary(
+ selectedExecutable.m_BinaryInfo,
+ selectedExecutable.m_Arguments,
+ selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory
+ : selectedExecutable.m_BinaryInfo.absolutePath(),
+ selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE,
+ selectedExecutable.m_SteamAppID);
} else {
qCritical("not an action?");
}
}
-void MainWindow::setExecutablesList(const ExecutablesList &executablesList)
-{
- m_ExecutablesList = executablesList;
- refreshExecutablesList();
- updateToolBar();
-}
-
void MainWindow::setExecutableIndex(int index)
{
QComboBox *executableBox = findChild<QComboBox*>("executablesListBox");
@@ -1478,13 +1003,11 @@ void MainWindow::activateSelectedProfile() qDebug("activate profile \"%s\"", qPrintable(profileName));
QString profileDir = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir()))
.append("/").append(profileName);
- delete m_CurrentProfile;
- m_CurrentProfile = new Profile(QDir(profileDir));
- m_ModList.setProfile(m_CurrentProfile);
+ m_OrganizerCore.setCurrentProfile(new Profile(QDir(profileDir)));
- m_ModListSortProxy->setProfile(m_CurrentProfile);
+ m_ModListSortProxy->setProfile(m_OrganizerCore.currentProfile());
- connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint)));
+ connect(m_OrganizerCore.currentProfile(), SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint)));
refreshSaveList();
refreshModList();
@@ -1497,9 +1020,9 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) m_OldProfileIndex = index;
if ((previousIndex != -1) &&
- (m_CurrentProfile != NULL) &&
- m_CurrentProfile->exists()) {
- saveCurrentLists();
+ (m_OrganizerCore.currentProfile() != NULL) &&
+ m_OrganizerCore.currentProfile()->exists()) {
+ m_OrganizerCore.saveCurrentLists();
}
// ensure the new index is valid
@@ -1520,7 +1043,6 @@ void MainWindow::on_profileBox_currentIndexChanged(int index) }
}
-
void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &directorySoFar, const DirectoryEntry &directoryEntry, bool conflictsOnly)
{
{
@@ -1535,7 +1057,7 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director QStringList columns(fileName);
bool isArchive = false;
int originID = current->getOrigin(isArchive);
- FilesOrigin origin = m_DirectoryStructure->getOriginByID(originID);
+ FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID);
QString source("data");
unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName()));
if (modIndex != UINT_MAX) {
@@ -1575,7 +1097,7 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director if (altIter != alternatives.begin()) {
altString << " , ";
}
- altString << "<span style=\"white-space: nowrap;\"><i>" << m_DirectoryStructure->getOriginByID(*altIter).getName() << "</font></span>";
+ altString << "<span style=\"white-space: nowrap;\"><i>" << m_OrganizerCore.directoryStructure()->getOriginByID(*altIter).getName() << "</font></span>";
}
fileChild->setToolTip(1, QString("%1").arg(ToQString(altString.str())));
fileChild->setForeground(1, QBrush(Qt::red));
@@ -1636,7 +1158,7 @@ void MainWindow::expandDataTreeItem(QTreeWidgetItem *item) bool conflictsOnly = onDemandDataItem->data(0, Qt::UserRole + 2).toBool();
std::wstring virtualPath = (path + L"\\").substr(6) + ToWString(item->text(0));
- DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(virtualPath);
+ DirectoryEntry *dir = m_OrganizerCore.directoryStructure()->findSubDirectoryRecursive(virtualPath);
if (dir != NULL) {
updateTo(item, path, *dir, conflictsOnly);
} else {
@@ -1699,31 +1221,6 @@ bool MainWindow::refreshProfiles(bool selectProfile) }
}
-std::set<QString> MainWindow::enabledArchives()
-{
- std::set<QString> result;
- QFile archiveFile(m_CurrentProfile->getArchivesFileName());
- if (archiveFile.open(QIODevice::ReadOnly)) {
- while (!archiveFile.atEnd()) {
- result.insert(QString::fromUtf8(archiveFile.readLine()).trimmed());
- }
- archiveFile.close();
- }
- return result;
-}
-
-void MainWindow::refreshDirectoryStructure()
-{
- m_DirectoryUpdate = true;
- std::vector<std::tuple<QString, QString, int> > activeModList = m_CurrentProfile->getActiveMods();
-
- m_DirectoryRefresher.setMods(activeModList, enabledArchives());
-
- statusBar()->show();
- m_RefreshProgress->setRange(0, 100);
-
- QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh()));
-}
#if QT_VERSION >= 0x050000
extern QPixmap qt_pixmapFromWinHICON(HICON icon);
@@ -1754,7 +1251,7 @@ void MainWindow::refreshExecutablesList() QAbstractItemModel *model = executablesList->model();
std::vector<Executable>::const_iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
+ m_OrganizerCore.executablesList()->getExecutables(current, end);
for(int i = 0; current != end; ++current, ++i) {
QVariant temp;
temp.setValue(*current);
@@ -1776,7 +1273,7 @@ void MainWindow::refreshDataTree() QStringList columns("data");
columns.append("");
QTreeWidgetItem *subTree = new QTreeWidgetItem(columns);
- updateTo(subTree, L"", *m_DirectoryStructure, conflictsBox->isChecked());
+ updateTo(subTree, L"", *m_OrganizerCore.directoryStructure(), conflictsBox->isChecked());
tree->insertTopLevelItem(0, subTree);
subTree->setExpanded(true);
tree->header()->resizeSection(0, 200);
@@ -1796,13 +1293,13 @@ void MainWindow::refreshSaveList() ui->savegameList->clear();
QDir savesDir;
- if (m_CurrentProfile->localSavesEnabled()) {
- savesDir.setPath(m_CurrentProfile->getPath() + "/saves");
+ if (m_OrganizerCore.currentProfile()->localSavesEnabled()) {
+ savesDir.setPath(m_OrganizerCore.currentProfile()->getPath() + "/saves");
} else {
wchar_t path[MAX_PATH];
::GetPrivateProfileStringW(L"General", L"SLocalSavePath", L"Saves",
path, MAX_PATH,
- (ToWString(m_CurrentProfile->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str());
+ (ToWString(m_OrganizerCore.currentProfile()->getPath()) + L"\\" + GameInfo::instance().getIniFileNames().at(0)).c_str());
savesDir.setPath(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getDocumentsDir() + L"\\" + path)));
}
@@ -1825,67 +1322,15 @@ void MainWindow::refreshSaveList() }
-void MainWindow::refreshLists()
-{
- if ((m_CurrentProfile != NULL) && m_DirectoryStructure->isPopulated()) {
- refreshESPList();
- refreshBSAList();
- } // no point in refreshing lists if no files have been added to the directory tree
-}
-
-
-void MainWindow::refreshESPList()
-{
- m_CurrentProfile->writeModlist();
-
- // clear list
- try {
- m_PluginList.refresh(m_CurrentProfile->getName(),
- *m_DirectoryStructure,
- m_CurrentProfile->getPluginsFileName(),
- m_CurrentProfile->getLoadOrderFileName(),
- m_CurrentProfile->getLockedOrderFileName());
- } catch (const std::exception &e) {
- reportError(tr("Failed to refresh list of esps: %1").arg(e.what()));
- }
-}
-
-void MainWindow::refreshModList(bool saveChanges)
-{
- // don't lose changes!
- if (saveChanges) {
- m_CurrentProfile->writeModlistNow(true);
- }
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
-
- m_CurrentProfile->refreshModStatus();
-
- m_ModList.notifyChange(-1);
-
- refreshDirectoryStructure();
-}
-
-
static bool BySortValue(const std::pair<UINT32, QTreeWidgetItem*> &LHS, const std::pair<UINT32, QTreeWidgetItem*> &RHS)
{
return LHS.first < RHS.first;
}
-template <typename InputIterator>
-QStringList toStringList(InputIterator current, InputIterator end)
+void MainWindow::updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives)
{
- QStringList result;
- for (; current != end; ++current) {
- result.append(*current);
- }
- return result;
-}
-
-void MainWindow::refreshBSAList()
-{
- m_ArchivesInit = false;
ui->bsaList->clear();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
ui->bsaList->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -1893,40 +1338,9 @@ void MainWindow::refreshBSAList() ui->bsaList->header()->setResizeMode(QHeaderView::ResizeToContents);
#endif
- m_DefaultArchives.clear();
-
- wchar_t buffer[256];
- std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName()));
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- L"", buffer, 256, iniFileName.c_str()) != 0) {
- m_DefaultArchives = ToQString(buffer).split(',');
- } else {
- std::vector<std::wstring> vanillaBSAs = GameInfo::instance().getVanillaBSAs();
- for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) {
- m_DefaultArchives.append(ToQString(*iter));
- }
- }
-
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(),
- L"", buffer, 256, iniFileName.c_str()) != 0) {
- m_DefaultArchives.append(ToQString(buffer).split(','));
- }
-
- for (int i = 0; i < m_DefaultArchives.count(); ++i) {
- m_DefaultArchives[i] = m_DefaultArchives[i].trimmed();
- }
-
- m_ActiveArchives.clear();
-
- auto iter = enabledArchives();
- m_ActiveArchives = toStringList(iter.begin(), iter.end());
- if (m_ActiveArchives.isEmpty()) {
- m_ActiveArchives = m_DefaultArchives;
- }
-
std::vector<std::pair<UINT32, QTreeWidgetItem*> > items;
- std::vector<FileEntry::Ptr> files = m_DirectoryStructure->getFiles();
+ std::vector<FileEntry::Ptr> files = m_OrganizerCore.directoryStructure()->getFiles();
for (auto iter = files.begin(); iter != files.end(); ++iter) {
FileEntry::Ptr current = *iter;
@@ -1934,7 +1348,7 @@ void MainWindow::refreshBSAList() QString extension = filename.right(3).toLower();
if (extension == "bsa") {
- int index = m_ActiveArchives.indexOf(filename);
+ int index = activeArchives.indexOf(filename);
if (index == -1) {
index = 0xFFFF;
}
@@ -1942,20 +1356,20 @@ void MainWindow::refreshBSAList() QStringList strings(filename);
bool isArchive = false;
int origin = current->getOrigin(isArchive);
- strings.append(ToQString(m_DirectoryStructure->getOriginByID(origin).getName()));
+ strings.append(ToQString(m_OrganizerCore.directoryStructure()->getOriginByID(origin).getName()));
QTreeWidgetItem *newItem = new QTreeWidgetItem(strings);
newItem->setData(0, Qt::UserRole, index);
newItem->setData(1, Qt::UserRole, origin);
newItem->setFlags(newItem->flags() & ~Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable);
newItem->setCheckState(0, (index != -1) ? Qt::Checked : Qt::Unchecked);
newItem->setData(0, Qt::UserRole, false);
- if (m_Settings.forceEnableCoreFiles()
- && m_DefaultArchives.contains(filename)) {
+ if (m_OrganizerCore.settings().forceEnableCoreFiles()
+ && defaultArchives.contains(filename)) {
newItem->setCheckState(0, Qt::Checked);
newItem->setDisabled(true);
newItem->setData(0, Qt::UserRole, true);
- } else if ((m_PluginList.state(basename + ".esp") == IPluginList::STATE_ACTIVE)
- || (m_PluginList.state(basename + ".esm") == IPluginList::STATE_ACTIVE)) {
+ } else if ((m_OrganizerCore.pluginList()->state(basename + ".esp") == IPluginList::STATE_ACTIVE)
+ || (m_OrganizerCore.pluginList()->state(basename + ".esm") == IPluginList::STATE_ACTIVE)) {
newItem->setCheckState(0, Qt::Checked);
newItem->setDisabled(true);
} else {
@@ -1969,7 +1383,7 @@ void MainWindow::refreshBSAList() if (index < 0) index = 0;
- UINT32 sortValue = ((m_DirectoryStructure->getOriginByID(origin).getPriority() & 0xFFFF) << 16) | (index & 0xFFFF);
+ UINT32 sortValue = ((m_OrganizerCore.directoryStructure()->getOriginByID(origin).getPriority() & 0xFFFF) << 16) | (index & 0xFFFF);
items.push_back(std::make_pair(sortValue, newItem));
}
}
@@ -1979,7 +1393,7 @@ void MainWindow::refreshBSAList() for (std::vector<std::pair<UINT32, QTreeWidgetItem*> >::iterator iter = items.begin(); iter != items.end(); ++iter) {
int originID = iter->second->data(1, Qt::UserRole).toInt();
- FilesOrigin origin = m_DirectoryStructure->getOriginByID(originID);
+ FilesOrigin origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID);
QString modName("data");
unsigned int modIndex = ModInfo::getIndex(ToQString(origin.getName()));
if (modIndex != UINT_MAX) {
@@ -1999,12 +1413,11 @@ void MainWindow::refreshBSAList() subItem->setExpanded(true);
}
- checkBSAList();
- m_ArchivesInit = true;
+ m_OrganizerCore.checkBSAList();
}
-void MainWindow::checkBSAList()
+void MainWindow::checkBSAList(const QStringList &defaultArchives)
{
ui->bsaList->blockSignals(true);
@@ -2020,7 +1433,7 @@ void MainWindow::checkBSAList() item->setToolTip(0, QString());
if (item->checkState(0) == Qt::Unchecked) {
- if (m_DefaultArchives.contains(filename)) {
+ if (defaultArchives.contains(filename)) {
item->setIcon(0, QIcon(":/MO/gui/warning"));
item->setToolTip(0, tr("This bsa is enabled in the ini file so it may be required!"));
modWarning = true;
@@ -2129,103 +1542,35 @@ void MainWindow::readSettings() }
-void MainWindow::storeSettings()
+void MainWindow::storeSettings(QSettings &settings)
{
- if (m_CurrentProfile == NULL) {
- return;
- }
- m_CurrentProfile->writeModlist();
- m_CurrentProfile->createTweakedIniFile();
- saveCurrentLists();
- m_Settings.setupLoadMechanism();
-
- QString iniFile = ToQString(GameInfo::instance().getIniFilename());
- shellCopy(iniFile, iniFile + ".new", true, this);
-
- QSettings::Status result = QSettings::NoError;
- {
- QSettings settings(iniFile + ".new", QSettings::IniFormat);
- if (m_CurrentProfile != NULL) {
- settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData());
- } else {
- settings.remove("selected_profile");
- }
+ settings.setValue("mod_list_state", ui->modList->header()->saveState());
+ settings.setValue("plugin_list_state", ui->espList->header()->saveState());
- settings.setValue("mod_list_state", ui->modList->header()->saveState());
- settings.setValue("plugin_list_state", ui->espList->header()->saveState());
-
- settings.setValue("group_state", ui->groupCombo->currentIndex());
-
- settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
-
- settings.setValue("window_geometry", saveGeometry());
- settings.setValue("window_split", ui->splitter->saveState());
- settings.setValue("log_split", ui->topLevelSplitter->saveState());
-
- settings.setValue("browser_geometry", m_IntegratedBrowser.saveGeometry());
-
- settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked());
- settings.setValue("manage_bsas", ui->manageArchivesBox->isChecked());
-
- settings.remove("customExecutables");
- settings.beginWriteArray("customExecutables");
- std::vector<Executable>::const_iterator current, end;
- m_ExecutablesList.getExecutables(current, end);
- int count = 0;
- for (; current != end; ++current) {
- const Executable &item = *current;
- if (item.m_Custom || item.m_Toolbar) {
- settings.setArrayIndex(count++);
- settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath());
- settings.setValue("title", item.m_Title);
- settings.setValue("arguments", item.m_Arguments);
- settings.setValue("workingDirectory", item.m_WorkingDirectory);
- settings.setValue("closeOnStart", item.m_CloseMO == DEFAULT_CLOSE);
- settings.setValue("steamAppID", item.m_SteamAppID);
- settings.setValue("custom", item.m_Custom);
- settings.setValue("toolbar", item.m_Toolbar);
- }
- }
- settings.endArray();
+ settings.setValue("group_state", ui->groupCombo->currentIndex());
- QComboBox *executableBox = findChild<QComboBox*>("executablesListBox");
- settings.setValue("selected_executable", executableBox->currentIndex());
+ settings.setValue("window_geometry", saveGeometry());
+ settings.setValue("window_split", ui->splitter->saveState());
+ settings.setValue("log_split", ui->topLevelSplitter->saveState());
- FileDialogMemory::save(settings);
+ settings.setValue("browser_geometry", m_IntegratedBrowser.saveGeometry());
- settings.sync();
- result = settings.status();
- }
- if (result == QSettings::NoError) {
- if (!shellRename(iniFile + ".new", iniFile, true, this)) {
- QMessageBox::critical(this, tr("Failed to write settings"),
- tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(::GetLastError())));
- }
- } else {
- QString reason = result == QSettings::AccessError ? tr("File is write protected")
- : result == QSettings::FormatError ? tr("Invalid file format (probably a bug)")
- : tr("Unknown error %1").arg(result);
- QMessageBox::critical(this, tr("Failed to write settings"),
- tr("An error occured trying to write back MO settings: %1").arg(reason));
- }
+ settings.setValue("filters_visible", ui->displayCategoriesBtn->isChecked());
+ settings.setValue("manage_bsas", ui->manageArchivesBox->isChecked());
}
void MainWindow::on_btnRefreshData_clicked()
{
- if (!m_DirectoryUpdate) {
- refreshDirectoryStructure();
- } else {
- qDebug("directory update");
- }
+ m_OrganizerCore.refreshDirectoryStructure();
}
void MainWindow::on_tabWidget_currentChanged(int index)
{
if (index == 0) {
- refreshESPList();
+ m_OrganizerCore.refreshESPList();
} else if (index == 1) {
- refreshBSAList();
+ m_OrganizerCore.refreshBSAList();
} else if (index == 2) {
refreshDataTree();
} else if (index == 3) {
@@ -2235,67 +1580,11 @@ void MainWindow::on_tabWidget_currentChanged(int index) }
}
-std::vector<unsigned int> MainWindow::activeProblems() const
-{
- std::vector<unsigned int> problems;
- if (m_UnloadedPlugins.size() != 0) {
- problems.push_back(PROBLEM_PLUGINSNOTLOADED);
- }
- if (m_PluginList.enabledCount() > 255) {
- problems.push_back(PROBLEM_TOOMANYPLUGINS);
- }
- return problems;
-}
-
-QString MainWindow::shortDescription(unsigned int key) const
-{
- switch (key) {
- case PROBLEM_PLUGINSNOTLOADED: {
- return tr("Some plugins could not be loaded");
- } break;
- case PROBLEM_TOOMANYPLUGINS: {
- return tr("Too many esps and esms enabled");
- } break;
- default: {
- return tr("Description missing");
- } break;
- }
-}
-
-QString MainWindow::fullDescription(unsigned int key) const
-{
- switch (key) {
- case PROBLEM_PLUGINSNOTLOADED: {
- QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "<ul>";
- foreach (const QString &plugin, m_UnloadedPlugins) {
- result += "<li>" + plugin + "</li>";
- }
- result += "<ul>";
- return result;
- } break;
- case PROBLEM_TOOMANYPLUGINS: {
- return tr("The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or "
- "merge some plugins into one. You can find a guide here: <a href=\"http://wiki.step-project.com/Guide:Merging_Plugins\">http://wiki.step-project.com/Guide:Merging_Plugins</a>");
- } break;
- default: {
- return tr("Description missing");
- } break;
- }
-}
-
-bool MainWindow::hasGuidedFix(unsigned int) const
-{
- return false;
-}
-
-void MainWindow::startGuidedFix(unsigned int) const
-{
-}
void MainWindow::installMod()
{
try {
- QStringList extensions = m_InstallationManager.getSupportedExtensions();
+ QStringList extensions = m_OrganizerCore.installationManager()->getSupportedExtensions();
for (auto iter = extensions.begin(); iter != extensions.end(); ++iter) {
*iter = "*." + *iter;
}
@@ -2306,114 +1595,13 @@ void MainWindow::installMod() if (fileName.length() == 0) {
return;
} else {
- installMod(fileName);
+ m_OrganizerCore.installMod(fileName);
}
} catch (const std::exception &e) {
reportError(e.what());
}
}
-IModInterface *MainWindow::installMod(const QString &fileName)
-{
- if (m_CurrentProfile == NULL) {
- return NULL;
- }
-
- bool hasIniTweaks = false;
- GuessedValue<QString> modName;
- m_CurrentProfile->writeModlistNow();
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
- MessageDialog::showMessage(tr("Installation successful"), this);
- refreshModList();
-
- QModelIndexList posList = m_ModList.match(m_ModList.index(0, 0), Qt::DisplayRole, static_cast<const QString&>(modName));
- if (posList.count() == 1) {
- ui->modList->scrollTo(posList.at(0));
- }
- int modIndex = ModInfo::getIndex(modName);
- if (modIndex != UINT_MAX) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
- if (hasIniTweaks &&
- (QMessageBox::question(this, tr("Configure Mod"),
- tr("This mod contains ini tweaks. Do you want to configure them now?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
- displayModInformation(modInfo, modIndex, ModInfoDialog::TAB_INIFILES);
- }
- m_ModInstalled(modName);
- return modInfo.data();
- } else {
- reportError(tr("mod \"%1\" not found").arg(modName));
- }
- } else if (m_InstallationManager.wasCancelled()) {
- QMessageBox::information(this, tr("Installation cancelled"), tr("The mod was not installed completely."), QMessageBox::Ok);
- }
- return NULL;
-}
-
-IModInterface *MainWindow::getMod(const QString &name)
-{
- unsigned int index = ModInfo::getIndex(name);
- if (index == UINT_MAX) {
- return NULL;
- } else {
- return ModInfo::getByIndex(index).data();
- }
-}
-
-IModInterface *MainWindow::createMod(GuessedValue<QString> &name)
-{
- if (!m_InstallationManager.testOverwrite(name)) {
- return NULL;
- }
-
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
-
- QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name);
-
- QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat);
-
- settingsFile.setValue("modid", 0);
- settingsFile.setValue("version", "");
- settingsFile.setValue("newestVersion", "");
- settingsFile.setValue("category", 0);
- settingsFile.setValue("installationFile", "");
- return ModInfo::createFrom(QDir(targetDirectory), &m_DirectoryStructure).data();
-}
-
-bool MainWindow::removeMod(IModInterface *mod)
-{
- unsigned int index = ModInfo::getIndex(mod->name());
- if (index == UINT_MAX) {
- return mod->remove();
- } else {
- return ModInfo::removeMod(index);
- }
-}
-
-QList<IOrganizer::FileInfo> MainWindow::findFileInfos(const QString &path, const std::function<bool (const IOrganizer::FileInfo &)> &filter) const
-{
- QList<IOrganizer::FileInfo> result;
- DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path));
- if (dir != NULL) {
- std::vector<FileEntry::Ptr> files = dir->getFiles();
- foreach (FileEntry::Ptr file, files) {
- IOrganizer::FileInfo info;
- info.filePath = ToQString(file->getFullPath());
- bool fromArchive = false;
- info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)).getName()));
- info.archive = fromArchive ? ToQString(file->getArchive()) : "";
- foreach (int idx, file->getAlternatives()) {
- info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(idx).getName()));
- }
-
- if (filter(info)) {
- result.append(info);
- }
- }
- }
- return result;
-}
void MainWindow::on_startButton_clicked()
{
@@ -2421,12 +1609,13 @@ void MainWindow::on_startButton_clicked() Executable selectedExecutable = executablesList->itemData(executablesList->currentIndex()).value<Executable>();
- spawnBinary(selectedExecutable.m_BinaryInfo,
- selectedExecutable.m_Arguments,
- selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory
- : selectedExecutable.m_BinaryInfo.absolutePath(),
- selectedExecutable.m_CloseMO == DEFAULT_CLOSE,
- selectedExecutable.m_SteamAppID);
+ m_OrganizerCore.spawnBinary(
+ selectedExecutable.m_BinaryInfo,
+ selectedExecutable.m_Arguments,
+ selectedExecutable.m_WorkingDirectory.length() != 0 ? selectedExecutable.m_WorkingDirectory
+ : selectedExecutable.m_BinaryInfo.absolutePath(),
+ selectedExecutable.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE,
+ selectedExecutable.m_SteamAppID);
}
@@ -2503,9 +1692,9 @@ bool MainWindow::modifyExecutablesDialog() {
bool result = false;
try {
- EditExecutablesDialog dialog(m_ExecutablesList);
+ EditExecutablesDialog dialog(m_OrganizerCore.executablesList());
if (dialog.exec() == QDialog::Accepted) {
- m_ExecutablesList = dialog.getExecutablesList();
+ m_OrganizerCore.setExecutablesDialog(dialog.getExecutablesList());
result = true;
}
refreshExecutablesList();
@@ -2617,26 +1806,6 @@ void MainWindow::setESPListSorting(int index) }
-bool MainWindow::queryLogin(QString &username, QString &password)
-{
- CredentialsDialog dialog(this);
- int res = dialog.exec();
- if (dialog.neverAsk()) {
- m_AskForNexusPW = false;
- }
- if (res == QDialog::Accepted) {
- username = dialog.username();
- password = dialog.password();
- if (dialog.store()) {
- m_Settings.setNexusLogin(username, password);
- }
- return true;
- } else {
- return false;
- }
-}
-
-
bool MainWindow::setCurrentProfile(int index)
{
QComboBox *profilesBox = findChild<QComboBox*>("profileBox");
@@ -2665,136 +1834,45 @@ bool MainWindow::setCurrentProfile(const QString &name) void MainWindow::refresher_progress(int percent)
{
- m_RefreshProgress->setValue(percent);
+ if (percent == 100) {
+ m_RefreshProgress->setVisible(false);
+ } else if (!m_RefreshProgress->isVisible()) {
+ m_RefreshProgress->setVisible(true);
+ m_RefreshProgress->setRange(0, 100);
+ m_RefreshProgress->setValue(percent);
+ }
}
-
void MainWindow::directory_refreshed()
{
- DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure();
- Q_ASSERT(newStructure != m_DirectoryStructure);
- if (newStructure != NULL) {
- std::swap(m_DirectoryStructure, newStructure);
- delete newStructure;
- refreshDataTree();
- } else {
- // TODO: don't know why this happens, this slot seems to get called twice with only one emit
- return;
- }
- m_DirectoryUpdate = false;
- if (m_CurrentProfile != NULL) {
- refreshLists();
- }
-
// some problem-reports may rely on the virtual directory tree so they need to be updated
// now
+ refreshDataTree();
updateProblemsButton();
-
- for (int i = 0; i < m_ModList.rowCount(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- modInfo->clearCaches();
- }
statusBar()->hide();
}
-void MainWindow::externalMessage(const QString &message)
-{
- if (message.left(6).toLower() == "nxm://") {
- MessageDialog::showMessage(tr("Download started"), this);
- downloadRequestedNXM(message);
- }
-}
-
-void MainWindow::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo)
-{
- // add files of the bsa to the directory structure
- m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure
- , modInfo->name()
- , m_CurrentProfile->getModPriority(index)
- , modInfo->absolutePath()
- , modInfo->stealFiles()
- );
- DirectoryRefresher::cleanStructure(m_DirectoryStructure);
- // need to refresh plugin list now so we can activate esps
- refreshESPList();
- // activate all esps of the specified mod so the bsas get activated along with it
- updateModActiveState(index, true);
- // now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active
- refreshBSAList();
- saveArchiveList();
- m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives());
-
- // finally also add files from bsas to the directory structure
- m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure
- , modInfo->name()
- , m_CurrentProfile->getModPriority(index)
- , modInfo->absolutePath()
- , modInfo->archives()
- );
-}
-
-void MainWindow::modStatusChanged(unsigned int index)
-{
- try {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
- if (m_CurrentProfile->modEnabled(index)) {
- updateModInDirectoryStructure(index, modInfo);
- } else {
- updateModActiveState(index, false);
- refreshESPList();
- if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
- FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
- origin.enable(false);
- }
- }
- modInfo->clearCaches();
-
- for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- int priority = m_CurrentProfile->getModPriority(i);
- if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
- // priorities in the directory structure are one higher because data is 0
- m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
- }
- }
- m_DirectoryStructure->getFileRegister()->sortOrigins();
-
- refreshLists();
- } catch (const std::exception& e) {
- reportError(tr("failed to update mod list: %1").arg(e.what()));
- }
-}
-
-
-void MainWindow::removeOrigin(const QString &name)
-{
- FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(name));
- origin.enable(false);
- refreshLists();
-}
-
-
void MainWindow::modorder_changed()
{
- for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
- int priority = m_CurrentProfile->getModPriority(i);
- if (m_CurrentProfile->modEnabled(i)) {
+ for (unsigned int i = 0; i < m_OrganizerCore.currentProfile()->numMods(); ++i) {
+ int priority = m_OrganizerCore.currentProfile()->getModPriority(i);
+ if (m_OrganizerCore.currentProfile()->modEnabled(i)) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
// priorities in the directory structure are one higher because data is 0
- m_DirectoryStructure->getOriginByName(ToWString(modInfo->internalName())).setPriority(priority + 1);
+ m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->internalName())).setPriority(priority + 1);
}
}
- refreshBSAList();
- m_CurrentProfile->writeModlist();
- saveArchiveList();
- m_DirectoryStructure->getFileRegister()->sortOrigins();
+ m_OrganizerCore.refreshBSAList();
+ m_OrganizerCore.currentProfile()->writeModlist();
+ m_OrganizerCore.saveArchiveList();
+ m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins();
{ // refresh selection
QModelIndex current = ui->modList->currentIndex();
if (current.isValid()) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
modInfo->doConflictCheck();
- m_ModList.setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten());
+ m_OrganizerCore.modList()->setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten());
if (m_ModListSortProxy != NULL) {
m_ModListSortProxy->invalidate();
}
@@ -2803,6 +1881,16 @@ void MainWindow::modorder_changed() }
}
+void MainWindow::modInstalled()
+{
+ QModelIndexList posList =
+ m_OrganizerCore.modList().match(m_OrganizerCore.modList().index(0, 0),
+ Qt::DisplayRole, static_cast<const QString&>(modName));
+ if (posList.count() == 1) {
+ ui->modList->scrollTo(posList.at(0));
+ }
+}
+
void MainWindow::procError(QProcess::ProcessError error)
{
reportError(tr("failed to spawn notepad.exe: %1").arg(error));
@@ -2814,15 +1902,6 @@ void MainWindow::procFinished(int, QProcess::ExitStatus) this->sender()->deleteLater();
}
-void MainWindow::profileRefresh()
-{
- // have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
- m_CurrentProfile->refreshModStatus();
-
- refreshModList();
-}
-
void MainWindow::showMessage(const QString &message)
{
MessageDialog::showMessage(message, this);
@@ -2906,12 +1985,12 @@ void MainWindow::modRenamed(const QString &oldName, const QString &newName) }
// immediately refresh the active profile because the data in memory is invalid
- m_CurrentProfile->refreshModStatus();
+ m_OrganizerCore.currentProfile()->refreshModStatus();
// also fix the directory structure
try {
- if (m_DirectoryStructure->originExists(ToWString(oldName))) {
- FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(oldName));
+ if (m_OrganizerCore.directoryStructure()->originExists(ToWString(oldName))) {
+ FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(oldName));
origin.setName(ToWString(newName));
} else {
@@ -2930,11 +2009,11 @@ void MainWindow::modlistChanged(int) void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName)
{
- const FileEntry::Ptr filePtr = m_DirectoryStructure->findFile(ToWString(filePath));
+ const FileEntry::Ptr filePtr = m_OrganizerCore.directoryStructure()->findFile(ToWString(filePath));
if (filePtr.get() != NULL) {
try {
- if (m_DirectoryStructure->originExists(ToWString(newOriginName))) {
- FilesOrigin &newOrigin = m_DirectoryStructure->getOriginByName(ToWString(newOriginName));
+ if (m_OrganizerCore.directoryStructure()->originExists(ToWString(newOriginName))) {
+ FilesOrigin &newOrigin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(newOriginName));
QString fullNewPath = ToQString(newOrigin.getPath()) + "\\" + filePath;
WIN32_FIND_DATAW findData;
@@ -2942,8 +2021,8 @@ void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L"");
}
- if (m_DirectoryStructure->originExists(ToWString(oldOriginName))) {
- FilesOrigin &oldOrigin = m_DirectoryStructure->getOriginByName(ToWString(oldOriginName));
+ if (m_OrganizerCore.directoryStructure()->originExists(ToWString(oldOriginName))) {
+ FilesOrigin &oldOrigin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(oldOriginName));
filePtr->removeOrigin(oldOrigin.getID());
}
} catch (const std::exception &e) {
@@ -3059,7 +2138,7 @@ void MainWindow::restoreBackup_clicked() ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
if (backupRegEx.indexIn(modInfo->name()) != -1) {
QString regName = backupRegEx.cap(1);
- QDir modDir(QDir::fromNativeSeparators(m_Settings.getModDirectory()));
+ QDir modDir(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()));
if (!modDir.exists(regName) ||
(QMessageBox::question(this, tr("Overwrite?"),
tr("This will replace the existing mod \"%1\". Continue?").arg(regName),
@@ -3067,7 +2146,7 @@ void MainWindow::restoreBackup_clicked() if (modDir.exists(regName) && !shellDelete(QStringList(modDir.absoluteFilePath(regName)))) {
reportError(tr("failed to remove mod \"%1\"").arg(regName));
} else {
- QString destinationPath = QDir::fromNativeSeparators(m_Settings.getModDirectory()) + "/" + regName;
+ QString destinationPath = QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()) + "/" + regName;
if (!modDir.rename(modInfo->absolutePath(), destinationPath)) {
reportError(tr("failed to rename \"%1\" to \"%2\"").arg(modInfo->absolutePath()).arg(destinationPath));
}
@@ -3077,43 +2156,18 @@ void MainWindow::restoreBackup_clicked() }
}
-void MainWindow::updateModActiveState(int index, bool active)
-{
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
-
- QDir dir(modInfo->absolutePath());
- foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
- m_PluginList.enableESP(esm, active);
- }
- int enabled = 0;
- QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
- foreach (const QString &esp, esps) {
- if (active != m_PluginList.isEnabled(esp)) {
- m_PluginList.enableESP(esp, active);
- ++enabled;
- }
- }
- if (active && (enabled > 1)) {
- MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), this);
- }
- m_PluginList.refreshLoadOrder();
- // immediately save affected lists
- savePluginList();
-// refreshBSAList();
-}
-
void MainWindow::modlistChanged(const QModelIndex&, int)
{
- m_CurrentProfile->writeModlist();
+ m_OrganizerCore.currentProfile()->writeModlist();
}
void MainWindow::modlistSelectionChanged(const QModelIndex ¤t, const QModelIndex&)
{
if (current.isValid()) {
ModInfo::Ptr selectedMod = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
- m_ModList.setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten());
+ m_OrganizerCore.modList()->setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten());
} else {
- m_ModList.setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
+ m_OrganizerCore.modList()->setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
}
if ((m_ModListSortProxy != NULL)
&& !m_ModListSortProxy->beingInvalidated()) {
@@ -3148,11 +2202,11 @@ void MainWindow::removeMod_clicked() QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
// use mod names instead of indexes because those become invalid during the removal
foreach (QString name, modNames) {
- m_ModList.removeRowForce(ModInfo::getIndex(name));
+ m_OrganizerCore.modList()->removeRowForce(ModInfo::getIndex(name));
}
}
} else {
- m_ModList.removeRow(m_ContextRow, QModelIndex());
+ m_OrganizerCore.modList()->removeRow(m_ContextRow, QModelIndex());
}
} catch (const std::exception &e) {
reportError(tr("failed to remove mod: %1").arg(e.what()));
@@ -3163,9 +2217,9 @@ void MainWindow::removeMod_clicked() void MainWindow::modRemoved(const QString &fileName)
{
if (!fileName.isEmpty() && !QFileInfo(fileName).isAbsolute()) {
- int index = m_DownloadManager.indexByName(fileName);
+ int index = m_OrganizerCore.downloadManager()->indexByName(fileName);
if (index >= 0) {
- m_DownloadManager.markUninstalled(index);
+ m_OrganizerCore.downloadManager()->markUninstalled(index);
}
}
}
@@ -3182,10 +2236,10 @@ void MainWindow::reinstallMod_clicked() if (fileInfo.exists()) {
fullInstallationFile = installationFile;
} else {
- fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(fileInfo.fileName());
+ fullInstallationFile = m_OrganizerCore.downloadManager()->getOutputDirectory().append("/").append(fileInfo.fileName());
}
} else {
- fullInstallationFile = m_DownloadManager.getOutputDirectory().append("/").append(installationFile);
+ fullInstallationFile = m_OrganizerCore.downloadManager()->getOutputDirectory().append("/").append(installationFile);
}
if (QFile::exists(fullInstallationFile)) {
installMod(fullInstallationFile);
@@ -3202,11 +2256,12 @@ void MainWindow::reinstallMod_clicked() void MainWindow::resumeDownload(int downloadIndex)
{
if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
- m_DownloadManager.resumeDownload(downloadIndex);
+ m_OrganizerCore.downloadManager()->resumeDownload(downloadIndex);
} else {
QString username, password;
- if (m_Settings.getNexusLogin(username, password)) {
- m_PostLoginTasks.push_back(boost::bind(&MainWindow::resumeDownload, _1, downloadIndex));
+ if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
+ //m_PostLoginTasks.push_back(boost::bind(&MainWindow::resumeDownload, _1, downloadIndex));
+ m_OrganizerCore.doAfterLogin(std::bind(&MainWindow::resumeDownload, this, downloadIndex));
NexusInterface::instance()->getAccessManager()->login(username, password);
} else {
MessageDialog::showMessage(tr("You need to be logged in with Nexus to resume a download"), this);
@@ -3221,7 +2276,7 @@ void MainWindow::endorseMod(ModInfo::Ptr mod) mod->endorse(true);
} else {
QString username, password;
- if (m_Settings.getNexusLogin(username, password)) {
+ if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
m_PostLoginTasks.push_back(boost::bind(&MainWindow::endorseMod, _1, mod));
NexusInterface::instance()->getAccessManager()->login(username, password);
} else {
@@ -3248,7 +2303,7 @@ void MainWindow::unendorse_clicked() if (NexusInterface::instance()->getAccessManager()->loggedIn()) {
ModInfo::getByIndex(m_ContextRow)->endorse(false);
} else {
- if (m_Settings.getNexusLogin(username, password)) {
+ if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::unendorse_clicked));
NexusInterface::instance()->getAccessManager()->login(username, password);
} else {
@@ -3257,12 +2312,21 @@ void MainWindow::unendorse_clicked() }
}
+void MainWindow::loginFailed(const QString &message)
+{
+ statusBar()->hide();
+}
+
+void MainWindow::windowTutorialFinished(const QString &windowName)
+{
+ m_OrganizerCore.settings().directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, this);
+}
void MainWindow::overwriteClosed(int)
{
OverwriteInfoDialog *dialog = this->findChild<OverwriteInfoDialog*>("__overwriteDialog");
if (dialog != NULL) {
- m_ModList.modInfoChanged(dialog->modInfo());
+ m_OrganizerCore.modList()->modInfoChanged(dialog->modInfo());
dialog->deleteLater();
}
}
@@ -3270,7 +2334,7 @@ void MainWindow::overwriteClosed(int) void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab)
{
- m_ModList.modInfoAboutToChange(modInfo);
+ m_OrganizerCore.modList()->modInfoAboutToChange(modInfo);
std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end()) {
QDialog *dialog = this->findChild<QDialog*>("__overwriteDialog");
@@ -3290,7 +2354,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, }
} else {
modInfo->saveMeta();
- ModInfoDialog dialog(modInfo, m_DirectoryStructure, modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this);
+ ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), this);
connect(&dialog, SIGNAL(nexusLinkActivated(QString)), this, SLOT(nexusLinkActivated(QString)));
connect(&dialog, SIGNAL(downloadRequest(QString)), this, SLOT(downloadRequestedNXM(QString)));
connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection);
@@ -3300,31 +2364,31 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, connect(&dialog, SIGNAL(endorseMod(ModInfo::Ptr)), this, SLOT(endorseMod(ModInfo::Ptr)));
dialog.openTab(tab);
- dialog.restoreTabState(m_Settings.directInterface().value("mod_info_tabs").toByteArray());
+ dialog.restoreTabState(m_OrganizerCore.settings().directInterface().value("mod_info_tabs").toByteArray());
dialog.exec();
- m_Settings.directInterface().setValue("mod_info_tabs", dialog.saveTabState());
+ m_OrganizerCore.settings().directInterface().setValue("mod_info_tabs", dialog.saveTabState());
modInfo->saveMeta();
emit modInfoDisplayed();
- m_ModList.modInfoChanged(modInfo);
+ m_OrganizerCore.modList()->modInfoChanged(modInfo);
}
- if (m_CurrentProfile->modEnabled(index)) {
- FilesOrigin& origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
+ if (m_OrganizerCore.currentProfile()->modEnabled(index)) {
+ FilesOrigin& origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->name()));
origin.enable(false);
- if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
- FilesOrigin& origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
+ if (m_OrganizerCore.directoryStructure()->originExists(ToWString(modInfo->name()))) {
+ FilesOrigin& origin = m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(modInfo->name()));
origin.enable(false);
- m_DirectoryRefresher.addModToStructure(m_DirectoryStructure
+ m_OrganizerCore.directoryRefresher()->addModToStructure(m_OrganizerCore.directoryStructure()
, modInfo->name()
- , m_CurrentProfile->getModPriority(index)
+ , m_OrganizerCore.currentProfile()->getModPriority(index)
, modInfo->absolutePath()
, modInfo->stealFiles()
, modInfo->archives());
- DirectoryRefresher::cleanStructure(m_DirectoryStructure);
- refreshLists();
+ DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure());
+ m_OrganizerCore.refreshLists();
}
}
}
@@ -3332,7 +2396,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, void MainWindow::modOpenNext()
{
- QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0));
+ QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0));
index = m_ModListSortProxy->index((index.row() + 1) % m_ModListSortProxy->rowCount(), 0);
m_ContextRow = m_ModListSortProxy->mapToSource(index).row();
@@ -3349,7 +2413,7 @@ void MainWindow::modOpenNext() void MainWindow::modOpenPrev()
{
- QModelIndex index = m_ModListSortProxy->mapFromSource(m_ModList.index(m_ContextRow, 0));
+ QModelIndex index = m_ModListSortProxy->mapFromSource(m_OrganizerCore.modList()->index(m_ContextRow, 0));
int row = index.row() - 1;
if (row == -1) {
row = m_ModListSortProxy->rowCount() - 1;
@@ -3392,15 +2456,15 @@ void MainWindow::ignoreMissingData_clicked() ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow);
QDir(info->absolutePath()).mkdir("textures");
info->testValid();
- connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), &m_ModList, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+ connect(this, SIGNAL(modListDataChanged(QModelIndex,QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex,QModelIndex)));
- emit modListDataChanged(m_ModList.index(m_ContextRow, 0), m_ModList.index(m_ContextRow, m_ModList.columnCount() - 1));
+ emit modListDataChanged(m_OrganizerCore.modList()->index(m_ContextRow, 0), m_OrganizerCore.modList()->index(m_ContextRow, m_OrganizerCore.modList()->columnCount() - 1));
}
void MainWindow::visitOnNexus_clicked()
{
- int modID = m_ModList.data(m_ModList.index(m_ContextRow, 0), Qt::UserRole).toInt();
+ int modID = m_OrganizerCore.modList()->data(m_OrganizerCore.modList()->index(m_ContextRow, 0), Qt::UserRole).toInt();
if (modID > 0) {
nexusLinkActivated(QString("%1/mods/%2").arg(ToQString(GameInfo::instance().getNexusPage(false))).arg(modID));
} else {
@@ -3427,9 +2491,9 @@ void MainWindow::information_clicked() void MainWindow::syncOverwrite()
{
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
- SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_DirectoryStructure, this);
+ SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_OrganizerCore.directoryStructure(), this);
if (syncDialog.exec() == QDialog::Accepted) {
- syncDialog.apply(QDir::fromNativeSeparators(m_Settings.getModDirectory()));
+ syncDialog.apply(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()));
modInfo->testValid();
refreshDirectoryStructure();
}
@@ -3452,12 +2516,12 @@ void MainWindow::createModFromOverwrite() }
}
- if (getMod(name) != NULL) {
+ if (m_OrganizerCore.getMod(name) != NULL) {
reportError(tr("A mod with this name already exists"));
return;
}
- IModInterface *newMod = createMod(name);
+ IModInterface *newMod = m_OrganizerCore.createMod(name);
if (newMod == NULL) {
return;
}
@@ -3480,7 +2544,7 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) if (!index.isValid()) {
return;
}
- QModelIndex sourceIdx = mapToModel(&m_ModList, index);
+ QModelIndex sourceIdx = mapToModel(m_OrganizerCore.modList(), index);
if (!sourceIdx.isValid()) {
return;
}
@@ -3594,14 +2658,14 @@ void MainWindow::addRemoveCategories_MenuHandler() { if (selected.size() > 0) {
foreach (const QPersistentModelIndex &idx, selected) {
qDebug("change categories on: %s (ref: %s)", qPrintable(idx.data().toString()), qPrintable(m_ContextIdx.data().toString()));
- QModelIndex modIdx = mapToModel(&m_ModList, idx);
+ QModelIndex modIdx = mapToModel(m_OrganizerCore.modList(), idx);
if (modIdx.row() != m_ContextIdx.row()) {
addRemoveCategoriesFromMenu(menu, modIdx.row(), m_ContextIdx.row());
}
}
replaceCategoriesFromMenu(menu, m_ContextIdx.row());
- m_ModList.notifyChange(-1);
+ m_OrganizerCore.modList()->notifyChange(-1);
foreach (const QPersistentModelIndex &idx, selected) {
ui->modList->selectionModel()->select(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows);
@@ -3609,7 +2673,7 @@ void MainWindow::addRemoveCategories_MenuHandler() { } else {
//For single mod selections, just do a replace
replaceCategoriesFromMenu(menu, m_ContextRow);
- m_ModList.notifyChange(m_ContextRow);
+ m_OrganizerCore.modList()->notifyChange(m_ContextRow);
}
refreshFilters();
@@ -3627,12 +2691,12 @@ void MainWindow::replaceCategories_MenuHandler() { if (selected.size() > 0) {
QStringList selectedMods;
for (int i = 0; i < selected.size(); ++i) {
- QModelIndex temp = mapToModel(&m_ModList, selected.at(i));
+ QModelIndex temp = mapToModel(m_OrganizerCore.modList(), selected.at(i));
selectedMods.append(temp.data().toString());
- replaceCategoriesFromMenu(menu, mapToModel(&m_ModList, selected.at(i)).row());
+ replaceCategoriesFromMenu(menu, mapToModel(m_OrganizerCore.modList(), selected.at(i)).row());
}
- m_ModList.notifyChange(-1);
+ m_OrganizerCore.modList()->notifyChange(-1);
// find mods by their name because indices are invalidated
QAbstractItemModel *model = ui->modList->model();
@@ -3646,7 +2710,7 @@ void MainWindow::replaceCategories_MenuHandler() { } else {
//For single mod selections, just do a replace
replaceCategoriesFromMenu(menu, m_ContextRow);
- m_ModList.notifyChange(m_ContextRow);
+ m_OrganizerCore.modList()->notifyChange(m_ContextRow);
}
refreshFilters();
@@ -3676,6 +2740,33 @@ void MainWindow::savePrimaryCategory() }
}
+bool MainWindow::saveArchiveList()
+{
+ if (m_ArchivesInit) {
+ SafeWriteFile archiveFile(m_OrganizerCore.currentProfile()->getArchivesFileName());
+ for (int i = 0; i < ui->bsaList->topLevelItemCount(); ++i) {
+ QTreeWidgetItem *tlItem = ui->bsaList->topLevelItem(i);
+ for (int j = 0; j < tlItem->childCount(); ++j) {
+ QTreeWidgetItem *item = tlItem->child(j);
+ if (item->checkState(0) == Qt::Checked) {
+ // in managed mode, "register" all enabled archives, otherwise register only the files registered in the ini
+ if (ui->manageArchivesBox->isChecked()
+ || item->data(0, Qt::UserRole).toBool()) {
+ archiveFile->write(item->text(0).toUtf8().append("\r\n"));
+ }
+ }
+ }
+ }
+ if (archiveFile.commitIfDifferent(m_ArchiveListHash)) {
+ qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_OrganizerCore.currentProfile()->getArchivesFileName())));
+ return true;
+ }
+ } else {
+ qWarning("archive list not initialised");
+ }
+ return false;
+}
+
void MainWindow::checkModsForUpdates()
{
statusBar()->show();
@@ -3684,8 +2775,8 @@ void MainWindow::checkModsForUpdates() m_RefreshProgress->setRange(0, m_ModsToUpdate);
} else {
QString username, password;
- if (m_Settings.getNexusLogin(username, password)) {
- m_PostLoginTasks.push_back(boost::mem_fn(&MainWindow::checkModsForUpdates));
+ if (m_OrganizerCore.settings().getNexusLogin(username, password)) {
+ m_OrganizerCore.doAfterLogin(boost::mem_fn(&MainWindow::checkModsForUpdates));
NexusInterface::instance()->getAccessManager()->login(username, password);
} else { // otherwise there will be no endorsement info
m_ModsToUpdate = ModInfo::checkAllForUpdate(this);
@@ -3810,7 +2901,7 @@ void MainWindow::exportModListCSV() for (unsigned int i = 0; i < numMods; ++i) {
ModInfo::Ptr info = ModInfo::getByIndex(i);
- bool enabled = m_CurrentProfile->modEnabled(i);
+ bool enabled = m_OrganizerCore.currentProfile()->modEnabled(i);
if ((selection.getChoiceData().toInt() == 1) && !enabled) {
continue;
} else if ((selection.getChoiceData().toInt() == 2) && !m_ModListSortProxy->filterMatchesMod(info, enabled)) {
@@ -3855,7 +2946,7 @@ QMenu *MainWindow::modListContextMenu() menu->addAction(tr("Check all for update"), this, SLOT(checkModsForUpdates()));
- menu->addAction(tr("Refresh"), this, SLOT(profileRefresh()));
+ menu->addAction(tr("Refresh"), &m_OrganizerCore, SLOT(profileRefresh()));
menu->addAction(tr("Export to csv..."), this, SLOT(exportModListCSV()));
return menu;
@@ -3866,7 +2957,7 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos) try {
QTreeView *modList = findChild<QTreeView*>("modList");
- m_ContextIdx = mapToModel(&m_ModList, modList->indexAt(pos));
+ m_ContextIdx = mapToModel(m_OrganizerCore.modList(), modList->indexAt(pos));
m_ContextRow = m_ContextIdx.row();
QMenu *menu = NULL;
@@ -4042,7 +3133,7 @@ void MainWindow::fixMods_clicked() for (int i = 0; i < save->numPlugins(); ++i) {
const QString &pluginName = save->plugin(i);
- if (!m_PluginList.isEnabled(pluginName)) {
+ if (!m_OrganizerCore.pluginList()->isEnabled(pluginName)) {
missingPlugins[pluginName] = std::vector<QString>();
}
}
@@ -4064,8 +3155,8 @@ void MainWindow::fixMods_clicked() }
// search in mods
- for (unsigned int i = 0; i < m_CurrentProfile->numRegularMods(); ++i) {
- int modIndex = m_CurrentProfile->modIndexByPriority(i);
+ for (unsigned int i = 0; i < m_OrganizerCore.currentProfile()->numRegularMods(); ++i) {
+ int modIndex = m_OrganizerCore.currentProfile()->modIndexByPriority(i);
ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
QStringList esps = QDir(modInfo->absolutePath()).entryList(espFilter);
@@ -4097,18 +3188,18 @@ void MainWindow::fixMods_clicked() for (std::set<QString>::iterator iter = modsToActivate.begin(); iter != modsToActivate.end(); ++iter) {
if ((*iter != "<data>") && (*iter != "<overwrite>")) {
unsigned int modIndex = ModInfo::getIndex(*iter);
- m_CurrentProfile->setModEnabled(modIndex, true);
+ m_OrganizerCore.currentProfile()->setModEnabled(modIndex, true);
}
}
- m_CurrentProfile->writeModlist();
- refreshLists();
+ m_OrganizerCore.currentProfile()->writeModlist();
+ m_OrganizerCore.refreshLists();
std::set<QString> espsToActivate = dialog.getESPsToActivate();
for (std::set<QString>::iterator iter = espsToActivate.begin(); iter != espsToActivate.end(); ++iter) {
- m_PluginList.enableESP(*iter);
+ m_OrganizerCore.pluginList()->enableESP(*iter);
}
- saveCurrentLists();
+ m_OrganizerCore.saveCurrentLists();
}
}
@@ -4135,7 +3226,7 @@ void MainWindow::on_savegameList_customContextMenuRequested(const QPoint &pos) void MainWindow::linkToolbar()
{
const Executable &selectedExecutable = ui->executablesListBox->itemData(ui->executablesListBox->currentIndex()).value<Executable>();
- Executable &exe = m_ExecutablesList.find(selectedExecutable.m_Title);
+ Executable &exe = m_OrganizerCore.executablesList()->find(selectedExecutable.m_Title);
exe.m_Toolbar = !exe.m_Toolbar;
ui->linkButton->menu()->actions().at(2)->setIcon(exe.m_Toolbar ? QIcon(":/MO/gui/remove") : QIcon(":/MO/gui/link"));
updateToolBar();
@@ -4208,44 +3299,44 @@ void MainWindow::linkMenu() void MainWindow::downloadSpeed(const QString &serverName, int bytesPerSecond)
{
- m_Settings.setDownloadSpeed(serverName, bytesPerSecond);
+ m_OrganizerCore.settings().setDownloadSpeed(serverName, bytesPerSecond);
}
void MainWindow::on_actionSettings_triggered()
{
- QString oldModDirectory(m_Settings.getModDirectory());
- QString oldCacheDirectory(m_Settings.getCacheDirectory());
- bool oldDisplayForeign(m_Settings.displayForeign());
- bool proxy = m_Settings.useProxy();
- m_Settings.query(this);
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory());
+ QString oldModDirectory(m_OrganizerCore.settings().getModDirectory());
+ QString oldCacheDirectory(m_OrganizerCore.settings().getCacheDirectory());
+ bool oldDisplayForeign(m_OrganizerCore.settings().displayForeign());
+ bool proxy = m_OrganizerCore.settings().useProxy();
+ m_OrganizerCore.settings().query(this);
+ m_OrganizerCore.installationManager()->setModsDirectory(m_OrganizerCore.settings().getModDirectory());
+ m_OrganizerCore.installationManager()->setDownloadDirectory(m_OrganizerCore.settings().getDownloadDirectory());
fixCategories();
refreshFilters();
- if (QDir::fromNativeSeparators(m_DownloadManager.getOutputDirectory()) != QDir::fromNativeSeparators(m_Settings.getDownloadDirectory())) {
- if (m_DownloadManager.downloadsInProgress()) {
+ if (QDir::fromNativeSeparators(m_OrganizerCore.downloadManager()->getOutputDirectory()) != QDir::fromNativeSeparators(m_OrganizerCore.settings().getDownloadDirectory())) {
+ if (m_OrganizerCore.downloadManager()->downloadsInProgress()) {
MessageDialog::showMessage(tr("Can't change download directory while downloads are in progress!"), this);
} else {
- m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory());
+ m_OrganizerCore.downloadManager()->setOutputDirectory(m_OrganizerCore.settings().getDownloadDirectory());
}
}
- m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
+ m_OrganizerCore.downloadManager()->setPreferredServers(m_OrganizerCore.settings().getPreferredServers());
- if ((m_Settings.getModDirectory() != oldModDirectory)
- || (m_Settings.displayForeign() != oldDisplayForeign)) {
- profileRefresh();
+ if ((m_OrganizerCore.settings().getModDirectory() != oldModDirectory)
+ || (m_OrganizerCore.settings().displayForeign() != oldDisplayForeign)) {
+ m_OrganizerCore.profileRefresh();
}
- if (m_Settings.getCacheDirectory() != oldCacheDirectory) {
- NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory());
+ if (m_OrganizerCore.settings().getCacheDirectory() != oldCacheDirectory) {
+ NexusInterface::instance()->setCacheDirectory(m_OrganizerCore.settings().getCacheDirectory());
}
- if (proxy != m_Settings.useProxy()) {
- activateProxy(m_Settings.useProxy());
+ if (proxy != m_OrganizerCore.settings().useProxy()) {
+ activateProxy(m_OrganizerCore.settings().useProxy());
}
- NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion());
+ NexusInterface::instance()->setNMMVersion(m_OrganizerCore.settings().getNMMVersion());
updateDownloadListDelegate();
}
@@ -4270,58 +3361,12 @@ void MainWindow::linkClicked(const QString &url) }
-bool MainWindow::nexusLogin()
-{
- QString username, password;
-
- NXMAccessManager *accessManager = NexusInterface::instance()->getAccessManager();
-
- if (!accessManager->loginAttempted()
- && !accessManager->loggedIn()
- && (m_Settings.getNexusLogin(username, password)
- || (m_AskForNexusPW
- && queryLogin(username, password)))) {
- accessManager->login(username, password);
- return true;
- } else {
- return false;
- }
-}
-
-
-void MainWindow::downloadRequestedNXM(const QString &url)
-{
- qDebug("download requested: %s", qPrintable(url));
- if (nexusLogin()) {
- m_PendingDownloads.append(url);
- } else {
- m_DownloadManager.addNXMDownload(url);
- }
-}
-
-
-void MainWindow::downloadRequested(QNetworkReply *reply, int modID, const QString &fileName)
-{
- try {
- if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID, 0, new ModRepositoryFileInfo(modID))) {
- MessageDialog::showMessage(tr("Download started"), this);
- }
- } catch (const std::exception &e) {
- MessageDialog::showMessage(tr("Download failed"), this);
- qCritical("exception starting download: %s", e.what());
- }
-}
-
-
void MainWindow::installTranslator(const QString &name)
{
-/* if (m_CurrentLanguage == "en_US") {
- return;
- }*/
QTranslator *translator = new QTranslator(this);
QString fileName = name + "_" + m_CurrentLanguage;
if (!translator->load(fileName, qApp->applicationDirPath() + "/translations")) {
- if (m_CurrentLanguage != "en-US") {
+ if ((m_CurrentLanguage != "en-US") && (m_CurrentLanguage != "en_US")) {
qWarning("localization file %s not found", qPrintable(fileName));
} // we don't actually expect localization files for english
}
@@ -4358,8 +3403,8 @@ void MainWindow::languageChange(const QString &newLanguage) void MainWindow::installDownload(int index)
{
try {
- QString fileName = m_DownloadManager.getFilePath(index);
- int modID = m_DownloadManager.getModID(index);
+ QString fileName = m_OrganizerCore.downloadManager()->getFilePath(index);
+ int modID = m_OrganizerCore.downloadManager()->getModID(index);
GuessedValue<QString> modName;
// see if there already are mods with the specified mod id
@@ -4374,15 +3419,15 @@ void MainWindow::installDownload(int index) }
}
- m_CurrentProfile->writeModlistNow();
+ m_OrganizerCore.currentProfile()->writeModlistNow();
bool hasIniTweaks = false;
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
+ m_OrganizerCore.installationManager()->setModsDirectory(m_OrganizerCore.settings().getModDirectory());
+ if (m_OrganizerCore.installationManager()->install(fileName, modName, hasIniTweaks)) {
MessageDialog::showMessage(tr("Installation successful"), this);
refreshModList();
- QModelIndexList posList = m_ModList.match(m_ModList.index(0, 0), Qt::DisplayRole, static_cast<const QString&>(modName));
+ QModelIndexList posList = m_OrganizerCore.modList()->match(m_OrganizerCore.modList()->index(0, 0), Qt::DisplayRole, static_cast<const QString&>(modName));
if (posList.count() == 1) {
ui->modList->scrollTo(posList.at(0));
}
@@ -4401,10 +3446,10 @@ void MainWindow::installDownload(int index) } else {
reportError(tr("mod \"%1\" not found").arg(modName));
}
- m_DownloadManager.markInstalled(index);
+ m_OrganizerCore.downloadManager()->markInstalled(index);
emit modInstalled();
- } else if (m_InstallationManager.wasCancelled()) {
+ } else if (m_OrganizerCore.installationManager()->wasCancelled()) {
QMessageBox::information(this, tr("Installation cancelled"), tr("The mod was not installed completely."), QMessageBox::Ok);
}
} catch (const std::exception &e) {
@@ -4434,7 +3479,7 @@ void MainWindow::writeDataToFile(QFile &file, const QString &directory, const Di file.write(fullName.toUtf8());
file.write("\t(");
- file.write(ToQString(m_DirectoryStructure->getOriginByID(origin).getName()).toUtf8());
+ file.write(ToQString(m_OrganizerCore.directoryStructure()->getOriginByID(origin).getName()).toUtf8());
file.write(")\r\n");
}
}
@@ -4457,7 +3502,7 @@ void MainWindow::writeDataToFile() reportError(tr("failed to write to file %1").arg(fileName));
}
- writeDataToFile(file, "data", *m_DirectoryStructure);
+ writeDataToFile(file, "data", *m_OrganizerCore.directoryStructure());
file.close();
MessageDialog::showMessage(tr("%1 written").arg(QDir::toNativeSeparators(fileName)), this);
@@ -4485,7 +3530,7 @@ int MainWindow::getBinaryExecuteInfo(const QFileInfo &targetInfo, if (::FindExecutableW(targetPathW.c_str(), NULL, buffer) > (HINSTANCE)32) {
DWORD binaryType = 0UL;
if (!::GetBinaryTypeW(targetPathW.c_str(), &binaryType)) {
- qDebug("failed to determine binary type: %lu", ::GetLastError());
+ qDebug("failed to determine binary type of \"%ls\": %lu", targetPathW.c_str(), ::GetLastError());
} else if (binaryType == SCS_32BIT_BINARY) {
binaryPath = ToQString(buffer);
}
@@ -4529,9 +3574,9 @@ void MainWindow::addAsExecutable() tr("Please enter a name for the executable"), QLineEdit::Normal,
targetInfo.baseName());
if (!name.isEmpty()) {
- m_ExecutablesList.addExecutable(name, binaryInfo.absoluteFilePath(),
+ m_OrganizerCore.executablesList()->addExecutable(name, binaryInfo.absoluteFilePath(),
arguments, targetInfo.absolutePath(),
- DEFAULT_STAY, QString(),
+ ExecutableInfo::CloseMOStyle::DEFAULT_STAY, QString(),
true, false);
refreshExecutablesList();
}
@@ -4549,10 +3594,10 @@ void MainWindow::addAsExecutable() void MainWindow::originModified(int originID)
{
- FilesOrigin &origin = m_DirectoryStructure->getOriginByID(originID);
+ FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByID(originID);
origin.enable(false);
- m_DirectoryStructure->addFromOrigin(origin.getName(), origin.getPath(), origin.getPriority());
- DirectoryRefresher::cleanStructure(m_DirectoryStructure);
+ m_OrganizerCore.directoryStructure()->addFromOrigin(origin.getName(), origin.getPath(), origin.getPriority());
+ DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure());
}
@@ -4613,11 +3658,11 @@ void MainWindow::previewDataFile() // what we want is the path relative to the virtual data directory
// crude: we search for the next slash after the base mod directory to skip everything up to the data-relative directory
- int offset = m_Settings.getModDirectory().size() + 1;
+ int offset = m_OrganizerCore.settings().getModDirectory().size() + 1;
offset = fileName.indexOf("/", offset);
fileName = fileName.mid(offset + 1);
- const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(fileName), NULL);
+ const FileEntry::Ptr file = m_OrganizerCore.directoryStructure()->searchFile(ToWString(fileName), NULL);
if (file.get() == NULL) {
reportError(tr("file not found: %1").arg(fileName));
@@ -4627,12 +3672,12 @@ void MainWindow::previewDataFile() // set up preview dialog
PreviewDialog preview(fileName);
auto addFunc = [&] (int originId) {
- FilesOrigin &origin = m_DirectoryStructure->getOriginByID(originId);
+ FilesOrigin &origin = m_OrganizerCore.directoryStructure()->getOriginByID(originId);
QString filePath = QDir::fromNativeSeparators(ToQString(origin.getPath())) + "/" + fileName;
if (QFile::exists(filePath)) {
// it's very possible the file doesn't exist, because it's inside an archive. we don't support that
- QWidget *wid = m_PreviewGenerator.genPreview(filePath);
- if (wid == NULL) {
+ QWidget *wid = m_PluginContainer.previewGenerator().genPreview(filePath);
+ if (wid == nullptr) {
reportError(tr("failed to generate preview for %1").arg(filePath));
} else {
preview.addVariant(ToQString(origin.getName()), wid);
@@ -4659,7 +3704,7 @@ void MainWindow::openDataFile() QString arguments;
switch (getBinaryExecuteInfo(targetInfo, binaryInfo, arguments)) {
case 1: {
- spawnBinaryDirect(binaryInfo, arguments, m_CurrentProfile->getName(), targetInfo.absolutePath(), "");
+ spawnBinaryDirect(binaryInfo, arguments, m_OrganizerCore.currentProfile()->getName(), targetInfo.absolutePath(), "");
} break;
case 2: {
::ShellExecuteW(NULL, L"open", ToWString(targetInfo.absoluteFilePath()).c_str(), NULL, NULL, SW_SHOWNORMAL);
@@ -4691,10 +3736,10 @@ void MainWindow::motdReceived(const QString &motd) // internet connection is faster next time
if (m_StartTime.secsTo(QTime::currentTime()) < 5) {
uint hash = qHash(motd);
- if (hash != m_Settings.getMotDHash()) {
+ if (hash != m_OrganizerCore.settings().getMotDHash()) {
MotDDialog dialog(motd);
dialog.exec();
- m_Settings.setMotDHash(hash);
+ m_OrganizerCore.settings().setMotDHash(hash);
}
}
@@ -4719,7 +3764,7 @@ void MainWindow::on_dataTree_customContextMenuRequested(const QPoint &pos) menu.addAction(tr("Add as Executable"), this, SLOT(addAsExecutable()));
QString fileName = m_ContextItem->text(0);
- if (m_PreviewGenerator.previewSupported(QFileInfo(fileName).completeSuffix())) {
+ if (m_PluginContainer.previewGenerator().previewSupported(QFileInfo(fileName).completeSuffix())) {
menu.addAction(tr("Preview"), this, SLOT(previewDataFile()));
}
@@ -4748,11 +3793,7 @@ void MainWindow::on_conflictsCheckBox_toggled(bool) void MainWindow::on_actionUpdate_triggered()
{
- if (nexusLogin()) {
- m_PostLoginTasks.push_back([&](MainWindow*) { m_Updater.startUpdate(); });
- } else {
- m_Updater.startUpdate();
- }
+ m_OrganizerCore.startMOUpdate();
}
@@ -4768,16 +3809,22 @@ void MainWindow::on_actionEndorseMO_triggered() void MainWindow::updateDownloadListDelegate()
{
- if (m_Settings.compactDownloads()) {
- ui->downloadView->setItemDelegate(new DownloadListWidgetCompactDelegate(&m_DownloadManager, m_Settings.metaDownloads(),
- ui->downloadView, ui->downloadView));
+ if (m_OrganizerCore.settings().compactDownloads()) {
+ ui->downloadView->setItemDelegate(
+ new DownloadListWidgetCompactDelegate(m_OrganizerCore.downloadManager(),
+ m_OrganizerCore.settings().metaDownloads(),
+ ui->downloadView,
+ ui->downloadView));
} else {
- ui->downloadView->setItemDelegate(new DownloadListWidgetDelegate(&m_DownloadManager, m_Settings.metaDownloads(),
- ui->downloadView, ui->downloadView));
+ ui->downloadView->setItemDelegate(
+ new DownloadListWidgetDelegate(m_OrganizerCore.downloadManager(),
+ m_OrganizerCore.settings().metaDownloads(),
+ ui->downloadView,
+ ui->downloadView));
}
- DownloadListSortProxy *sortProxy = new DownloadListSortProxy(&m_DownloadManager, ui->downloadView);
- sortProxy->setSourceModel(new DownloadList(&m_DownloadManager, ui->downloadView));
+ DownloadListSortProxy *sortProxy = new DownloadListSortProxy(m_OrganizerCore.downloadManager(), ui->downloadView);
+ sortProxy->setSourceModel(new DownloadList(m_OrganizerCore.downloadManager(), ui->downloadView));
connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), sortProxy, SLOT(updateFilter(QString)));
connect(ui->downloadFilterEdit, SIGNAL(textChanged(QString)), this, SLOT(downloadFilterChanged(QString)));
@@ -4786,11 +3833,11 @@ void MainWindow::updateDownloadListDelegate() ui->downloadView->header()->resizeSections(QHeaderView::Fixed);
connect(ui->downloadView->itemDelegate(), SIGNAL(installDownload(int)), this, SLOT(installDownload(int)));
- connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), &m_DownloadManager, SLOT(queryInfo(int)));
- connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), &m_DownloadManager, SLOT(removeDownload(int, bool)));
- connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), &m_DownloadManager, SLOT(restoreDownload(int)));
- connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), &m_DownloadManager, SLOT(cancelDownload(int)));
- connect(ui->downloadView->itemDelegate(), SIGNAL(pauseDownload(int)), &m_DownloadManager, SLOT(pauseDownload(int)));
+ connect(ui->downloadView->itemDelegate(), SIGNAL(queryInfo(int)), m_OrganizerCore.downloadManager(), SLOT(queryInfo(int)));
+ connect(ui->downloadView->itemDelegate(), SIGNAL(removeDownload(int, bool)), m_OrganizerCore.downloadManager(), SLOT(removeDownload(int, bool)));
+ connect(ui->downloadView->itemDelegate(), SIGNAL(restoreDownload(int)), m_OrganizerCore.downloadManager(), SLOT(restoreDownload(int)));
+ connect(ui->downloadView->itemDelegate(), SIGNAL(cancelDownload(int)), m_OrganizerCore.downloadManager(), SLOT(cancelDownload(int)));
+ connect(ui->downloadView->itemDelegate(), SIGNAL(pauseDownload(int)), m_OrganizerCore.downloadManager(), SLOT(pauseDownload(int)));
connect(ui->downloadView->itemDelegate(), SIGNAL(resumeDownload(int)), this, SLOT(resumeDownload(int)));
}
@@ -4879,7 +3926,7 @@ void MainWindow::nxmDownloadURLs(int, int, QVariant, QVariant resultData, int) // other keys: ConnectedUsers, Country, URI
servers.append(info);
}
- m_Settings.updateServers(servers);
+ m_OrganizerCore.settings().updateServers(servers);
}
@@ -4894,62 +3941,6 @@ void MainWindow::nxmRequestFailed(int modID, int, QVariant, int, const QString & }
-void MainWindow::loginSuccessful(bool necessary)
-{
- if (necessary) {
- MessageDialog::showMessage(tr("login successful"), this);
- }
- foreach (QString url, m_PendingDownloads) {
- downloadRequestedNXM(url);
- }
- m_PendingDownloads.clear();
- foreach (auto task, m_PostLoginTasks) {
- task(this);
- }
-
- m_PostLoginTasks.clear();
- NexusInterface::instance()->loginCompleted();
-}
-
-
-void MainWindow::loginSuccessfulUpdate(bool necessary)
-{
- if (necessary) {
- MessageDialog::showMessage(tr("login successful"), this);
- }
- m_Updater.startUpdate();
-}
-
-
-void MainWindow::loginFailed(const QString &message)
-{
- if (!m_PendingDownloads.isEmpty()) {
- MessageDialog::showMessage(tr("login failed: %1. Trying to download anyway").arg(message), this);
- foreach (QString url, m_PendingDownloads) {
- downloadRequestedNXM(url);
- }
- m_PendingDownloads.clear();
- } else {
- MessageDialog::showMessage(tr("login failed: %1").arg(message), this);
- m_PostLoginTasks.clear();
- statusBar()->hide();
- }
- NexusInterface::instance()->loginCompleted();
-}
-
-
-void MainWindow::loginFailedUpdate(const QString &message)
-{
- MessageDialog::showMessage(tr("login failed: %1. You need to log-in with Nexus to update MO.").arg(message), this);
-}
-
-
-void MainWindow::windowTutorialFinished(const QString &windowName)
-{
- m_Settings.directInterface().setValue(QString("CompletedWindowTutorials/") + windowName, true);
-}
-
-
BSA::EErrorCode MainWindow::extractBSA(BSA::Archive &archive, BSA::Folder::Ptr folder, const QString &destination,
QProgressDialog &progress)
{
@@ -5007,7 +3998,7 @@ void MainWindow::extractBSATriggered() QString targetFolder = FileDialogMemory::getExistingDirectory("extractBSA", this, tr("Extract BSA"));
if (!targetFolder.isEmpty()) {
BSA::Archive archive;
- QString originPath = QDir::fromNativeSeparators(ToQString(m_DirectoryStructure->getOriginByName(ToWString(item->text(1))).getPath()));
+ QString originPath = QDir::fromNativeSeparators(ToQString(m_OrganizerCore.directoryStructure()->getOriginByName(ToWString(item->text(1))).getPath()));
QString archivePath = QString("%1\\%2").arg(originPath).arg(item->text(0));
BSA::EErrorCode result = archive.read(archivePath.toLocal8Bit().constData(), true);
@@ -5088,10 +4079,7 @@ void MainWindow::on_bsaList_itemChanged(QTreeWidgetItem*, int) void MainWindow::on_actionProblems_triggered()
{
-// QString problemDescription;
-// checkForProblems(problemDescription);
-// QMessageBox::information(this, tr("Problems"), problemDescription);
- ProblemsDialog problems(m_DiagnosisPlugins, this);
+ ProblemsDialog problems(m_PluginContainer.plugins<IPluginDiagnose>(), this);
if (problems.hasProblems()) {
problems.exec();
updateProblemsButton();
@@ -5142,10 +4130,10 @@ void MainWindow::updateESPLock(bool locked) QItemSelection currentSelection = ui->espList->selectionModel()->selection();
if (currentSelection.count() == 0) {
// this path is probably useless
- m_PluginList.lockESPIndex(m_ContextRow, locked);
+ m_OrganizerCore.pluginList()->lockESPIndex(m_ContextRow, locked);
} else {
Q_FOREACH (const QModelIndex &idx, currentSelection.indexes()) {
- m_PluginList.lockESPIndex(mapToModel(&m_PluginList, idx).row(), locked);
+ m_OrganizerCore.pluginList()->lockESPIndex(mapToModel(m_OrganizerCore.pluginList(), idx).row(), locked);
}
}
}
@@ -5165,7 +4153,7 @@ void MainWindow::unlockESPIndex() void MainWindow::removeFromToolbar()
{
try {
- Executable &exe = m_ExecutablesList.find(m_ContextAction->text());
+ Executable &exe = m_OrganizerCore.executablesList()->find(m_ContextAction->text());
exe.m_Toolbar = false;
} catch (const std::runtime_error&) {
qDebug("executable doesn't exist any more");
@@ -5193,16 +4181,16 @@ void MainWindow::on_espList_customContextMenuRequested(const QPoint &pos) m_ContextRow = m_PluginListSortProxy->mapToSource(ui->espList->indexAt(pos)).row();
QMenu menu;
- menu.addAction(tr("Enable all"), &m_PluginList, SLOT(enableAll()));
- menu.addAction(tr("Disable all"), &m_PluginList, SLOT(disableAll()));
+ menu.addAction(tr("Enable all"), m_OrganizerCore.pluginList(), SLOT(enableAll()));
+ menu.addAction(tr("Disable all"), m_OrganizerCore.pluginList(), SLOT(disableAll()));
QItemSelection currentSelection = ui->espList->selectionModel()->selection();
bool hasLocked = false;
bool hasUnlocked = false;
Q_FOREACH (const QModelIndex &idx, currentSelection.indexes()) {
int row = m_PluginListSortProxy->mapToSource(idx).row();
- if (m_PluginList.isEnabled(row)) {
- if (m_PluginList.isESPLocked(row)) {
+ if (m_OrganizerCore.pluginList()->isEnabled(row)) {
+ if (m_OrganizerCore.pluginList()->isESPLocked(row)) {
hasLocked = true;
} else {
hasUnlocked = true;
@@ -5236,11 +4224,11 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) QAbstractProxyModel *newModel = NULL;
switch (index) {
case 1: {
- newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole,
+ newModel = new QtGroupingProxy(m_OrganizerCore.modList(), QModelIndex(), ModList::COL_CATEGORY, Qt::UserRole,
0, Qt::UserRole + 2);
} break;
case 2: {
- newModel = new QtGroupingProxy(&m_ModList, QModelIndex(), ModList::COL_MODID, Qt::DisplayRole,
+ newModel = new QtGroupingProxy(m_OrganizerCore.modList(), QModelIndex(), ModList::COL_MODID, Qt::DisplayRole,
QtGroupingProxy::FLAG_NOGROUPNAME | QtGroupingProxy::FLAG_NOSINGLE,
Qt::UserRole + 2);
} break;
@@ -5258,7 +4246,7 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index) connect(ui->modList, SIGNAL(collapsed(QModelIndex)), newModel, SLOT(collapsed(QModelIndex)));
connect(newModel, SIGNAL(expandItem(QModelIndex)), this, SLOT(expandModList(QModelIndex)));
} else {
- m_ModListSortProxy->setSourceModel(&m_ModList);
+ m_ModListSortProxy->setSourceModel(m_OrganizerCore.modList());
}
modFilterActive(m_ModListSortProxy->isFilterActive());
}
@@ -5280,7 +4268,7 @@ void MainWindow::on_linkButton_pressed() void MainWindow::on_showHiddenBox_toggled(bool checked)
{
- m_DownloadManager.setShowHidden(checked);
+ m_OrganizerCore.downloadManager()->setShowHidden(checked);
}
@@ -5334,13 +4322,10 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU foreach (const std::string &line, lines) {
if (line.length() > 0) {
- size_t progidx = line.find("[progress]");
- size_t reportidx = line.find("[Report]");
- size_t erroridx = line.find("[error]");
+ size_t progidx = line.find("[progress]");
+ size_t erroridx = line.find("[error]");
if (progidx != std::string::npos) {
dialog.setLabelText(line.substr(progidx + 11).c_str());
- } else if (reportidx != std::string::npos) {
- reportURL = line.substr(reportidx + 9);
} else if (erroridx != std::string::npos) {
qWarning("%s", line.c_str());
errorMessages.append(boost::algorithm::trim_copy(line.substr(erroridx + 8)) + "\n");
@@ -5349,11 +4334,11 @@ void MainWindow::processLOOTOut(const std::string &lootOut, std::string &reportU if (std::tr1::regex_match(line, match, exRequires)) {
std::string modName(match[1].first, match[1].second);
std::string dependency(match[2].first, match[2].second);
- m_PluginList.addInformation(modName.c_str(), tr("depends on missing \"%1\"").arg(dependency.c_str()));
+ m_OrganizerCore.pluginList()->addInformation(modName.c_str(), tr("depends on missing \"%1\"").arg(dependency.c_str()));
} else if (std::tr1::regex_match(line, match, exIncompatible)) {
std::string modName(match[1].first, match[1].second);
std::string dependency(match[2].first, match[2].second);
- m_PluginList.addInformation(modName.c_str(), tr("incompatible with \"%1\"").arg(dependency.c_str()));
+ m_OrganizerCore.pluginList()->addInformation(modName.c_str(), tr("incompatible with \"%1\"").arg(dependency.c_str()));
} else {
qDebug("[loot] %s", line.c_str());
}
@@ -5370,8 +4355,8 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList QString currentDirectory = cwd;
QString profileName = profile;
if (profile.length() == 0) {
- if (m_CurrentProfile != NULL) {
- profileName = m_CurrentProfile->getName();
+ if (m_OrganizerCore.currentProfile() != NULL) {
+ profileName = m_OrganizerCore.currentProfile()->getName();
} else {
throw MyException(tr("No profile set"));
}
@@ -5379,18 +4364,29 @@ HANDLE MainWindow::startApplication(const QString &executable, const QStringList QString steamAppID;
if (executable.contains('\\') || executable.contains('/')) {
// file path
+
binary = QFileInfo(executable);
if (binary.isRelative()) {
// relative path, should be relative to game directory
binary = QFileInfo(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/" + executable);
}
+
+ std::vector<Executable>::iterator current, end;
+ m_OrganizerCore.executablesList()->getExecutables(current, end);
+ for (; current != end; ++current) {
+ if (current->m_BinaryInfo == binary) {
+ steamAppID = current->m_SteamAppID;
+ currentDirectory = current->m_WorkingDirectory;
+ }
+ }
+
if (cwd.length() == 0) {
currentDirectory = binary.absolutePath();
}
} else {
// only a file name, search executables list
try {
- const Executable &exe = m_ExecutablesList.find(executable);
+ const Executable &exe = m_OrganizerCore.executablesList()->find(executable);
steamAppID = exe.m_SteamAppID;
if (arguments == "") {
arguments = exe.m_Arguments;
@@ -5472,7 +4468,7 @@ void MainWindow::on_bossButton_clicked() std::string reportURL;
std::string errorMessages;
- m_CurrentProfile->writeModlistNow();
+ m_OrganizerCore.currentProfile()->writeModlistNow();
bool success = false;
@@ -5484,12 +4480,15 @@ void MainWindow::on_bossButton_clicked() dialog.setMaximum(0);
dialog.show();
+ QString outPath = QDir::temp().absoluteFilePath("lootreport.json");
+
QStringList parameters;
parameters << "--unattended"
<< "--stdout"
<< "--noreport"
<< "--game" << ToQString(GameInfo::instance().getGameShortName())
- << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory()));
+ << "--gamePath" << QString("\"%1\"").arg(ToQString(GameInfo::instance().getGameDirectory()))
+ << "--out" << outPath;
if (m_DidUpdateMasterList) {
parameters << "--skipUpdateMasterlist";
@@ -5499,10 +4498,10 @@ void MainWindow::on_bossButton_clicked() HANDLE stdOutWrite = INVALID_HANDLE_VALUE;
HANDLE stdOutRead = INVALID_HANDLE_VALUE;
createStdoutPipe(&stdOutRead, &stdOutWrite);
- HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/LOOT.exe"),
+ HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"),
parameters.join(" "),
- m_CurrentProfile->getName(),
- m_Settings.logLevel(),
+ m_OrganizerCore.currentProfile()->getName(),
+ m_OrganizerCore.settings().logLevel(),
qApp->applicationDirPath() + "/loot",
true,
stdOutWrite);
@@ -5510,15 +4509,15 @@ void MainWindow::on_bossButton_clicked() // we don't use the write end
::CloseHandle(stdOutWrite);
- m_PluginList.clearAdditionalInformation();
+ m_OrganizerCore.pluginList()->clearAdditionalInformation();
DWORD retLen;
JOBOBJECT_BASIC_PROCESS_ID_LIST info;
- bool isJobHandle = true;
- ULONG lastProcessID;
HANDLE processHandle = loot;
if (loot != INVALID_HANDLE_VALUE) {
+ bool isJobHandle = true;
+ ULONG lastProcessID;
DWORD res = ::MsgWaitForMultipleObjects(1, &loot, false, 1000, QS_KEY | QS_MOUSE);
while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0)) {
if (isJobHandle) {
@@ -5574,6 +4573,22 @@ void MainWindow::on_bossButton_clicked() return;
} else {
success = true;
+ QFile outFile(outPath);
+ outFile.open(QIODevice::ReadOnly);
+ QJsonDocument doc = QJsonDocument::fromJson(outFile.readAll());
+ QJsonArray array = doc.array();
+ for (auto iter = array.begin(); iter != array.end(); ++iter) {
+ QJsonObject pluginObj = (*iter).toObject();
+ QJsonArray pluginMessages = pluginObj["messages"].toArray();
+ for (auto msgIter = pluginMessages.begin(); msgIter != pluginMessages.end(); ++msgIter) {
+ QJsonObject msg = (*msgIter).toObject();
+ m_OrganizerCore.pluginList()->addInformation(pluginObj["name"].toString(),
+ QString("%1: %2").arg(msg["type"].toString(), msg["message"].toString()));
+ }
+ if (pluginObj["dirty"].toString() == "yes")
+ m_OrganizerCore.pluginList()->addInformation(pluginObj["name"].toString(), "dirty");
+ }
+
}
} else {
reportError(tr("failed to start loot"));
@@ -5594,7 +4609,11 @@ void MainWindow::on_bossButton_clicked() QStringList temp = report.split("?");
QUrl url = QUrl::fromLocalFile(temp.at(0));
if (temp.size() > 1) {
+#if QT_VERSION >= 0x050000
url.setQuery(temp.at(1).toUtf8());
+#else
+ url.setEncodedQuery(temp.at(1).toUtf8());
+#endif
}
m_IntegratedBrowser.openUrl(url);
}
@@ -5602,9 +4621,9 @@ void MainWindow::on_bossButton_clicked() // if the game specifies load order by file time, our own load order file needs to be removed because it's outdated.
// refreshESPList will then use the file time as the load order.
if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
- QFile::remove(m_CurrentProfile->getLoadOrderFileName());
+ QFile::remove(m_OrganizerCore.currentProfile()->getLoadOrderFileName());
}
- refreshESPList();
+ m_OrganizerCore.refreshESPList();
}
}
@@ -5628,11 +4647,11 @@ bool MainWindow::createBackup(const QString &filePath, const QDateTime &time) void MainWindow::on_saveButton_clicked()
{
- savePluginList();
+ m_OrganizerCore.savePluginList();
QDateTime now = QDateTime::currentDateTime();
- if (createBackup(m_CurrentProfile->getPluginsFileName(), now)
- && createBackup(m_CurrentProfile->getLoadOrderFileName(), now)
- && createBackup(m_CurrentProfile->getLockedOrderFileName(), now)) {
+ if (createBackup(m_OrganizerCore.currentProfile()->getPluginsFileName(), now)
+ && createBackup(m_OrganizerCore.currentProfile()->getLoadOrderFileName(), now)
+ && createBackup(m_OrganizerCore.currentProfile()->getLockedOrderFileName(), now)) {
MessageDialog::showMessage(tr("Backup of load order created"), this);
}
}
@@ -5669,32 +4688,32 @@ QString MainWindow::queryRestore(const QString &filePath) void MainWindow::on_restoreButton_clicked()
{
- QString pluginName = m_CurrentProfile->getPluginsFileName();
+ QString pluginName = m_OrganizerCore.currentProfile()->getPluginsFileName();
QString choice = queryRestore(pluginName);
if (!choice.isEmpty()) {
- QString loadOrderName = m_CurrentProfile->getLoadOrderFileName();
- QString lockedName = m_CurrentProfile->getLockedOrderFileName();
+ QString loadOrderName = m_OrganizerCore.currentProfile()->getLoadOrderFileName();
+ QString lockedName = m_OrganizerCore.currentProfile()->getLockedOrderFileName();
if (!shellCopy(pluginName + "." + choice, pluginName, true, this) ||
!shellCopy(loadOrderName + "." + choice, loadOrderName, true, this) ||
!shellCopy(lockedName + "." + choice, lockedName, true, this)) {
QMessageBox::critical(this, tr("Restore failed"),
tr("Failed to restore the backup. Errorcode: %1").arg(windowsErrorString(::GetLastError())));
}
- refreshESPList();
+ m_OrganizerCore.refreshESPList();
}
}
void MainWindow::on_saveModsButton_clicked()
{
- m_CurrentProfile->writeModlistNow(true);
+ m_OrganizerCore.currentProfile()->writeModlistNow(true);
QDateTime now = QDateTime::currentDateTime();
- if (createBackup(m_CurrentProfile->getModlistFileName(), now)) {
+ if (createBackup(m_OrganizerCore.currentProfile()->getModlistFileName(), now)) {
MessageDialog::showMessage(tr("Backup of modlist created"), this);
}
}
void MainWindow::on_restoreModsButton_clicked()
{
- QString modlistName = m_CurrentProfile->getModlistFileName();
+ QString modlistName = m_OrganizerCore.currentProfile()->getModlistFileName();
QString choice = queryRestore(modlistName);
if (!choice.isEmpty()) {
if (!shellCopy(modlistName + "." + choice, modlistName, true, this)) {
@@ -5739,5 +4758,5 @@ void MainWindow::on_managedArchiveLabel_linkHovered(const QString&) void MainWindow::on_manageArchivesBox_toggled(bool)
{
- refreshBSAList();
+ m_OrganizerCore.refreshBSAList();
}
diff --git a/src/mainwindow.h b/src/mainwindow.h index 22152f1c..c8cb8152 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -32,14 +32,13 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "executableslist.h"
#include "modlist.h"
#include "pluginlist.h"
+#include "plugincontainer.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <archive.h>
#include "directoryrefresher.h"
#include <imoinfo.h>
-#include <iplugintool.h>
-#include <iplugindiagnose.h>
-#include <ipluginmodpage.h>
+#include <iplugingame.h>
#include "settings.h"
#include "downloadmanager.h"
#include "installationmanager.h"
@@ -51,9 +50,12 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "savegameinfowidgetgamebryo.h"
#include "previewgenerator.h"
#include "browserdialog.h"
+#include "iuserinterface.h"
#include <guessedvalue.h>
#include <directoryentry.h>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
+#endif
namespace Ui {
class MainWindow;
@@ -64,42 +66,24 @@ class ModListSortProxy; class ModListGroupCategoriesProxy;
-class MainWindow : public QMainWindow, public MOBase::IPluginDiagnose
+class MainWindow : public QMainWindow, public IUserInterface
{
Q_OBJECT
- Q_INTERFACES(MOBase::IPluginDiagnose)
friend class OrganizerProxy;
-private:
-
- struct SignalCombinerAnd
- {
- typedef bool result_type;
- template<typename InputIterator>
- bool operator()(InputIterator first, InputIterator last) const
- {
- while (first != last) {
- if (!(*first)) {
- return false;
- }
- ++first;
- }
- return true;
- }
- };
-
- typedef boost::signals2::signal<bool (const QString&), SignalCombinerAnd> SignalAboutToRunApplication;
- typedef boost::signals2::signal<void (const QString&)> SignalModInstalled;
public:
- explicit MainWindow(const QString &exeName, QSettings &initSettings, QWidget *parent = 0);
+ explicit MainWindow(const QString &exeName, QSettings &initSettings,
+ OrganizerCore &organizerCore, PluginContainer &pluginContainer,
+ QWidget *parent = 0);
~MainWindow();
+ void storeSettings(QSettings &settings);
void readSettings();
bool addProfile();
- void refreshBSAList();
+ void updateBSAList(const QStringList &defaultArchives, const QStringList &activeArchives);
void refreshDataTree();
void refreshSaveList();
@@ -113,21 +97,13 @@ public: void createFirstProfile();
-/* void spawnProgram(const QString &fileName, const QString &argumentsArg,
- const QString &profileName, const QDir ¤tDirectory);*/
-
- void loadPlugins();
+ bool saveArchiveList();
- virtual std::vector<unsigned int> activeProblems() const;
- virtual QString shortDescription(unsigned int key) const;
- virtual QString fullDescription(unsigned int key) const;
- virtual bool hasGuidedFix(unsigned int key) const;
- virtual void startGuidedFix(unsigned int key) const;
+ void registerPluginTool(MOBase::IPluginTool *tool);
+ void registerModPage(MOBase::IPluginModPage *modPage);
void addPrimaryCategoryCandidates(QMenu *primaryCategoryMenu, ModInfo::Ptr info);
- bool saveArchiveList();
-
void createStdoutPipe(HANDLE *stdOutRead, HANDLE *stdOutWrite);
std::string readFromPipe(HANDLE stdOutRead);
void processLOOTOut(const std::string &lootOut, std::string &reportURL, std::string &errorMessages, QProgressDialog &dialog);
@@ -138,14 +114,21 @@ public: void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
+ QString getOriginDisplayName(int originID);
-public slots:
+ void installTranslator(const QString &name);
- void refreshLists();
+ virtual void disconnectPlugins();
+
+ virtual bool close();
+ virtual void setEnabled(bool enabled);
+
+ void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab);
+
+public slots:
void displayColumnSelection(const QPoint &pos);
- void externalMessage(const QString &message);
void modorder_changed();
void refresher_progress(int percent);
void directory_refreshed();
@@ -155,11 +138,6 @@ public slots: signals:
- /**
- * @brief emitted after a mod has been installed
- * @node this is currently only used for tutorials
- */
- void modInstalled();
/**
* @brief emitted after the information dialog has been closed
@@ -183,40 +161,28 @@ protected: private:
- void refreshESPList();
void refreshModList(bool saveChanges = true);
void actionToToolButton(QAction *&sourceAction);
- bool verifyPlugin(MOBase::IPlugin *plugin);
- void registerPluginTool(MOBase::IPluginTool *tool);
- void registerModPage(MOBase::IPluginModPage *modPage);
- bool registerPlugin(QObject *pluginObj, const QString &fileName);
void updateToolBar();
void activateSelectedProfile();
void setExecutableIndex(int index);
- bool testForSteam();
void startSteam();
HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID);
- void spawnBinary(const QFileInfo &binary, const QString &arguments = "", const QDir ¤tDirectory = QDir(), bool closeAfterStart = true, const QString &steamAppID = "");
void updateTo(QTreeWidgetItem *subTree, const std::wstring &directorySoFar, const MOShared::DirectoryEntry &directoryEntry, bool conflictsOnly);
void refreshDirectoryStructure();
bool refreshProfiles(bool selectProfile = true);
void refreshExecutablesList();
void installMod();
- MOBase::IModInterface *installMod(const QString &fileName);
- MOBase::IModInterface *getMod(const QString &name);
- MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
- bool removeMod(MOBase::IModInterface *mod);
QList<MOBase::IOrganizer::FileInfo> findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const;
bool modifyExecutablesDialog();
- void displayModInformation(ModInfo::Ptr modInfo, unsigned int index, int tab);
void displayModInformation(int row, int tab = 0);
void testExtractBSA(int modIndex);
@@ -250,10 +216,6 @@ private: // remove invalid category-references from mods
void fixCategories();
- void storeSettings();
-
- bool queryLogin(QString &username, QString &password);
-
void createHelpWidget();
bool extractProgress(QProgressDialog &extractProgress, int percentage, std::string fileName);
@@ -282,7 +244,6 @@ private: static void setupNetworkProxy(bool activate);
void activateProxy(bool activate);
- void installTranslator(const QString &name);
void setBrowserGeometry(const QByteArray &geometry);
bool createBackup(const QString &filePath, const QDateTime &time);
@@ -294,13 +255,8 @@ private: void scheduleUpdateButton();
- void updateModActiveState(int index, bool active);
-
private:
- static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1;
- static const unsigned int PROBLEM_TOOMANYPLUGINS = 2;
-
static const char *PATTERN_BACKUP_GLOB;
static const char *PATTERN_BACKUP_REGEX;
static const char *PATTERN_BACKUP_DATE;
@@ -315,21 +271,15 @@ private: int m_OldProfileIndex;
- QThread m_RefresherThread;
- DirectoryRefresher m_DirectoryRefresher;
- MOShared::DirectoryEntry *m_DirectoryStructure;
std::vector<QString> m_ModNameList; // the mod-list to go with the directory structure
QProgressBar *m_RefreshProgress;
bool m_Refreshing;
- ModList m_ModList;
QAbstractItemModel *m_ModListGroupingProxy;
ModListSortProxy *m_ModListSortProxy;
- PluginList m_PluginList;
PluginListSortProxy *m_PluginListSortProxy;
- ExecutablesList m_ExecutablesList;
int m_OldExecutableIndex;
QString m_GamePath;
@@ -341,28 +291,12 @@ private: //int m_SelectedSaveGame;
- Settings m_Settings;
-
- DownloadManager m_DownloadManager;
- InstallationManager m_InstallationManager;
-
- SelfUpdater m_Updater;
-
CategoryFactory &m_CategoryFactory;
- Profile *m_CurrentProfile;
-
int m_ModsToUpdate;
- QStringList m_PendingDownloads;
- QList<boost::function<void (MainWindow*)> > m_PostLoginTasks;
- bool m_AskForNexusPW;
bool m_LoginAttempted;
- QStringList m_DefaultArchives;
- QStringList m_ActiveArchives;
- bool m_DirectoryUpdate;
- bool m_ArchivesInit;
QTimer m_CheckBSATimer;
QTimer m_SaveMetaTimer;
QTimer m_UpdateProblemsTimer;
@@ -370,21 +304,14 @@ private: QTime m_StartTime;
SaveGameInfoWidget *m_CurrentSaveView;
- MOBase::IGameInfo *m_GameInfo;
-
- std::vector<MOBase::IPluginDiagnose*> m_DiagnosisPlugins;
- std::vector<MOBase::IPluginModPage*> m_ModPages;
- std::vector<QString> m_UnloadedPlugins;
+ OrganizerCore &m_OrganizerCore;
+ PluginContainer &m_PluginContainer;
- QFile m_PluginsCheck;
-
- SignalAboutToRunApplication m_AboutToRun;
- SignalModInstalled m_ModInstalled;
+ MOBase::IPluginGame *m_ActiveGame;
QString m_CurrentLanguage;
std::vector<QTranslator*> m_Translators;
- PreviewGenerator m_PreviewGenerator;
BrowserDialog m_IntegratedBrowser;
QFileSystemWatcher m_SavesWatcher;
@@ -439,8 +366,6 @@ private slots: void modStatusChanged(unsigned int index);
void saveSelectionChanged(QListWidgetItem *newItem);
- bool saveCurrentLists();
-
void windowTutorialFinished(const QString &windowName);
BSA::EErrorCode extractBSA(BSA::Archive &archive, BSA::Folder::Ptr folder, const QString &destination, QProgressDialog &extractProgress);
@@ -449,8 +374,6 @@ private slots: void createModFromOverwrite();
- void removeOrigin(const QString &name);
-
void procError(QProcess::ProcessError error);
void procFinished(int exitCode, QProcess::ExitStatus exitStatus);
@@ -458,17 +381,9 @@ private slots: void checkModsForUpdates();
void nexusLinkActivated(const QString &link);
- void linkClicked(const QString &url);
-
- bool nexusLogin();
-
- void loginSuccessful(bool necessary);
- void loginSuccessfulUpdate(bool necessary);
void loginFailed(const QString &message);
- void loginFailedUpdate(const QString &message);
- void downloadRequestedNXM(const QString &url);
- void downloadRequested(QNetworkReply *reply, int modID, const QString &fileName);
+ void linkClicked(const QString &url);
void installDownload(int index);
void updateAvailable();
@@ -487,6 +402,8 @@ private slots: void modDetailsUpdated(bool success);
void modlistChanged(int row);
+ void modInstalled();
+
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);
@@ -519,7 +436,7 @@ private slots: void startExeAction();
- void checkBSAList();
+ void checkBSAList(const QStringList &defaultArchives);
void updateProblemsButton();
@@ -530,7 +447,6 @@ private slots: void modlistChanged(const QModelIndex &index, int role);
void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName);
- void savePluginList();
void modFilterActive(bool active);
void espFilterChanged(const QString &filter);
@@ -568,7 +484,6 @@ private slots: void modListSortIndicatorChanged(int column, Qt::SortOrder order);
private slots: // ui slots
- void profileRefresh();
// actions
void on_actionAdd_Profile_triggered();
void on_actionInstallMod_triggered();
@@ -611,6 +526,7 @@ private slots: // ui slots void on_categoriesOrBtn_toggled(bool checked);
void on_managedArchiveLabel_linkHovered(const QString &link);
void on_manageArchivesBox_toggled(bool checked);
+
};
diff --git a/src/messagedialog.cpp b/src/messagedialog.cpp index 863d7628..36902bbf 100644 --- a/src/messagedialog.cpp +++ b/src/messagedialog.cpp @@ -82,7 +82,7 @@ void MessageDialog::resizeEvent(QResizeEvent *event) void MessageDialog::showMessage(const QString &text, QWidget *reference, bool bringToFront)
{
qDebug("%s", qPrintable(text));
- if (reference != NULL) {
+ if (reference != nullptr) {
if (bringToFront || (qApp->activeWindow() != NULL)) {
MessageDialog *dialog = new MessageDialog(text, reference);
dialog->show();
diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 9558e03b..189e67b2 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -1,1051 +1,1049 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "modinfo.h"
-#include "utility.h"
-#include "installationtester.h"
-#include "categories.h"
-#include "report.h"
-#include "modinfodialog.h"
-#include "overwriteinfodialog.h"
-#include "json.h"
-#include "messagedialog.h"
-
-#include <gameinfo.h>
-#include <versioninfo.h>
-
-#include <QApplication>
-
-#include <QDirIterator>
-#include <QMutexLocker>
-#include <QSettings>
-#include <sstream>
-
-
-using namespace MOBase;
-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;
-int ModInfo::s_NextID;
-QMutex ModInfo::s_Mutex(QMutex::Recursive);
-
-QString ModInfo::s_HiddenExt(".mohidden");
-
-
-static bool ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS)
-{
- return QString::compare(LHS->name(), RHS->name(), Qt::CaseInsensitive) < 0;
-}
-
-
-ModInfo::Ptr ModInfo::createFrom(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));
- } else {
- result = ModInfo::Ptr(new ModInfoRegular(dir, directoryStructure));
- }
- s_Collection.push_back(result);
- return result;
-}
-
-ModInfo::Ptr ModInfo::createFromPlugin(const QString &espName, const QStringList &bsaNames
- , DirectoryEntry ** directoryStructure)
-{
- QMutexLocker locker(&s_Mutex);
- ModInfo::Ptr result = ModInfo::Ptr(new ModInfoForeign(espName, bsaNames, directoryStructure));
- s_Collection.push_back(result);
- return result;
-}
-
-QString ModInfo::getContentTypeName(int contentType)
-{
- switch (contentType) {
- case CONTENT_PLUGIN: return tr("Plugins");
- case CONTENT_TEXTURE: return tr("Textures");
- case CONTENT_MESH: return tr("Meshes");
- case CONTENT_INTERFACE: return tr("UI Changes");
- case CONTENT_MUSIC: return tr("Music");
- case CONTENT_SOUND: return tr("Sound Effects");
- case CONTENT_SCRIPT: return tr("Scripts");
- case CONTENT_SKSE: return tr("SKSE Plugins");
- case CONTENT_SKYPROC: return tr("SkyProc Tools");
- case CONTENT_STRING: return tr("Strings");
- default: throw MyException(tr("invalid content type %1").arg(contentType));
- }
-}
-
-void ModInfo::createFromOverwrite()
-{
- QMutexLocker locker(&s_Mutex);
-
- s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite));
-}
-
-unsigned int ModInfo::getNumMods()
-{
- QMutexLocker locker(&s_Mutex);
- return s_Collection.size();
-}
-
-
-ModInfo::Ptr ModInfo::getByIndex(unsigned int index)
-{
- QMutexLocker locker(&s_Mutex);
-
- if (index >= s_Collection.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
- return s_Collection[index];
-}
-
-
-std::vector<ModInfo::Ptr> ModInfo::getByModID(int modID)
-{
- QMutexLocker locker(&s_Mutex);
-
- auto iter = s_ModsByModID.find(modID);
- if (iter == s_ModsByModID.end()) {
- return std::vector<ModInfo::Ptr>();
- }
-
- std::vector<ModInfo::Ptr> result;
- for (auto idxIter = iter->second.begin(); idxIter != iter->second.end(); ++idxIter) {
- result.push_back(getByIndex(*idxIter));
- }
-
- return result;
-}
-
-
-bool ModInfo::removeMod(unsigned int index)
-{
- QMutexLocker locker(&s_Mutex);
-
- if (index >= s_Collection.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
-
- // update the indices first
- ModInfo::Ptr modInfo = s_Collection[index];
- s_ModsByName.erase(s_ModsByName.find(modInfo->name()));
-
- auto iter = s_ModsByModID.find(modInfo->getNexusID());
- if (iter != s_ModsByModID.end()) {
- std::vector<unsigned int> indices = iter->second;
- std::remove(indices.begin(), indices.end(), index);
- s_ModsByModID[modInfo->getNexusID()] = indices;
- }
-
- // physically remove the mod directory
- //TODO the return value is ignored because the indices were already removed here, so stopping
- // would cause data inconsistencies. Instead we go through with the removal but the mod will show up
- // again if the user refreshes
- modInfo->remove();
-
- // finally, remove the mod from the collection
- s_Collection.erase(s_Collection.begin() + index);
-
- // and update the indices
- updateIndices();
- return true;
-}
-
-
-unsigned int ModInfo::getIndex(const QString &name)
-{
- QMutexLocker locker(&s_Mutex);
-
- std::map<QString, unsigned int>::iterator iter = s_ModsByName.find(name);
- if (iter == s_ModsByName.end()) {
- return UINT_MAX;
- }
-
- return iter->second;
-}
-
-unsigned int ModInfo::findMod(const boost::function<bool (ModInfo::Ptr)> &filter)
-{
- for (unsigned int i = 0U; i < s_Collection.size(); ++i) {
- if (filter(s_Collection[i])) {
- return i;
- }
- }
- return UINT_MAX;
-}
-
-
-void ModInfo::updateFromDisc(const QString &modDirectory, DirectoryEntry **directoryStructure, bool displayForeign)
-{
- QMutexLocker lock(&s_Mutex);
- s_Collection.clear();
- s_NextID = 0;
-
- { // list all directories in the mod directory and make a mod out of each
- QDir mods(QDir::fromNativeSeparators(modDirectory));
- mods.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
- QDirIterator modIter(mods);
- while (modIter.hasNext()) {
- createFrom(QDir(modIter.next()), directoryStructure);
- }
- }
-
- { // list plugins in the data directory and make a foreign-managed mod out of each
- std::vector<std::wstring> dlcPlugins = GameInfo::instance().getDLCPlugins();
- QDir dataDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/data");
- foreach (const QFileInfo &file, dataDir.entryInfoList(QStringList() << "*.esp" << "*.esm")) {
- if ((file.baseName() != "Update") // hide update
- && (file.baseName() != ToQString(GameInfo::instance().getGameName())) // hide the game esp
- && (displayForeign // show non-dlc bundles only if the user wants them
- || std::find(dlcPlugins.begin(), dlcPlugins.end(), ToWString(file.fileName())) != dlcPlugins.end())) {
- QStringList archives;
- foreach (const QString archiveName, dataDir.entryList(QStringList() << file.baseName() + "*.bsa")) {
- archives.append(dataDir.absoluteFilePath(archiveName));
- }
-
- createFromPlugin(file.fileName(), archives, directoryStructure);
- }
- }
- }
-
- createFromOverwrite();
-
- std::sort(s_Collection.begin(), s_Collection.end(), ByName);
-
- updateIndices();
-}
-
-
-void ModInfo::updateIndices()
-{
- s_ModsByName.clear();
- s_ModsByModID.clear();
- QRegExp backupRegEx(".*backup[0-9]*$");
-
- for (unsigned int i = 0; i < s_Collection.size(); ++i) {
- QString modName = s_Collection[i]->internalName();
- int modID = s_Collection[i]->getNexusID();
- s_ModsByName[modName] = i;
- s_ModsByModID[modID].push_back(i);
- }
-}
-
-
-ModInfo::ModInfo()
- : m_Valid(false), m_PrimaryCategory(-1)
-{
-}
-
-
-void ModInfo::checkChunkForUpdate(const std::vector<int> &modIDs, QObject *receiver)
-{
- if (modIDs.size() != 0) {
- NexusInterface::instance()->requestUpdates(modIDs, receiver, QVariant(), QString());
- }
-}
-
-
-int ModInfo::checkAllForUpdate(QObject *receiver)
-{
- int result = 0;
- std::vector<int> modIDs;
-
- modIDs.push_back(GameInfo::instance().getNexusModID());
-
- for (std::vector<ModInfo::Ptr>::iterator iter = s_Collection.begin();
- iter != s_Collection.end(); ++iter) {
- if ((*iter)->canBeUpdated()) {
- modIDs.push_back((*iter)->getNexusID());
- if (modIDs.size() >= 255) {
- checkChunkForUpdate(modIDs, receiver);
- modIDs.clear();
- }
- }
- }
-
- checkChunkForUpdate(modIDs, receiver);
-
- return result;
-}
-
-void ModInfo::setVersion(const VersionInfo &version)
-{
- m_Version = version;
-}
-
-bool ModInfo::hasFlag(ModInfo::EFlag flag) const
-{
- std::vector<EFlag> flags = getFlags();
- return std::find(flags.begin(), flags.end(), flag) != flags.end();
-}
-
-bool ModInfo::hasContent(ModInfo::EContent content) const
-{
- std::vector<EContent> contents = getContents();
- return std::find(contents.begin(), contents.end(), content) != contents.end();
-}
-
-bool ModInfo::categorySet(int categoryID) const
-{
- for (std::set<int>::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) {
- if ((*iter == categoryID) ||
- (CategoryFactory::instance().isDecendantOf(*iter, categoryID))) {
- return true;
- }
- }
-
- return false;
-}
-
-
-void ModInfo::testValid()
-{
- m_Valid = false;
- QDirIterator dirIter(absolutePath());
- while (dirIter.hasNext()) {
- dirIter.next();
- if (dirIter.fileInfo().isDir()) {
- if (InstallationTester::isTopLevelDirectory(dirIter.fileName())) {
- m_Valid = true;
- break;
- }
- } else {
- if (InstallationTester::isTopLevelSuffix(dirIter.fileName())) {
- m_Valid = true;
- break;
- }
- }
- }
-
- // NOTE: in Qt 4.7 it seems that QDirIterator leaves a file handle open if it is not iterated to the
- // end
- while (dirIter.hasNext()) {
- dirIter.next();
- }
-}
-
-
-ModInfoWithConflictInfo::ModInfoWithConflictInfo(DirectoryEntry **directoryStructure)
- : m_DirectoryStructure(directoryStructure) {}
-
-void ModInfoWithConflictInfo::clearCaches()
-{
- m_LastConflictCheck = QTime();
-}
-
-std::vector<ModInfo::EFlag> ModInfoWithConflictInfo::getFlags() const
-{
- std::vector<ModInfo::EFlag> result;
- switch (isConflicted()) {
- case CONFLICT_MIXED: {
- result.push_back(ModInfo::FLAG_CONFLICT_MIXED);
- } break;
- case CONFLICT_OVERWRITE: {
- result.push_back(ModInfo::FLAG_CONFLICT_OVERWRITE);
- } break;
- case CONFLICT_OVERWRITTEN: {
- result.push_back(ModInfo::FLAG_CONFLICT_OVERWRITTEN);
- } break;
- case CONFLICT_REDUNDANT: {
- result.push_back(ModInfo::FLAG_CONFLICT_REDUNDANT);
- } break;
- default: { /* NOP */ }
- }
- return result;
-}
-
-
-void ModInfoWithConflictInfo::doConflictCheck() const
-{
- m_OverwriteList.clear();
- m_OverwrittenList.clear();
- bool regular = false;
-
- int dataID = 0;
- if ((*m_DirectoryStructure)->originExists(L"data")) {
- dataID = (*m_DirectoryStructure)->getOriginByName(L"data").getID();
- }
-
- std::wstring name = ToWString(this->name());
- if ((*m_DirectoryStructure)->originExists(name)) {
- FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name);
- std::vector<FileEntry::Ptr> files = origin.getFiles();
- // for all files in this origin
- for (auto iter = files.begin(); iter != files.end(); ++iter) {
- const std::vector<int> &alternatives = (*iter)->getAlternatives();
- if ((alternatives.size() == 0)
- || (alternatives[0] == dataID)) {
- // no alternatives -> no conflict
- regular = true;
- } else {
- if ((*iter)->getOrigin() != origin.getID()) {
- FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID((*iter)->getOrigin());
- unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName()));
- m_OverwrittenList.insert(altIndex);
- }
- // for all non-providing alternative origins
- for (auto altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) {
- if ((*altIter != dataID) && (*altIter != origin.getID())) {
- FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(*altIter);
- unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName()));
- if (origin.getPriority() > altOrigin.getPriority()) {
- m_OverwriteList.insert(altIndex);
- } else {
- m_OverwrittenList.insert(altIndex);
- }
- }
- }
- }
- }
- }
-
- m_LastConflictCheck = QTime::currentTime();
-
- if (!m_OverwriteList.empty() && !m_OverwrittenList.empty())
- m_CurrentConflictState = CONFLICT_MIXED;
- else if (!m_OverwriteList.empty())
- m_CurrentConflictState = CONFLICT_OVERWRITE;
- else if (!m_OverwrittenList.empty()) {
- if (!regular) {
- m_CurrentConflictState = CONFLICT_REDUNDANT;
- } else {
- m_CurrentConflictState = CONFLICT_OVERWRITTEN;
- }
- }
- else m_CurrentConflictState = CONFLICT_NONE;
-}
-
-ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isConflicted() const
-{
- // this is costy so cache the result
- QTime now = QTime::currentTime();
- if (m_LastConflictCheck.isNull() || (m_LastConflictCheck.secsTo(now) > 10)) {
- doConflictCheck();
- }
-
- return m_CurrentConflictState;
-}
-
-
-bool ModInfoWithConflictInfo::isRedundant() const
-{
- std::wstring name = ToWString(this->name());
- if ((*m_DirectoryStructure)->originExists(name)) {
- FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name);
- std::vector<FileEntry::Ptr> files = origin.getFiles();
- bool ignore = false;
- for (auto iter = files.begin(); iter != files.end(); ++iter) {
- if ((*iter)->getOrigin(ignore) == origin.getID()) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
-}
-
-
-
-ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStructure)
- : ModInfoWithConflictInfo(directoryStructure)
- , m_Name(path.dirName())
- , m_Path(path.absolutePath())
- , m_MetaInfoChanged(false)
- , m_EndorsedState(ENDORSED_UNKNOWN)
-{
- testValid();
- m_CreationTime = QFileInfo(path.absolutePath()).created();
- // read out the meta-file for information
- readMeta();
-
- 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)));
-}
-
-
-ModInfoRegular::~ModInfoRegular()
-{
- try {
- saveMeta();
- } catch (const std::exception &e) {
- qCritical("failed to save meta information for \"%s\": %s",
- m_Name.toUtf8().constData(), e.what());
- }
-}
-
-bool ModInfoRegular::isEmpty() const
-{
- QDirIterator iter(m_Path, QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- if (!iter.hasNext()) return true;
- iter.next();
- if ((iter.fileName() == "meta.ini") && !iter.hasNext()) return true;
- return false;
-}
-
-
-void ModInfoRegular::readMeta()
-{
- QSettings metaFile(m_Path + "/meta.ini", QSettings::IniFormat);
-
- m_Notes = metaFile.value("notes", "").toString();
- 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_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate);
- if (metaFile.contains("endorsed")) {
- if (metaFile.value("endorsed").canConvert<int>()) {
- switch (metaFile.value("endorsed").toInt()) {
- case ENDORSED_FALSE: m_EndorsedState = ENDORSED_FALSE; break;
- case ENDORSED_TRUE: m_EndorsedState = ENDORSED_TRUE; break;
- case ENDORSED_NEVER: m_EndorsedState = ENDORSED_NEVER; break;
- default: m_EndorsedState = ENDORSED_UNKNOWN; break;
- }
- } else {
- m_EndorsedState = metaFile.value("endorsed", false).toBool() ? ENDORSED_TRUE : ENDORSED_FALSE;
- }
- }
-
- QString categoriesString = metaFile.value("category", "").toString();
-
- QStringList categories = categoriesString.split(',', QString::SkipEmptyParts);
- for (QStringList::iterator iter = categories.begin(); iter != categories.end(); ++iter) {
- bool ok = false;
- int categoryID = iter->toInt(&ok);
- if (categoryID < 0) {
- // ignore invalid id
- continue;
- }
- if (ok && (categoryID != 0) && (CategoryFactory::instance().categoryExists(categoryID))) {
- m_Categories.insert(categoryID);
- if (iter == categories.begin()) {
- m_PrimaryCategory = categoryID;
- }
- }
- }
-
- m_MetaInfoChanged = false;
-}
-
-void ModInfoRegular::saveMeta()
-{
- // only write meta data if the mod directory exists
- if (m_MetaInfoChanged && QFile::exists(absolutePath())) {
- QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat);
- if (metaFile.status() == QSettings::NoError) {
- std::set<int> temp = m_Categories;
- temp.erase(m_PrimaryCategory);
- metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ","));
- metaFile.setValue("newestVersion", m_NewestVersion.canonicalString());
- metaFile.setValue("ignoredVersion", m_IgnoredVersion.canonicalString());
- metaFile.setValue("version", m_Version.canonicalString());
- if (m_NexusID != -1) {
- metaFile.setValue("modid", m_NexusID);
- }
- metaFile.setValue("notes", m_Notes);
- metaFile.setValue("nexusDescription", m_NexusDescription);
- metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate));
- if (m_EndorsedState != ENDORSED_UNKNOWN) {
- metaFile.setValue("endorsed", m_EndorsedState);
- }
- metaFile.sync(); // sync needs to be called to ensure the file is created
-
- if (metaFile.status() == QSettings::NoError) {
- m_MetaInfoChanged = false;
- } else {
- reportError(tr("failed to write %1/meta.ini: error %2").arg(absolutePath()).arg(metaFile.status()));
- }
- } else {
- reportError(tr("failed to write %1/meta.ini: error %2").arg(absolutePath()).arg(metaFile.status()));
- }
- }
-}
-
-
-bool ModInfoRegular::updateAvailable() const
-{
- if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
- return false;
- }
- return m_NewestVersion.isValid() && (m_Version < m_NewestVersion);
-}
-
-
-bool ModInfoRegular::downgradeAvailable() const
-{
- if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) {
- return false;
- }
- return m_NewestVersion.isValid() && (m_NewestVersion < m_Version);
-}
-
-
-void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData)
-{
- QVariantMap result = resultData.toMap();
- m_NewestVersion.parse(result["version"].toString());
- m_NexusDescription = result["description"].toString();
- if ((m_EndorsedState != ENDORSED_NEVER) && (result.contains("voted_by_user"))) {
- m_EndorsedState = result["voted_by_user"].toBool() ? ENDORSED_TRUE : ENDORSED_FALSE;
- }
- m_LastNexusQuery = QDateTime::currentDateTime();
- m_MetaInfoChanged = true;
- saveMeta();
- emit modDetailsUpdated(true);
-}
-
-
-void ModInfoRegular::nxmEndorsementToggled(int, QVariant, QVariant resultData)
-{
- m_EndorsedState = resultData.toBool() ? ENDORSED_TRUE : ENDORSED_FALSE;
- m_MetaInfoChanged = true;
- saveMeta();
- emit modDetailsUpdated(true);
-}
-
-
-void ModInfoRegular::nxmRequestFailed(int, int, QVariant userData, const QString &errorMessage)
-{
- QString fullMessage = errorMessage;
- if (userData.canConvert<int>() && (userData.toInt() == 1)) {
- fullMessage += "\nNexus will reject endorsements within 15 Minutes of a failed attempt, the error message may be misleading.";
- }
- if (QApplication::activeWindow() != NULL) {
- MessageDialog::showMessage(fullMessage, QApplication::activeWindow());
- }
- emit modDetailsUpdated(false);
-}
-
-
-bool ModInfoRegular::updateNXMInfo()
-{
- if (m_NexusID > 0) {
- m_NexusBridge.requestDescription(m_NexusID, QVariant());
- return true;
- }
- return false;
-}
-
-
-void ModInfoRegular::setCategory(int categoryID, bool active)
-{
- m_MetaInfoChanged = true;
-
- if (active) {
- m_Categories.insert(categoryID);
- if (m_PrimaryCategory == -1) {
- m_PrimaryCategory = categoryID;
- }
- } else {
- std::set<int>::iterator iter = m_Categories.find(categoryID);
- if (iter != m_Categories.end()) {
- m_Categories.erase(iter);
- }
- if (categoryID == m_PrimaryCategory) {
- if (m_Categories.size() == 0) {
- m_PrimaryCategory = -1;
- } else {
- m_PrimaryCategory = *(m_Categories.begin());
- }
- }
- }
-}
-
-
-bool ModInfoRegular::setName(const QString &name)
-{
- if (name.contains('/') || name.contains('\\')) {
- return false;
- }
-
- QString newPath = m_Path.mid(0).replace(m_Path.length() - m_Name.length(), m_Name.length(), name);
- QDir modDir(m_Path.mid(0, m_Path.length() - m_Name.length()));
-
- if (m_Name.compare(name, Qt::CaseInsensitive) == 0) {
- QString tempName = name;
- tempName.append("_temp");
- while (modDir.exists(tempName)) {
- tempName.append("_");
- }
- if (!modDir.rename(m_Name, tempName)) {
- return false;
- }
- if (!modDir.rename(tempName, name)) {
- qCritical("rename to final name failed after successful rename to intermediate name");
- modDir.rename(tempName, m_Name);
- return false;
- }
- } else {
- if (!shellRename(modDir.absoluteFilePath(m_Name), modDir.absoluteFilePath(name))) {
- qCritical("failed to rename mod %s (errorcode %d)",
- qPrintable(name), ::GetLastError());
- return false;
- }
- }
-
- std::map<QString, unsigned int>::iterator nameIter = s_ModsByName.find(m_Name);
- if (nameIter != s_ModsByName.end()) {
- unsigned int index = nameIter->second;
- s_ModsByName.erase(nameIter);
-
- m_Name = name;
- m_Path = newPath;
-
- s_ModsByName[m_Name] = index;
-
- std::sort(s_Collection.begin(), s_Collection.end(), ByName);
- updateIndices();
- } else { // otherwise mod isn't registered yet?
- m_Name = name;
- m_Path = newPath;
- }
-
- return true;
-}
-
-void ModInfoRegular::setNotes(const QString ¬es)
-{
- m_Notes = notes;
- m_MetaInfoChanged = true;
-}
-
-void ModInfoRegular::setNexusID(int modID)
-{
- m_NexusID = modID;
- m_MetaInfoChanged = true;
-}
-
-void ModInfoRegular::setVersion(const VersionInfo &version)
-{
- m_Version = version;
- m_MetaInfoChanged = true;
-}
-
-void ModInfoRegular::setNewestVersion(const VersionInfo &version) {
- m_NewestVersion = version;
-}
-
-void ModInfoRegular::setNexusDescription(const QString &description)
-{
- m_NexusDescription = description;
- m_MetaInfoChanged = true;
-}
-
-void ModInfoRegular::addNexusCategory(int categoryID)
-{
- m_Categories.insert(CategoryFactory::instance().resolveNexusID(categoryID));
-}
-
-void ModInfoRegular::setIsEndorsed(bool endorsed)
-{
- if (m_EndorsedState != ENDORSED_NEVER) {
- m_EndorsedState = endorsed ? ENDORSED_TRUE : ENDORSED_FALSE;
- m_MetaInfoChanged = true;
- }
-}
-
-
-void ModInfoRegular::setNeverEndorse()
-{
- m_EndorsedState = ENDORSED_NEVER;
- m_MetaInfoChanged = true;
-}
-
-
-bool ModInfoRegular::remove()
-{
- m_MetaInfoChanged = false;
- return shellDelete(QStringList(absolutePath()), true);
-}
-
-void ModInfoRegular::endorse(bool doEndorse)
-{
- if (doEndorse != (m_EndorsedState == ENDORSED_TRUE)) {
- m_NexusBridge.requestToggleEndorsement(getNexusID(), doEndorse, QVariant(1));
- }
-}
-
-
-QString ModInfoRegular::absolutePath() const
-{
- return m_Path;
-}
-
-void ModInfoRegular::ignoreUpdate(bool ignore)
-{
- if (ignore) {
- m_IgnoredVersion = m_NewestVersion;
- } else {
- m_IgnoredVersion.clear();
- }
- m_MetaInfoChanged = true;
-}
-
-
-std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const
-{
- std::vector<ModInfo::EFlag> result = ModInfoWithConflictInfo::getFlags();
- if ((m_NexusID != -1) && (endorsedState() == ENDORSED_FALSE)) {
- result.push_back(ModInfo::FLAG_NOTENDORSED);
- }
- if (!isValid()) {
- result.push_back(ModInfo::FLAG_INVALID);
- }
- if (m_Notes.length() != 0) {
- result.push_back(ModInfo::FLAG_NOTES);
- }
- return result;
-}
-
-
-std::vector<ModInfo::EContent> ModInfoRegular::getContents() const
-{
- std::vector<EContent> result;
- QDir dir(absolutePath());
- if (dir.entryList(QStringList() << "*.esp" << "*.esm").size() > 0) {
- result.push_back(CONTENT_PLUGIN);
- }
- QString sePluginPath = ToQString(GameInfo::instance().getSEName()) + "/plugins";
- if (dir.exists("textures")) result.push_back(CONTENT_TEXTURE);
- if (dir.exists("meshes")) result.push_back(CONTENT_MESH);
- if (dir.exists("interface")
- || dir.exists("menus")) result.push_back(CONTENT_INTERFACE);
- if (dir.exists("music")) result.push_back(CONTENT_MUSIC);
- if (dir.exists("sound")) result.push_back(CONTENT_SOUND);
- if (dir.exists("scripts")) result.push_back(CONTENT_SCRIPT);
- if (dir.exists(sePluginPath)) result.push_back(CONTENT_SKSE);
- if (dir.exists("strings")) result.push_back(CONTENT_STRING);
- if (dir.exists("SkyProc Patchers")) result.push_back(CONTENT_SKYPROC);
- return result;
-}
-
-
-int ModInfoRegular::getHighlight() const
-{
- return isValid() ? HIGHLIGHT_NONE: HIGHLIGHT_INVALID;
-}
-
-
-QString ModInfoRegular::getDescription() const
-{
- if (!isValid()) {
- return tr("%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory").arg(name());
- } else {
- const std::set<int> &categories = getCategories();
- std::wostringstream categoryString;
- categoryString << ToWString(tr("Categories: <br>"));
- CategoryFactory &categoryFactory = CategoryFactory::instance();
- for (std::set<int>::const_iterator catIter = categories.begin();
- catIter != categories.end(); ++catIter) {
- if (catIter != categories.begin()) {
- categoryString << " , ";
- }
- categoryString << "<span style=\"white-space: nowrap;\"><i>" << ToWString(categoryFactory.getCategoryName(categoryFactory.getCategoryIndex(*catIter))) << "</font></span>";
- }
-
- return ToQString(categoryString.str());
- }
-}
-
-QString ModInfoRegular::notes() const
-{
- return m_Notes;
-}
-
-QDateTime ModInfoRegular::creationTime() const
-{
- return m_CreationTime;
-}
-
-QString ModInfoRegular::getNexusDescription() const
-{
- return m_NexusDescription;
-}
-
-ModInfoRegular::EEndorsedState ModInfoRegular::endorsedState() const
-{
- return m_EndorsedState;
-}
-
-QDateTime ModInfoRegular::getLastNexusQuery() const
-{
- return m_LastNexusQuery;
-}
-
-
-QStringList ModInfoRegular::archives() const
-{
- QStringList result;
- QDir dir(this->absolutePath());
- foreach (const QString &archive, dir.entryList(QStringList("*.bsa"))) {
- result.append(this->absolutePath() + "/" + archive);
- }
- return result;
-}
-
-std::vector<QString> ModInfoRegular::getIniTweaks() const
-{
- QString metaFileName = absolutePath().append("/meta.ini");
- QSettings metaFile(metaFileName, QSettings::IniFormat);
-
- std::vector<QString> result;
-
- int numTweaks = metaFile.beginReadArray("INI Tweaks");
-
- if (numTweaks != 0) {
- qDebug("%d active ini tweaks in %s",
- numTweaks, QDir::toNativeSeparators(metaFileName).toUtf8().constData());
- }
-
- for (int i = 0; i < numTweaks; ++i) {
- metaFile.setArrayIndex(i);
- QString filename = absolutePath().append("/INI Tweaks/").append(metaFile.value("name").toString());
- result.push_back(filename);
- }
- metaFile.endArray();
- return result;
-}
-
-std::vector<ModInfo::EFlag> ModInfoBackup::getFlags() const
-{
- std::vector<ModInfo::EFlag> result = ModInfoRegular::getFlags();
- result.insert(result.begin(), ModInfo::FLAG_BACKUP);
- return result;
-}
-
-
-QString ModInfoBackup::getDescription() const
-{
- return tr("This is the backup of a mod");
-}
-
-
-ModInfoBackup::ModInfoBackup(const QDir &path, DirectoryEntry **directoryStructure)
- : ModInfoRegular(path, directoryStructure)
-{
-}
-
-
-ModInfoOverwrite::ModInfoOverwrite()
- : m_StartupTime(QDateTime::currentDateTime())
-{
- testValid();
-}
-
-
-bool ModInfoOverwrite::isEmpty() const
-{
- QDirIterator iter(absolutePath(), QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
- if (!iter.hasNext()) return true;
- iter.next();
- if ((iter.fileName() == "meta.ini") && !iter.hasNext()) return true;
- return false;
-}
-
-QString ModInfoOverwrite::absolutePath() const
-{
- return QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOverwriteDir()));
-}
-
-std::vector<ModInfo::EFlag> ModInfoOverwrite::getFlags() const
-{
- std::vector<ModInfo::EFlag> result;
- result.push_back(FLAG_OVERWRITE);
- return result;
-}
-
-int ModInfoOverwrite::getHighlight() const
-{
- return (isValid() ? HIGHLIGHT_IMPORTANT : HIGHLIGHT_INVALID) | HIGHLIGHT_CENTER;
-}
-
-QString ModInfoOverwrite::getDescription() const
-{
- return tr("This pseudo mod contains files from the virtual data tree that got "
- "modified (i.e. by the construction kit)");
-}
-
-QStringList ModInfoOverwrite::archives() const
-{
- QStringList result;
- QDir dir(this->absolutePath());
- foreach (const QString &archive, dir.entryList(QStringList("*.bsa"))) {
- result.append(this->absolutePath() + "/" + archive);
- }
- return result;
-}
-
-const char ModInfoForeign::INT_IDENTIFIER[] = "__int__foreign";
-
-QString ModInfoForeign::name() const
-{
- return m_Name;
-}
-
-QDateTime ModInfoForeign::creationTime() const
-{
- return m_CreationTime;
-}
-
-QString ModInfoForeign::absolutePath() const
-{
- return QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/data";
-}
-
-std::vector<ModInfo::EFlag> ModInfoForeign::getFlags() const
-{
- std::vector<ModInfo::EFlag> result = ModInfoWithConflictInfo::getFlags();
- result.push_back(FLAG_FOREIGN);
-
- return result;
-}
-
-int ModInfoForeign::getHighlight() const
-{
- return 0;
-}
-
-QString ModInfoForeign::getDescription() const
-{
- return tr("This pseudo mod represents content managed outside MO. It isn't modified by MO.");
-}
-
-ModInfoForeign::ModInfoForeign(const QString &referenceFile, const QStringList &archives,
- DirectoryEntry **directoryStructure)
- : ModInfoWithConflictInfo(directoryStructure)
- , m_ReferenceFile(referenceFile)
- , m_Archives(archives)
-{
- m_CreationTime = QFileInfo(referenceFile).created();
- m_Name = QFileInfo(m_ReferenceFile).baseName();
-}
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "modinfo.h" +#include "utility.h" +#include "installationtester.h" +#include "categories.h" +#include "report.h" +#include "modinfodialog.h" +#include "overwriteinfodialog.h" +#include "json.h" +#include "messagedialog.h" + +#include <gameinfo.h> +#include <versioninfo.h> + +#include <QApplication> + +#include <QDirIterator> +#include <QMutexLocker> +#include <QSettings> +#include <sstream> + + +using namespace MOBase; +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; +int ModInfo::s_NextID; +QMutex ModInfo::s_Mutex(QMutex::Recursive); + +QString ModInfo::s_HiddenExt(".mohidden"); + + +static bool ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS) +{ + return QString::compare(LHS->name(), RHS->name(), Qt::CaseInsensitive) < 0; +} + + +ModInfo::Ptr ModInfo::createFrom(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)); + } else { + result = ModInfo::Ptr(new ModInfoRegular(dir, directoryStructure)); + } + s_Collection.push_back(result); + return result; +} + +ModInfo::Ptr ModInfo::createFromPlugin(const QString &espName, const QStringList &bsaNames + , DirectoryEntry ** directoryStructure) +{ + QMutexLocker locker(&s_Mutex); + ModInfo::Ptr result = ModInfo::Ptr(new ModInfoForeign(espName, bsaNames, directoryStructure)); + s_Collection.push_back(result); + return result; +} + +QString ModInfo::getContentTypeName(int contentType) +{ + switch (contentType) { + case CONTENT_PLUGIN: return tr("Plugins"); + case CONTENT_TEXTURE: return tr("Textures"); + case CONTENT_MESH: return tr("Meshes"); + case CONTENT_INTERFACE: return tr("UI Changes"); + case CONTENT_MUSIC: return tr("Music"); + case CONTENT_SOUND: return tr("Sound Effects"); + case CONTENT_SCRIPT: return tr("Scripts"); + case CONTENT_SKSE: return tr("SKSE Plugins"); + case CONTENT_SKYPROC: return tr("SkyProc Tools"); + case CONTENT_STRING: return tr("Strings"); + default: throw MyException(tr("invalid content type %1").arg(contentType)); + } +} + +void ModInfo::createFromOverwrite() +{ + QMutexLocker locker(&s_Mutex); + + s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite)); +} + +unsigned int ModInfo::getNumMods() +{ + QMutexLocker locker(&s_Mutex); + return s_Collection.size(); +} + + +ModInfo::Ptr ModInfo::getByIndex(unsigned int index) +{ + QMutexLocker locker(&s_Mutex); + + if (index >= s_Collection.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + return s_Collection[index]; +} + + +std::vector<ModInfo::Ptr> ModInfo::getByModID(int modID) +{ + QMutexLocker locker(&s_Mutex); + + auto iter = s_ModsByModID.find(modID); + if (iter == s_ModsByModID.end()) { + return std::vector<ModInfo::Ptr>(); + } + + std::vector<ModInfo::Ptr> result; + for (auto idxIter = iter->second.begin(); idxIter != iter->second.end(); ++idxIter) { + result.push_back(getByIndex(*idxIter)); + } + + return result; +} + + +bool ModInfo::removeMod(unsigned int index) +{ + QMutexLocker locker(&s_Mutex); + + if (index >= s_Collection.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + + // update the indices first + ModInfo::Ptr modInfo = s_Collection[index]; + s_ModsByName.erase(s_ModsByName.find(modInfo->name())); + + auto iter = s_ModsByModID.find(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; + } + + // physically remove the mod directory + //TODO the return value is ignored because the indices were already removed here, so stopping + // would cause data inconsistencies. Instead we go through with the removal but the mod will show up + // again if the user refreshes + modInfo->remove(); + + // finally, remove the mod from the collection + s_Collection.erase(s_Collection.begin() + index); + + // and update the indices + updateIndices(); + return true; +} + + +unsigned int ModInfo::getIndex(const QString &name) +{ + QMutexLocker locker(&s_Mutex); + + std::map<QString, unsigned int>::iterator iter = s_ModsByName.find(name); + if (iter == s_ModsByName.end()) { + return UINT_MAX; + } + + return iter->second; +} + +unsigned int ModInfo::findMod(const boost::function<bool (ModInfo::Ptr)> &filter) +{ + for (unsigned int i = 0U; i < s_Collection.size(); ++i) { + if (filter(s_Collection[i])) { + return i; + } + } + return UINT_MAX; +} + + +void ModInfo::updateFromDisc(const QString &modDirectory, DirectoryEntry **directoryStructure, bool displayForeign) +{ + QMutexLocker lock(&s_Mutex); + s_Collection.clear(); + s_NextID = 0; + + { // list all directories in the mod directory and make a mod out of each + QDir mods(QDir::fromNativeSeparators(modDirectory)); + mods.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator modIter(mods); + while (modIter.hasNext()) { + createFrom(QDir(modIter.next()), directoryStructure); + } + } + + { // list plugins in the data directory and make a foreign-managed mod out of each + std::vector<std::wstring> dlcPlugins = GameInfo::instance().getDLCPlugins(); + QDir dataDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/data"); + foreach (const QFileInfo &file, dataDir.entryInfoList(QStringList() << "*.esp" << "*.esm")) { + if ((file.baseName() != "Update") // hide update + && (file.baseName() != ToQString(GameInfo::instance().getGameName())) // hide the game esp + && (displayForeign // show non-dlc bundles only if the user wants them + || std::find(dlcPlugins.begin(), dlcPlugins.end(), ToWString(file.fileName())) != dlcPlugins.end())) { + QStringList archives; + foreach (const QString archiveName, dataDir.entryList(QStringList() << file.baseName() + "*.bsa")) { + archives.append(dataDir.absoluteFilePath(archiveName)); + } + + createFromPlugin(file.fileName(), archives, directoryStructure); + } + } + } + + createFromOverwrite(); + + std::sort(s_Collection.begin(), s_Collection.end(), ByName); + + updateIndices(); +} + + +void ModInfo::updateIndices() +{ + s_ModsByName.clear(); + s_ModsByModID.clear(); + QRegExp backupRegEx(".*backup[0-9]*$"); + + for (unsigned int i = 0; i < s_Collection.size(); ++i) { + QString modName = s_Collection[i]->internalName(); + int modID = s_Collection[i]->getNexusID(); + s_ModsByName[modName] = i; + s_ModsByModID[modID].push_back(i); + } +} + + +ModInfo::ModInfo() + : m_Valid(false), m_PrimaryCategory(-1) +{ +} + + +void ModInfo::checkChunkForUpdate(const std::vector<int> &modIDs, QObject *receiver) +{ + if (modIDs.size() != 0) { + NexusInterface::instance()->requestUpdates(modIDs, receiver, QVariant(), QString()); + } +} + + +int ModInfo::checkAllForUpdate(QObject *receiver) +{ + int result = 0; + std::vector<int> modIDs; + + modIDs.push_back(GameInfo::instance().getNexusModID()); + + for (std::vector<ModInfo::Ptr>::iterator iter = s_Collection.begin(); + iter != s_Collection.end(); ++iter) { + if ((*iter)->canBeUpdated()) { + modIDs.push_back((*iter)->getNexusID()); + if (modIDs.size() >= 255) { + checkChunkForUpdate(modIDs, receiver); + modIDs.clear(); + } + } + } + + checkChunkForUpdate(modIDs, receiver); + + return result; +} + +void ModInfo::setVersion(const VersionInfo &version) +{ + m_Version = version; +} + +bool ModInfo::hasFlag(ModInfo::EFlag flag) const +{ + std::vector<EFlag> flags = getFlags(); + return std::find(flags.begin(), flags.end(), flag) != flags.end(); +} + +bool ModInfo::hasContent(ModInfo::EContent content) const +{ + std::vector<EContent> contents = getContents(); + return std::find(contents.begin(), contents.end(), content) != contents.end(); +} + +bool ModInfo::categorySet(int categoryID) const +{ + for (std::set<int>::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) { + if ((*iter == categoryID) || + (CategoryFactory::instance().isDecendantOf(*iter, categoryID))) { + return true; + } + } + + return false; +} + + +void ModInfo::testValid() +{ + m_Valid = false; + QDirIterator dirIter(absolutePath()); + while (dirIter.hasNext()) { + dirIter.next(); + if (dirIter.fileInfo().isDir()) { + if (InstallationTester::isTopLevelDirectory(dirIter.fileName())) { + m_Valid = true; + break; + } + } else { + if (InstallationTester::isTopLevelSuffix(dirIter.fileName())) { + m_Valid = true; + break; + } + } + } + + // NOTE: in Qt 4.7 it seems that QDirIterator leaves a file handle open if it is not iterated to the + // end + while (dirIter.hasNext()) { + dirIter.next(); + } +} + + +ModInfoWithConflictInfo::ModInfoWithConflictInfo(DirectoryEntry **directoryStructure) + : m_DirectoryStructure(directoryStructure) {} + +void ModInfoWithConflictInfo::clearCaches() +{ + m_LastConflictCheck = QTime(); +} + +std::vector<ModInfo::EFlag> ModInfoWithConflictInfo::getFlags() const +{ + std::vector<ModInfo::EFlag> result; + switch (isConflicted()) { + case CONFLICT_MIXED: { + result.push_back(ModInfo::FLAG_CONFLICT_MIXED); + } break; + case CONFLICT_OVERWRITE: { + result.push_back(ModInfo::FLAG_CONFLICT_OVERWRITE); + } break; + case CONFLICT_OVERWRITTEN: { + result.push_back(ModInfo::FLAG_CONFLICT_OVERWRITTEN); + } break; + case CONFLICT_REDUNDANT: { + result.push_back(ModInfo::FLAG_CONFLICT_REDUNDANT); + } break; + default: { /* NOP */ } + } + return result; +} + + +void ModInfoWithConflictInfo::doConflictCheck() const +{ + m_OverwriteList.clear(); + m_OverwrittenList.clear(); + bool regular = false; + + int dataID = 0; + if ((*m_DirectoryStructure)->originExists(L"data")) { + dataID = (*m_DirectoryStructure)->getOriginByName(L"data").getID(); + } + + std::wstring name = ToWString(this->name()); + if ((*m_DirectoryStructure)->originExists(name)) { + FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name); + std::vector<FileEntry::Ptr> files = origin.getFiles(); + // for all files in this origin + for (auto iter = files.begin(); iter != files.end(); ++iter) { + const std::vector<int> &alternatives = (*iter)->getAlternatives(); + if ((alternatives.size() == 0) + || (alternatives[0] == dataID)) { + // no alternatives -> no conflict + regular = true; + } else { + if ((*iter)->getOrigin() != origin.getID()) { + FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID((*iter)->getOrigin()); + unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName())); + m_OverwrittenList.insert(altIndex); + } + // for all non-providing alternative origins + for (auto altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) { + if ((*altIter != dataID) && (*altIter != origin.getID())) { + FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(*altIter); + unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName())); + if (origin.getPriority() > altOrigin.getPriority()) { + m_OverwriteList.insert(altIndex); + } else { + m_OverwrittenList.insert(altIndex); + } + } + } + } + } + } + + m_LastConflictCheck = QTime::currentTime(); + + if (!m_OverwriteList.empty() && !m_OverwrittenList.empty()) + m_CurrentConflictState = CONFLICT_MIXED; + else if (!m_OverwriteList.empty()) + m_CurrentConflictState = CONFLICT_OVERWRITE; + else if (!m_OverwrittenList.empty()) { + if (!regular) { + m_CurrentConflictState = CONFLICT_REDUNDANT; + } else { + m_CurrentConflictState = CONFLICT_OVERWRITTEN; + } + } + else m_CurrentConflictState = CONFLICT_NONE; +} + +ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isConflicted() const +{ + // this is costy so cache the result + QTime now = QTime::currentTime(); + if (m_LastConflictCheck.isNull() || (m_LastConflictCheck.secsTo(now) > 10)) { + doConflictCheck(); + } + + return m_CurrentConflictState; +} + + +bool ModInfoWithConflictInfo::isRedundant() const +{ + std::wstring name = ToWString(this->name()); + if ((*m_DirectoryStructure)->originExists(name)) { + FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name); + std::vector<FileEntry::Ptr> files = origin.getFiles(); + bool ignore = false; + for (auto iter = files.begin(); iter != files.end(); ++iter) { + if ((*iter)->getOrigin(ignore) == origin.getID()) { + return false; + } + } + return true; + } else { + return false; + } +} + + + +ModInfoRegular::ModInfoRegular(const QDir &path, DirectoryEntry **directoryStructure) + : ModInfoWithConflictInfo(directoryStructure) + , m_Name(path.dirName()) + , m_Path(path.absolutePath()) + , m_MetaInfoChanged(false) + , m_EndorsedState(ENDORSED_UNKNOWN) +{ + testValid(); + m_CreationTime = QFileInfo(path.absolutePath()).created(); + // read out the meta-file for information + readMeta(); + + 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))); +} + + +ModInfoRegular::~ModInfoRegular() +{ + try { + saveMeta(); + } catch (const std::exception &e) { + qCritical("failed to save meta information for \"%s\": %s", + m_Name.toUtf8().constData(), e.what()); + } +} + +bool ModInfoRegular::isEmpty() const +{ + QDirIterator iter(m_Path, QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); + if (!iter.hasNext()) return true; + iter.next(); + if ((iter.fileName() == "meta.ini") && !iter.hasNext()) return true; + return false; +} + + +void ModInfoRegular::readMeta() +{ + QSettings metaFile(m_Path + "/meta.ini", QSettings::IniFormat); + + m_Notes = metaFile.value("notes", "").toString(); + 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_LastNexusQuery = QDateTime::fromString(metaFile.value("lastNexusQuery", "").toString(), Qt::ISODate); + if (metaFile.contains("endorsed")) { + if (metaFile.value("endorsed").canConvert<int>()) { + switch (metaFile.value("endorsed").toInt()) { + case ENDORSED_FALSE: m_EndorsedState = ENDORSED_FALSE; break; + case ENDORSED_TRUE: m_EndorsedState = ENDORSED_TRUE; break; + case ENDORSED_NEVER: m_EndorsedState = ENDORSED_NEVER; break; + default: m_EndorsedState = ENDORSED_UNKNOWN; break; + } + } else { + m_EndorsedState = metaFile.value("endorsed", false).toBool() ? ENDORSED_TRUE : ENDORSED_FALSE; + } + } + + QString categoriesString = metaFile.value("category", "").toString(); + + QStringList categories = categoriesString.split(',', QString::SkipEmptyParts); + for (QStringList::iterator iter = categories.begin(); iter != categories.end(); ++iter) { + bool ok = false; + int categoryID = iter->toInt(&ok); + if (categoryID < 0) { + // ignore invalid id + continue; + } + if (ok && (categoryID != 0) && (CategoryFactory::instance().categoryExists(categoryID))) { + m_Categories.insert(categoryID); + if (iter == categories.begin()) { + m_PrimaryCategory = categoryID; + } + } + } + + m_MetaInfoChanged = false; +} + +void ModInfoRegular::saveMeta() +{ + // only write meta data if the mod directory exists + if (m_MetaInfoChanged && QFile::exists(absolutePath())) { + QSettings metaFile(absolutePath().append("/meta.ini"), QSettings::IniFormat); + if (metaFile.status() == QSettings::NoError) { + std::set<int> temp = m_Categories; + temp.erase(m_PrimaryCategory); + metaFile.setValue("category", QString("%1").arg(m_PrimaryCategory) + "," + SetJoin(temp, ",")); + metaFile.setValue("newestVersion", m_NewestVersion.canonicalString()); + metaFile.setValue("ignoredVersion", m_IgnoredVersion.canonicalString()); + metaFile.setValue("version", m_Version.canonicalString()); + metaFile.setValue("modid", m_NexusID); + metaFile.setValue("notes", m_Notes); + metaFile.setValue("nexusDescription", m_NexusDescription); + metaFile.setValue("lastNexusQuery", m_LastNexusQuery.toString(Qt::ISODate)); + if (m_EndorsedState != ENDORSED_UNKNOWN) { + metaFile.setValue("endorsed", m_EndorsedState); + } + metaFile.sync(); // sync needs to be called to ensure the file is created + + if (metaFile.status() == QSettings::NoError) { + m_MetaInfoChanged = false; + } else { + reportError(tr("failed to write %1/meta.ini: error %2").arg(absolutePath()).arg(metaFile.status())); + } + } else { + reportError(tr("failed to write %1/meta.ini: error %2").arg(absolutePath()).arg(metaFile.status())); + } + } +} + + +bool ModInfoRegular::updateAvailable() const +{ + if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) { + return false; + } + return m_NewestVersion.isValid() && (m_Version < m_NewestVersion); +} + + +bool ModInfoRegular::downgradeAvailable() const +{ + if (m_IgnoredVersion.isValid() && (m_IgnoredVersion == m_NewestVersion)) { + return false; + } + return m_NewestVersion.isValid() && (m_NewestVersion < m_Version); +} + + +void ModInfoRegular::nxmDescriptionAvailable(int, QVariant, QVariant resultData) +{ + QVariantMap result = resultData.toMap(); + m_NewestVersion.parse(result["version"].toString()); + m_NexusDescription = result["description"].toString(); + if ((m_EndorsedState != ENDORSED_NEVER) && (result.contains("voted_by_user"))) { + m_EndorsedState = result["voted_by_user"].toBool() ? ENDORSED_TRUE : ENDORSED_FALSE; + } + m_LastNexusQuery = QDateTime::currentDateTime(); + m_MetaInfoChanged = true; + saveMeta(); + emit modDetailsUpdated(true); +} + + +void ModInfoRegular::nxmEndorsementToggled(int, QVariant, QVariant resultData) +{ + m_EndorsedState = resultData.toBool() ? ENDORSED_TRUE : ENDORSED_FALSE; + m_MetaInfoChanged = true; + saveMeta(); + emit modDetailsUpdated(true); +} + + +void ModInfoRegular::nxmRequestFailed(int, int, QVariant userData, const QString &errorMessage) +{ + QString fullMessage = errorMessage; + if (userData.canConvert<int>() && (userData.toInt() == 1)) { + fullMessage += "\nNexus will reject endorsements within 15 Minutes of a failed attempt, the error message may be misleading."; + } + if (QApplication::activeWindow() != NULL) { + MessageDialog::showMessage(fullMessage, QApplication::activeWindow()); + } + emit modDetailsUpdated(false); +} + + +bool ModInfoRegular::updateNXMInfo() +{ + if (m_NexusID > 0) { + m_NexusBridge.requestDescription(m_NexusID, QVariant()); + return true; + } + return false; +} + + +void ModInfoRegular::setCategory(int categoryID, bool active) +{ + m_MetaInfoChanged = true; + + if (active) { + m_Categories.insert(categoryID); + if (m_PrimaryCategory == -1) { + m_PrimaryCategory = categoryID; + } + } else { + std::set<int>::iterator iter = m_Categories.find(categoryID); + if (iter != m_Categories.end()) { + m_Categories.erase(iter); + } + if (categoryID == m_PrimaryCategory) { + if (m_Categories.size() == 0) { + m_PrimaryCategory = -1; + } else { + m_PrimaryCategory = *(m_Categories.begin()); + } + } + } +} + + +bool ModInfoRegular::setName(const QString &name) +{ + if (name.contains('/') || name.contains('\\')) { + return false; + } + + QString newPath = m_Path.mid(0).replace(m_Path.length() - m_Name.length(), m_Name.length(), name); + QDir modDir(m_Path.mid(0, m_Path.length() - m_Name.length())); + + if (m_Name.compare(name, Qt::CaseInsensitive) == 0) { + QString tempName = name; + tempName.append("_temp"); + while (modDir.exists(tempName)) { + tempName.append("_"); + } + if (!modDir.rename(m_Name, tempName)) { + return false; + } + if (!modDir.rename(tempName, name)) { + qCritical("rename to final name failed after successful rename to intermediate name"); + modDir.rename(tempName, m_Name); + return false; + } + } else { + if (!shellRename(modDir.absoluteFilePath(m_Name), modDir.absoluteFilePath(name))) { + qCritical("failed to rename mod %s (errorcode %d)", + qPrintable(name), ::GetLastError()); + return false; + } + } + + std::map<QString, unsigned int>::iterator nameIter = s_ModsByName.find(m_Name); + if (nameIter != s_ModsByName.end()) { + unsigned int index = nameIter->second; + s_ModsByName.erase(nameIter); + + m_Name = name; + m_Path = newPath; + + s_ModsByName[m_Name] = index; + + std::sort(s_Collection.begin(), s_Collection.end(), ByName); + updateIndices(); + } else { // otherwise mod isn't registered yet? + m_Name = name; + m_Path = newPath; + } + + return true; +} + +void ModInfoRegular::setNotes(const QString ¬es) +{ + m_Notes = notes; + m_MetaInfoChanged = true; +} + +void ModInfoRegular::setNexusID(int modID) +{ + m_NexusID = modID; + m_MetaInfoChanged = true; +} + +void ModInfoRegular::setVersion(const VersionInfo &version) +{ + m_Version = version; + m_MetaInfoChanged = true; +} + +void ModInfoRegular::setNewestVersion(const VersionInfo &version) { + m_NewestVersion = version; +} + +void ModInfoRegular::setNexusDescription(const QString &description) +{ + m_NexusDescription = description; + m_MetaInfoChanged = true; +} + +void ModInfoRegular::addNexusCategory(int categoryID) +{ + m_Categories.insert(CategoryFactory::instance().resolveNexusID(categoryID)); +} + +void ModInfoRegular::setIsEndorsed(bool endorsed) +{ + if (m_EndorsedState != ENDORSED_NEVER) { + m_EndorsedState = endorsed ? ENDORSED_TRUE : ENDORSED_FALSE; + m_MetaInfoChanged = true; + } +} + + +void ModInfoRegular::setNeverEndorse() +{ + m_EndorsedState = ENDORSED_NEVER; + m_MetaInfoChanged = true; +} + + +bool ModInfoRegular::remove() +{ + m_MetaInfoChanged = false; + return shellDelete(QStringList(absolutePath()), true); +} + +void ModInfoRegular::endorse(bool doEndorse) +{ + if (doEndorse != (m_EndorsedState == ENDORSED_TRUE)) { + m_NexusBridge.requestToggleEndorsement(getNexusID(), doEndorse, QVariant(1)); + } +} + + +QString ModInfoRegular::absolutePath() const +{ + return m_Path; +} + +void ModInfoRegular::ignoreUpdate(bool ignore) +{ + if (ignore) { + m_IgnoredVersion = m_NewestVersion; + } else { + m_IgnoredVersion.clear(); + } + m_MetaInfoChanged = true; +} + + +std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const +{ + std::vector<ModInfo::EFlag> result = ModInfoWithConflictInfo::getFlags(); + if ((m_NexusID != -1) && (endorsedState() == ENDORSED_FALSE)) { + result.push_back(ModInfo::FLAG_NOTENDORSED); + } + if (!isValid()) { + result.push_back(ModInfo::FLAG_INVALID); + } + if (m_Notes.length() != 0) { + result.push_back(ModInfo::FLAG_NOTES); + } + return result; +} + + +std::vector<ModInfo::EContent> ModInfoRegular::getContents() const +{ + std::vector<EContent> result; + QDir dir(absolutePath()); + if (dir.entryList(QStringList() << "*.esp" << "*.esm").size() > 0) { + result.push_back(CONTENT_PLUGIN); + } + QString sePluginPath = ToQString(GameInfo::instance().getSEName()) + "/plugins"; + if (dir.exists("textures")) result.push_back(CONTENT_TEXTURE); + if (dir.exists("meshes")) result.push_back(CONTENT_MESH); + if (dir.exists("interface") + || dir.exists("menus")) result.push_back(CONTENT_INTERFACE); + if (dir.exists("music")) result.push_back(CONTENT_MUSIC); + if (dir.exists("sound")) result.push_back(CONTENT_SOUND); + if (dir.exists("scripts")) result.push_back(CONTENT_SCRIPT); + if (dir.exists(sePluginPath)) result.push_back(CONTENT_SKSE); + if (dir.exists("strings")) result.push_back(CONTENT_STRING); + if (dir.exists("SkyProc Patchers")) result.push_back(CONTENT_SKYPROC); + return result; +} + + +int ModInfoRegular::getHighlight() const +{ + return isValid() ? HIGHLIGHT_NONE: HIGHLIGHT_INVALID; +} + + +QString ModInfoRegular::getDescription() const +{ + if (!isValid()) { + return tr("%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory").arg(name()); + } else { + const std::set<int> &categories = getCategories(); + std::wostringstream categoryString; + categoryString << ToWString(tr("Categories: <br>")); + CategoryFactory &categoryFactory = CategoryFactory::instance(); + for (std::set<int>::const_iterator catIter = categories.begin(); + catIter != categories.end(); ++catIter) { + if (catIter != categories.begin()) { + categoryString << " , "; + } + categoryString << "<span style=\"white-space: nowrap;\"><i>" << ToWString(categoryFactory.getCategoryName(categoryFactory.getCategoryIndex(*catIter))) << "</font></span>"; + } + + return ToQString(categoryString.str()); + } +} + +QString ModInfoRegular::notes() const +{ + return m_Notes; +} + +QDateTime ModInfoRegular::creationTime() const +{ + return m_CreationTime; +} + +QString ModInfoRegular::getNexusDescription() const +{ + return m_NexusDescription; +} + +ModInfoRegular::EEndorsedState ModInfoRegular::endorsedState() const +{ + return m_EndorsedState; +} + +QDateTime ModInfoRegular::getLastNexusQuery() const +{ + return m_LastNexusQuery; +} + + +QStringList ModInfoRegular::archives() const +{ + QStringList result; + QDir dir(this->absolutePath()); + foreach (const QString &archive, dir.entryList(QStringList("*.bsa"))) { + result.append(this->absolutePath() + "/" + archive); + } + return result; +} + +std::vector<QString> ModInfoRegular::getIniTweaks() const +{ + QString metaFileName = absolutePath().append("/meta.ini"); + QSettings metaFile(metaFileName, QSettings::IniFormat); + + std::vector<QString> result; + + int numTweaks = metaFile.beginReadArray("INI Tweaks"); + + if (numTweaks != 0) { + qDebug("%d active ini tweaks in %s", + numTweaks, QDir::toNativeSeparators(metaFileName).toUtf8().constData()); + } + + for (int i = 0; i < numTweaks; ++i) { + metaFile.setArrayIndex(i); + QString filename = absolutePath().append("/INI Tweaks/").append(metaFile.value("name").toString()); + result.push_back(filename); + } + metaFile.endArray(); + return result; +} + +std::vector<ModInfo::EFlag> ModInfoBackup::getFlags() const +{ + std::vector<ModInfo::EFlag> result = ModInfoRegular::getFlags(); + result.insert(result.begin(), ModInfo::FLAG_BACKUP); + return result; +} + + +QString ModInfoBackup::getDescription() const +{ + return tr("This is the backup of a mod"); +} + + +ModInfoBackup::ModInfoBackup(const QDir &path, DirectoryEntry **directoryStructure) + : ModInfoRegular(path, directoryStructure) +{ +} + + +ModInfoOverwrite::ModInfoOverwrite() + : m_StartupTime(QDateTime::currentDateTime()) +{ + testValid(); +} + + +bool ModInfoOverwrite::isEmpty() const +{ + QDirIterator iter(absolutePath(), QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); + if (!iter.hasNext()) return true; + iter.next(); + if ((iter.fileName() == "meta.ini") && !iter.hasNext()) return true; + return false; +} + +QString ModInfoOverwrite::absolutePath() const +{ + return QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOverwriteDir())); +} + +std::vector<ModInfo::EFlag> ModInfoOverwrite::getFlags() const +{ + std::vector<ModInfo::EFlag> result; + result.push_back(FLAG_OVERWRITE); + return result; +} + +int ModInfoOverwrite::getHighlight() const +{ + return (isValid() ? HIGHLIGHT_IMPORTANT : HIGHLIGHT_INVALID) | HIGHLIGHT_CENTER; +} + +QString ModInfoOverwrite::getDescription() const +{ + return tr("This pseudo mod contains files from the virtual data tree that got " + "modified (i.e. by the construction kit)"); +} + +QStringList ModInfoOverwrite::archives() const +{ + QStringList result; + QDir dir(this->absolutePath()); + foreach (const QString &archive, dir.entryList(QStringList("*.bsa"))) { + result.append(this->absolutePath() + "/" + archive); + } + return result; +} + +const char ModInfoForeign::INT_IDENTIFIER[] = "__int__foreign"; + +QString ModInfoForeign::name() const +{ + return m_Name; +} + +QDateTime ModInfoForeign::creationTime() const +{ + return m_CreationTime; +} + +QString ModInfoForeign::absolutePath() const +{ + return QDir::fromNativeSeparators(ToQString(GameInfo::instance().getGameDirectory())) + "/data"; +} + +std::vector<ModInfo::EFlag> ModInfoForeign::getFlags() const +{ + std::vector<ModInfo::EFlag> result = ModInfoWithConflictInfo::getFlags(); + result.push_back(FLAG_FOREIGN); + + return result; +} + +int ModInfoForeign::getHighlight() const +{ + return 0; +} + +QString ModInfoForeign::getDescription() const +{ + return tr("This pseudo mod represents content managed outside MO. It isn't modified by MO."); +} + +ModInfoForeign::ModInfoForeign(const QString &referenceFile, const QStringList &archives, + DirectoryEntry **directoryStructure) + : ModInfoWithConflictInfo(directoryStructure) + , m_ReferenceFile(referenceFile) + , m_Archives(archives) +{ + m_CreationTime = QFileInfo(referenceFile).created(); + m_Name = tr("Unmanaged") + ": " + QFileInfo(m_ReferenceFile).baseName(); +} diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 1cea9e1e..9133b166 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -84,7 +84,8 @@ ModInfoDialog::ModInfoDialog(ModInfo::Ptr modInfo, const DirectoryEntry *directo connect(&m_ThumbnailMapper, SIGNAL(mapped(const QString&)), this, SIGNAL(thumbnailClickedSignal(const QString&)));
connect(this, SIGNAL(thumbnailClickedSignal(const QString&)), this, SLOT(thumbnailClicked(const QString&)));
connect(m_ModInfo.data(), SIGNAL(modDetailsUpdated(bool)), this, SLOT(modDetailsUpdated(bool)));
- connect(ui->descriptionView, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
+ connect(ui->descriptionView, SIGNAL(linkClicked(QUrl)), this, SLOT(linkClicked(QUrl)));
+ ui->descriptionView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
if (directory->originExists(ToWString(modInfo->name()))) {
m_Origin = &directory->getOriginByName(ToWString(modInfo->name()));
diff --git a/src/modinfodialog.ui b/src/modinfodialog.ui index d3862b58..a03edef7 100644 --- a/src/modinfodialog.ui +++ b/src/modinfodialog.ui @@ -232,8 +232,8 @@ <rect>
<x>0</x>
<y>0</y>
- <width>676</width>
- <height>126</height>
+ <width>98</width>
+ <height>28</height>
</rect>
</property>
<property name="toolTip">
@@ -678,25 +678,11 @@ p, li { white-space: pre-wrap; } </layout>
</item>
<item>
- <widget class="QTextBrowser" name="descriptionView">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>200</height>
- </size>
- </property>
- <property name="html">
- <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></string>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::TextBrowserInteraction</set>
- </property>
- <property name="openLinks">
- <bool>false</bool>
+ <widget class="QWebView" name="descriptionView">
+ <property name="url">
+ <url>
+ <string>about:blank</string>
+ </url>
</property>
</widget>
</item>
@@ -819,6 +805,13 @@ p, li { white-space: pre-wrap; } </item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>QWebView</class>
+ <extends>QWidget</extends>
+ <header>QtWebKitWidgets/QWebView</header>
+ </customwidget>
+ </customwidgets>
<resources>
<include location="resources.qrc"/>
</resources>
diff --git a/src/modlist.cpp b/src/modlist.cpp index 681d880c..fb8df15e 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -49,8 +49,12 @@ using namespace MOBase; ModList::ModList(QObject *parent)
- : QAbstractItemModel(parent), m_Profile(NULL), m_Modified(false),
- m_FontMetrics(QFont()), m_DropOnItems(false)
+ : QAbstractItemModel(parent)
+ , m_Profile(NULL)
+ , m_NexusInterface(NULL)
+ , m_Modified(false)
+ , m_FontMetrics(QFont())
+ , m_DropOnItems(false)
{
m_ContentIcons[ModInfo::CONTENT_PLUGIN] = std::make_tuple(QIcon(":/MO/gui/content/plugin"), ":/MO/gui/content/plugin", tr("Game plugins (esp/esm)"));
m_ContentIcons[ModInfo::CONTENT_INTERFACE] = std::make_tuple(QIcon(":/MO/gui/content/interface"), ":/MO/gui/content/interface", tr("Interface"));
@@ -64,6 +68,12 @@ ModList::ModList(QObject *parent) m_ContentIcons[ModInfo::CONTENT_TEXTURE] = std::make_tuple(QIcon(":/MO/gui/content/texture"), ":/MO/gui/content/texture", tr("Textures"));
}
+ModList::~ModList()
+{
+ m_ModStateChanged.disconnect_all_slots();
+ m_ModMoved.disconnect_all_slots();
+}
+
void ModList::setProfile(Profile *profile)
{
m_Profile = profile;
@@ -653,6 +663,11 @@ void ModList::modInfoChanged(ModInfo::Ptr info) }
}
+void ModList::disconnectSlots() {
+ m_ModMoved.disconnect_all_slots();
+ m_ModStateChanged.disconnect_all_slots();
+}
+
IModList::ModStates ModList::state(unsigned int modIndex) const
{
IModList::ModStates result;
diff --git a/src/modlist.h b/src/modlist.h index 6116a913..cf52b2ec 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -32,7 +32,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QListWidget>
#include <QNetworkReply>
#include <QNetworkAccessManager>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
+#endif
#include <set>
#include <vector>
#include <QVector>
@@ -73,6 +75,8 @@ public: **/
ModList(QObject *parent = NULL);
+ ~ModList();
+
/**
* @brief set the profile used for status information
*
@@ -103,6 +107,8 @@ public: void modInfoAboutToChange(ModInfo::Ptr info);
void modInfoChanged(ModInfo::Ptr info);
+ void disconnectSlots();
+
public:
/// \copydoc MOBase::IModList::displayName
@@ -261,7 +267,7 @@ private: struct TModInfo {
TModInfo(unsigned int index, ModInfo::Ptr modInfo)
- : modInfo(modInfo), nameOrder(index) {}
+ : modInfo(modInfo), nameOrder(index), priorityOrder(0), modIDOrder(0), categoryOrder(0) {}
ModInfo::Ptr modInfo;
unsigned int nameOrder;
unsigned int priorityOrder;
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index da5d99d5..e132b71e 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -79,36 +79,6 @@ Qt::ItemFlags ModListSortProxy::flags(const QModelIndex &modelIndex) const return flags;
}
-void ModListSortProxy::displayColumnSelection(const QPoint &pos)
-{
- QMenu menu;
-
- for (int i = 0; i <= ModList::COL_LASTCOLUMN; ++i) {
- QCheckBox *checkBox = new QCheckBox(&menu);
- checkBox->setText(ModList::getColumnName(i));
- checkBox->setChecked(m_EnabledColumns.test(i) ? Qt::Checked : Qt::Unchecked);
- QWidgetAction *checkableAction = new QWidgetAction(&menu);
- checkableAction->setDefaultWidget(checkBox);
- menu.addAction(checkableAction);
- }
- menu.exec(pos);
- int i = 0;
-
- emit layoutAboutToBeChanged();
- m_EnabledColumns.reset();
- foreach (const QAction *action, menu.actions()) {
- const QWidgetAction *widgetAction = qobject_cast<const QWidgetAction*>(action);
- if (widgetAction != NULL) {
- const QCheckBox *checkBox = qobject_cast<const QCheckBox*>(widgetAction->defaultWidget());
- if (checkBox != NULL) {
- m_EnabledColumns.set(i, checkBox->checkState() == Qt::Checked);
- }
- }
- ++i;
- }
- emit layoutChanged();
-}
-
void ModListSortProxy::enableAllVisible()
{
if (m_Profile == NULL) return;
@@ -298,7 +268,7 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const } break;
case CategoryFactory::CATEGORY_SPECIAL_NOTENDORSED: {
ModInfo::EEndorsedState state = info->endorsedState();
- if ((state == ModInfo::ENDORSED_FALSE) && (state != ModInfo::ENDORSED_NEVER)) return true;
+ if ((state == ModInfo::ENDORSED_FALSE) || (state == ModInfo::ENDORSED_NEVER)) return true;
} break;
case CategoryFactory::CATEGORY_SPECIAL_MANAGED: {
if (!info->hasFlag(ModInfo::FLAG_FOREIGN)) return true;
diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 71da79eb..05392c0b 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -95,7 +95,6 @@ public: public slots:
- void displayColumnSelection(const QPoint &pos);
void updateFilter(const QString &filter);
signals:
diff --git a/src/nexusinterface.cpp b/src/nexusinterface.cpp index d844cd39..b4006097 100644 --- a/src/nexusinterface.cpp +++ b/src/nexusinterface.cpp @@ -20,7 +20,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "nexusinterface.h"
#include "nxmaccessmanager.h"
#include "utility.h"
-#include <json.h>
+#include "json.h"
#include "selectiondialog.h"
#include <QApplication>
#include <utility.h>
@@ -145,30 +145,25 @@ QAtomicInt NexusInterface::NXMRequestInfo::s_NextID(0); NexusInterface::NexusInterface()
: m_NMMVersion()
{
- atexit(&cleanup);
-
VS_FIXEDFILEINFO version = GetFileVersion(ToWString(QApplication::applicationFilePath()));
m_MOVersion = VersionInfo(version.dwFileVersionMS >> 16,
version.dwFileVersionMS & 0xFFFF,
version.dwFileVersionLS >> 16);
m_AccessManager = new NXMAccessManager(this, m_MOVersion.displayString());
-
m_DiskCache = new QNetworkDiskCache(this);
connect(m_AccessManager, SIGNAL(requestNXMDownload(QString)), this, SLOT(downloadRequestedNXM(QString)));
}
-
-void NexusInterface::cleanup()
-{
-}
-
-
NXMAccessManager *NexusInterface::getAccessManager()
{
return m_AccessManager;
}
+NexusInterface::~NexusInterface()
+{
+ cleanup();
+}
NexusInterface *NexusInterface::instance()
{
@@ -176,14 +171,12 @@ NexusInterface *NexusInterface::instance() return &s_Instance;
}
-
void NexusInterface::setCacheDirectory(const QString &directory)
{
m_DiskCache->setCacheDirectory(directory);
m_AccessManager->setCache(m_DiskCache);
}
-
void NexusInterface::setNMMVersion(const QString &nmmVersion)
{
m_NMMVersion = nmmVersion;
@@ -378,6 +371,14 @@ bool NexusInterface::requiresLogin(const NXMRequestInfo &info) || (info.m_Type == NXMRequestInfo::TYPE_DOWNLOADURL);
}
+void NexusInterface::cleanup()
+{
+// delete m_AccessManager;
+// delete m_DiskCache;
+ m_AccessManager = nullptr;
+ m_DiskCache = nullptr;
+}
+
void NexusInterface::nextRequest()
{
if ((m_ActiveRequest.size() >= MAX_ACTIVE_DOWNLOADS)
@@ -579,6 +580,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID , m_URL(url)
, m_SubModule(subModule)
, m_NexusGameID(nexusGameId)
+ , m_Endorse(false)
{}
NexusInterface::NXMRequestInfo::NXMRequestInfo(std::vector<int> modIDList
@@ -599,6 +601,7 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(std::vector<int> modIDList , m_URL(url)
, m_SubModule(subModule)
, m_NexusGameID(nexusGameId)
+ , m_Endorse(false)
{}
NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID
@@ -619,4 +622,5 @@ NexusInterface::NXMRequestInfo::NXMRequestInfo(int modID , m_URL(url)
, m_SubModule(subModule)
, m_NexusGameID(nexusGameId)
+ , m_Endorse(false)
{}
diff --git a/src/nexusinterface.h b/src/nexusinterface.h index cc54daa9..af2f8c75 100644 --- a/src/nexusinterface.h +++ b/src/nexusinterface.h @@ -130,6 +130,8 @@ class NexusInterface : public QObject public:
+ ~NexusInterface();
+
static NexusInterface *instance();
/**
@@ -138,6 +140,11 @@ public: NXMAccessManager *getAccessManager();
/**
+ * @brief cleanup this interface. this is destructive, afterwards it can't be used again
+ */
+ void cleanup();
+
+ /**
* @brief request description for a mod
*
* @param modID id of the mod caller is interested in
@@ -301,7 +308,6 @@ private: void nextRequest();
void requestFinished(std::list<NXMRequestInfo>::iterator iter);
bool requiresLogin(const NXMRequestInfo &info);
- static void cleanup();
private:
diff --git a/src/organizer.pro b/src/organizer.pro index 5cdb758e..98dbcd4a 100644 --- a/src/organizer.pro +++ b/src/organizer.pro @@ -9,11 +9,15 @@ TARGET = ModOrganizer TEMPLATE = app
greaterThan(QT_MAJOR_VERSION, 4) {
- QT += core gui widgets network xml sql xmlpatterns qml quick script webkit webkitwidgets
+ QT += core gui widgets network xml sql xmlpatterns qml declarative script webkit webkitwidgets
} else {
QT += core gui network xml declarative script sql xmlpatterns webkit
}
+!include(../LocalPaths.pri) {
+ message("paths to required libraries need to be set up in LocalPaths.pri")
+}
+
SOURCES += \
transfersavesdialog.cpp \
syncoverwritedialog.cpp \
@@ -90,7 +94,9 @@ SOURCES += \ modflagicondelegate.cpp \
genericicondelegate.cpp \
organizerproxy.cpp \
- viewmarkingscrollbar.cpp
+ viewmarkingscrollbar.cpp \
+ plugincontainer.cpp \
+ organizercore.cpp
HEADERS += \
@@ -170,7 +176,10 @@ HEADERS += \ modflagicondelegate.h \
genericicondelegate.h \
organizerproxy.h \
- viewmarkingscrollbar.h
+ viewmarkingscrollbar.h \
+ plugincontainer.h \
+ organizercore.h \
+ iuserinterface.h
FORMS += \
transfersavesdialog.ui \
@@ -248,9 +257,9 @@ LIBS += -lDbgHelp #DEFINES += TEST_MODELS
-INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$(BOOSTPATH)"
+INCLUDEPATH += ../shared ../archive ../uibase ../bsatk ../esptk ../boss_modified/boss-api "$${BOOSTPATH}"
-LIBS += -L"$(BOOSTPATH)/stage/lib"
+LIBS += -L"$${BOOSTPATH}/stage/lib"
CONFIG(debug, debug|release) {
LIBS += -L$$OUT_PWD/../shared/debug
@@ -258,7 +267,8 @@ CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../uibase/debug
LIBS += -L$$OUT_PWD/../boss_modified/debug
LIBS += -lDbgHelp
- PRE_TARGETDEPS += $$OUT_PWD/../shared/debug/mo_shared.lib \
+ PRE_TARGETDEPS += \
+ $$OUT_PWD/../shared/debug/mo_shared.lib \
$$OUT_PWD/../bsatk/debug/bsatk.lib
} else {
LIBS += -L$$OUT_PWD/../shared/release
@@ -266,20 +276,19 @@ CONFIG(debug, debug|release) { LIBS += -L$$OUT_PWD/../uibase/release
LIBS += -L$$OUT_PWD/../boss_modified/release
QMAKE_CXXFLAGS += /Zi# /GL
-# QMAKE_CXXFLAGS -= -O2
QMAKE_LFLAGS += /DEBUG# /LTCG /OPT:REF /OPT:ICF
- PRE_TARGETDEPS += $$OUT_PWD/../shared/release/mo_shared.lib \
+ PRE_TARGETDEPS += \
+ $$OUT_PWD/../shared/release/mo_shared.lib \
$$OUT_PWD/../bsatk/release/bsatk.lib
}
#QMAKE_CXXFLAGS_WARN_ON -= -W3
#QMAKE_CXXFLAGS_WARN_ON += -W4
-QMAKE_CXXFLAGS += -wd4127 -wd4512 -wd4189
+QMAKE_CXXFLAGS += /wd4100 -wd4127 -wd4512 -wd4189
CONFIG += embed_manifest_exe
# QMAKE_CXXFLAGS += /analyze
-
# QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'highestAvailable\' uiAccess=\'false\'\"
TRANSLATIONS = organizer_de.ts \
@@ -313,9 +322,9 @@ TRANSLATIONS = organizer_de.ts \ LIBS += -lmo_shared -luibase -lshell32 -lole32 -luser32 -ladvapi32 -lgdi32 -lPsapi -lVersion -lbsatk -lshlwapi
-LIBS += -L"$(ZLIBPATH)/build" -lzlibstatic
+LIBS += -L"$${ZLIBPATH}/build" -lzlibstatic
-DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS NOMINMAX
+DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS NOMINMAX
DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
#DEFINES += QMLJSDEBUGGER
@@ -324,40 +333,40 @@ HGID = $$system(hg id -i) DEFINES += HGID=\\\"$${HGID}\\\"
CONFIG(debug, debug|release) {
- OUTDIR = $$OUT_PWD/debug
+ SRCDIR = $$OUT_PWD/debug
DSTDIR = $$PWD/../../outputd
} else {
- OUTDIR = $$OUT_PWD/release
+ SRCDIR = $$OUT_PWD/release
DSTDIR = $$PWD/../../output
}
-SRCDIR = $$PWD
+BASEDIR = $$PWD
+BASEDIR ~= s,/,$$QMAKE_DIR_SEP,g
SRCDIR ~= s,/,$$QMAKE_DIR_SEP,g
-OUTDIR ~= s,/,$$QMAKE_DIR_SEP,g
DSTDIR ~= s,/,$$QMAKE_DIR_SEP,g
-QMAKE_POST_LINK += xcopy /y /I $$quote($$OUTDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /I $$quote($$OUTDIR\\ModOrganizer*.pdb) $$quote($$DSTDIR) $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\stylesheets) $$quote($$DSTDIR)\\stylesheets $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\tutorials) $$quote($$DSTDIR)\\tutorials $$escape_expand(\\n)
-QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\*.qm) $$quote($$DSTDIR)\\translations $$escape_expand(\\n)
+QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n)
+QMAKE_POST_LINK += xcopy /y /I $$quote($$SRCDIR\\ModOrganizer*.exe) $$quote($$DSTDIR) $$escape_expand(\\n)
+QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\stylesheets) $$quote($$DSTDIR)\\stylesheets $$escape_expand(\\n)
+QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\tutorials) $$quote($$DSTDIR)\\tutorials $$escape_expand(\\n)
+QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\*.qm) $$quote($$DSTDIR)\\translations $$escape_expand(\\n)
CONFIG(debug, debug|release) {
greaterThan(QT_MAJOR_VERSION, 4) {
- QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.debug.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
+ QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.debug.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
QMAKE_POST_LINK += copy /y $$quote($$DSTDIR\\dlls\\dlls.manifest.debug.qt5) $$quote($$DSTDIR\\dlls\\dlls.manifest) $$escape_expand(\\n)
QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug.qt5 $$escape_expand(\\n)
} else {
- QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.debug) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
+ QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.debug) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
QMAKE_POST_LINK += copy /y $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug $$quote($$DSTDIR)\\dlls\\dlls.manifest $$escape_expand(\\n)
QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.debug $$escape_expand(\\n)
}
} else {
greaterThan(QT_MAJOR_VERSION, 4) {
- QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
+ QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest.qt5) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
QMAKE_POST_LINK += copy /y $$quote($$DSTDIR\\dlls\\dlls.manifest.qt5) $$quote($$DSTDIR\\dlls\\dlls.manifest) $$escape_expand(\\n)
QMAKE_POST_LINK += del $$quote($$DSTDIR)\\dlls\\dlls.manifest.qt5 $$escape_expand(\\n)
} else {
- QMAKE_POST_LINK += xcopy /y /s /I $$quote($$SRCDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
+ QMAKE_POST_LINK += xcopy /y /s /I $$quote($$BASEDIR\\..\\dlls.*manifest) $$quote($$DSTDIR)\\dlls $$escape_expand(\\n)
}
}
diff --git a/src/organizer_es.ts b/src/organizer_es.ts index cf6f18a6..1803ca7f 100644 --- a/src/organizer_es.ts +++ b/src/organizer_es.ts @@ -1,6 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.0" language="es"> +<?xml version="1.0" ?><!DOCTYPE TS><TS language="es" version="2.0"> <context> <name>AboutDialog</name> <message> @@ -62,7 +60,7 @@ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -159,22 +157,22 @@ Si existe un componente que es requerido llamado "00 Core" . Las opcio <message> <location filename="browserdialog.ui" line="14"/> <source>Some Page</source> - <translation type="unfinished"></translation> + <translation>Alguna Página</translation> </message> <message> <location filename="browserdialog.ui" line="281"/> <source>Search</source> - <translation type="unfinished"></translation> + <translation>Búsqueda</translation> </message> <message> <location filename="browserdialog.cpp" line="95"/> <source>new</source> - <translation type="unfinished"></translation> + <translation>nuevo</translation> </message> <message> <location filename="browserdialog.cpp" line="209"/> <source>failed to start download</source> - <translation type="unfinished"></translation> + <translation>Error al iniciar descarga</translation> </message> </context> <context> @@ -225,20 +223,16 @@ Si existe un componente que es requerido llamado "00 Core" . Las opcio <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html></source> - <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Puede coincidir con una o varias categorÃas de una ID interna de Nexus. Cada vez que se descarga un mod de la página de Nexus, Mod Organizador tratará de resolver la categorÃa definida en Nexus a una disponible en MO</span></p></body></html></translation> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { espacio blanco: pre envoltura; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Se puede sincronizar una o varias categorÃas de nexo a un ID interno. Cada vez que se descarga un mod de la Página Nexus, Mod Organizer tratará de resolver la categorÃa definida en el Nexus a uno disponible en MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Para saber la categoria de una ID usada por nexo, visitar la lista de categorÃas de la página nexo y discernir sobre los enlaces de allÃ.</span></p></body></html></translation> </message> <message> <location filename="categoriesdialog.ui" line="105"/> <source>Parent ID</source> - <translation>Parent ID</translation> + <translation>ID Paternal</translation> </message> <message> <location filename="categoriesdialog.ui" line="108"/> @@ -461,7 +455,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="308"/> <source>Un-Hide</source> - <translation>Un-Hide</translation> + <translation>Hacer Visible</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="310"/> @@ -577,7 +571,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="320"/> <source>Un-Hide</source> - <translation>Un-Hide</translation> + <translation>Hacer Visible</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="322"/> @@ -622,7 +616,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="339"/> <source>Remove All...</source> - <translation>Quitar todos...</translation> + <translation>Eliminando todos...</translation> </message> </context> <context> @@ -635,7 +629,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="321"/> <source>Memory allocation error (in refreshing directory).</source> - <translation type="unfinished"></translation> + <translation>Error de asignación de memoria (en directorio refrescante).</translation> </message> <message> <location filename="downloadmanager.cpp" line="369"/> @@ -705,7 +699,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="640"/> <source>No known download urls. Sorry, this download can't be resumed.</source> - <translation type="unfinished"></translation> + <translation>No se conocen descarga urls. Lo sentimos, esta descarga no se puede reanudar.</translation> </message> <message> <location filename="downloadmanager.cpp" line="695"/> @@ -750,12 +744,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="999"/> <source>Memory allocation error (in processing progress event).</source> - <translation type="unfinished"></translation> + <translation>Error de asignación de memoria (en el procesamiento de eventos de progreso).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1012"/> <source>Memory allocation error (in processing downloaded data).</source> - <translation type="unfinished"></translation> + <translation>Error de asignación de memoria (en el procesamiento de datos descargados).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1141"/> @@ -830,13 +824,13 @@ p, li { white-space: pre-wrap; } <message> <location filename="editexecutablesdialog.ui" line="59"/> <source>Binary</source> - <translation>Fichero</translation> + <translation>Binario</translation> </message> <message> <location filename="editexecutablesdialog.ui" line="66"/> <location filename="editexecutablesdialog.ui" line="69"/> <source>Binary to run</source> - <translation>Fiechero para ser ejecutado</translation> + <translation>Binario para funcionar</translation> </message> <message> <location filename="editexecutablesdialog.ui" line="76"/> @@ -846,18 +840,18 @@ p, li { white-space: pre-wrap; } <message> <location filename="editexecutablesdialog.ui" line="79"/> <source>Browse filesystem for the executable to run.</source> - <translation>Examinar en busca del ejecutable.</translation> + <translation>Explorar sistema de archivos para hacer funcionar el ejecutable.</translation> </message> <message> <location filename="editexecutablesdialog.ui" line="82"/> <location filename="editexecutablesdialog.ui" line="103"/> <source>...</source> - <translation>Examinar</translation> + <translation>...</translation> </message> <message> <location filename="editexecutablesdialog.ui" line="93"/> <source>Start in</source> - <translation>Comienzo en</translation> + <translation>Comenzar en</translation> </message> <message> <location filename="editexecutablesdialog.ui" line="114"/> @@ -956,7 +950,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p <message> <location filename="editexecutablesdialog.cpp" line="149"/> <source>Java (32-bit) required</source> - <translation>Java (32-bit) requeredo</translation> + <translation>Java (32-bit) requerido</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="150"/> @@ -1006,12 +1000,12 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p <message> <location filename="finddialog.ui" line="14"/> <source>Find</source> - <translation>Buscar</translation> + <translation>Encontrar:</translation> </message> <message> <location filename="finddialog.ui" line="24"/> <source>Find what:</source> - <translation>Buscar:</translation> + <translation>Encuentra en:</translation> </message> <message> <location filename="finddialog.ui" line="31"/> @@ -1028,7 +1022,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p <message> <location filename="finddialog.ui" line="53"/> <source>&Find Next</source> - <translation>&Encontrar</translation> + <translation>&Buscar siguiente</translation> </message> <message> <location filename="finddialog.ui" line="60"/> @@ -1133,7 +1127,7 @@ En este momento el único caso que conozco donde esto debe ser sobreescrito es p <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1177,87 +1171,87 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="164"/> <location filename="installationmanager.cpp" line="248"/> - <location filename="installationmanager.cpp" line="530"/> + <location filename="installationmanager.cpp" line="532"/> <source>Extracting files</source> <translation>Extrayendo ficheros</translation> </message> <message> - <location filename="installationmanager.cpp" line="439"/> + <location filename="installationmanager.cpp" line="441"/> <source>failed to create backup</source> <translation>fallo al crear copia de seguridad</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Mod Name</source> <translation>Nombre del Mod</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Name</source> <translation>Nombre</translation> </message> <message> - <location filename="installationmanager.cpp" line="501"/> + <location filename="installationmanager.cpp" line="503"/> <source>Invalid name</source> <translation>Nombre inválido</translation> </message> <message> - <location filename="installationmanager.cpp" line="502"/> + <location filename="installationmanager.cpp" line="504"/> <source>The name you entered is invalid, please enter a different one.</source> <translation>El nombre introducido no es válido, por favor introduzca uno diferente.</translation> </message> <message> - <location filename="installationmanager.cpp" line="610"/> + <location filename="installationmanager.cpp" line="612"/> <source>File format "%1" not supported</source> <translation>Formato de archivo no soportado para "%1"</translation> </message> <message> - <location filename="installationmanager.cpp" line="743"/> + <location filename="installationmanager.cpp" line="745"/> <source>None of the available installer plugins were able to handle that archive</source> <translation>Ninguno de los plugins del instalador disponible son capaces de manejar este archivo</translation> </message> <message> - <location filename="installationmanager.cpp" line="753"/> + <location filename="installationmanager.cpp" line="755"/> <source>no error</source> <translation>sin error</translation> </message> <message> - <location filename="installationmanager.cpp" line="756"/> + <location filename="installationmanager.cpp" line="758"/> <source>7z.dll not found</source> <translation>7z.dll no se encuentra</translation> </message> <message> - <location filename="installationmanager.cpp" line="759"/> + <location filename="installationmanager.cpp" line="761"/> <source>7z.dll isn't valid</source> <translation>7z.dll no es valido</translation> </message> <message> - <location filename="installationmanager.cpp" line="762"/> + <location filename="installationmanager.cpp" line="764"/> <source>archive not found</source> <translation>archivo no encontrado</translation> </message> <message> - <location filename="installationmanager.cpp" line="765"/> + <location filename="installationmanager.cpp" line="767"/> <source>failed to open archive</source> <translation>Error abriendo el fichero</translation> </message> <message> - <location filename="installationmanager.cpp" line="768"/> + <location filename="installationmanager.cpp" line="770"/> <source>unsupported archive type</source> <translation>formato de fichero no soportado</translation> </message> <message> - <location filename="installationmanager.cpp" line="771"/> + <location filename="installationmanager.cpp" line="773"/> <source>internal library error</source> <translation>error interno de libreria</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> + <location filename="installationmanager.cpp" line="776"/> <source>archive invalid</source> <translation>archivo invalido</translation> </message> <message> - <location filename="installationmanager.cpp" line="778"/> + <location filename="installationmanager.cpp" line="780"/> <source>unknown archive error</source> <translation>Error de fichero desconocido</translation> </message> @@ -1277,7 +1271,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="lockeddialog.ui" line="23"/> <source>MO is locked while the executable is running.</source> - <translation>MO esta bloqueado mientras se ejecute el programa.</translation> + <translation>MO esta bloqueado mientras se ejecuta el programa.</translation> </message> <message> <location filename="lockeddialog.ui" line="54"/> @@ -1317,27 +1311,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="97"/> <source>Click blank area to deselect</source> - <translation type="unfinished"></translation> + <translation>Púlsar en el área en blanco para anular la selección</translation> </message> <message> <location filename="mainwindow.ui" line="116"/> <source>If checked, only mods that match all selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>Si se selecciona, sólo mods que responden a todas las categorÃas seleccionadas son mostrados.</translation> </message> <message> <location filename="mainwindow.ui" line="119"/> <source>And</source> - <translation type="unfinished"></translation> + <translation>Y</translation> </message> <message> <location filename="mainwindow.ui" line="129"/> <source>If checked, all mods that match at least one of the selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>Si se selecciona, se muestran todos los mods que coincidan con al menos una de las categorÃas seleccionadas.</translation> </message> <message> <location filename="mainwindow.ui" line="132"/> <source>Or</source> - <translation type="unfinished"></translation> + <translation>O</translation> </message> <message> <location filename="mainwindow.ui" line="171"/> @@ -1354,7 +1348,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1365,6 +1359,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ten en cuenta que en estos momentos tu carga de esp no se mantiene separado para diferentes perfiles.</span></p></body></html></translation> </message> <message> + <location filename="mainwindow.ui" line="215"/> + <source>Open list options...</source> + <translation>Abrir Opciones de la lista...</translation> + </message> + <message> <location filename="mainwindow.ui" line="218"/> <source>Refresh list. This is usually not necessary unless you modified data outside the program.</source> <translation>Recargar lista. Esto es normalmente no necesario, a no ser que hayas modificado algo desde fuera del programa.</translation> @@ -1373,13 +1372,13 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="238"/> <location filename="mainwindow.ui" line="739"/> <source>Restore Backup...</source> - <translation type="unfinished">Restaurar copia de seguridad</translation> + <translation>Restaurar copia de seguridad...</translation> </message> <message> <location filename="mainwindow.ui" line="252"/> <location filename="mainwindow.ui" line="759"/> <source>Create Backup</source> - <translation type="unfinished"></translation> + <translation>Crear Copia de Seguridad</translation> </message> <message> <location filename="mainwindow.ui" line="368"/> @@ -1423,7 +1422,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1443,7 +1442,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1466,7 +1465,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1485,6 +1484,11 @@ p, li { white-space: pre-wrap; } <translation>Plugins</translation> </message> <message> + <location filename="mainwindow.ui" line="715"/> + <source>Sort</source> + <translation>Ordenar</translation> + </message> + <message> <location filename="mainwindow.ui" line="821"/> <source>List of available esp/esm files</source> <translation>Listado de ficheros esp/esm disponibles</translation> @@ -1494,7 +1498,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1503,29 +1507,19 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta lista contiene los ESP y ESMS contenidos en los mods activos. Requieren su propio orden de carga. Utilice arrastrar y soltar para modificar este orden de carga. Tenga en cuenta que MO sólo salvará el orden de carga de los mods que están activos/comprobados.<br />Hay una gran herramienta llamada &quot;BOSS&quot; para ordenar automáticamente los archivos.</span></p></body></html></translation> </message> <message> - <location filename="mainwindow.ui" line="715"/> - <source>Sort</source> - <translation>Ordenar</translation> - </message> - <message> - <location filename="mainwindow.ui" line="215"/> - <source>Open list options...</source> - <translation type="unfinished"></translation> - </message> - <message> <location filename="mainwindow.ui" line="886"/> <source>Archives</source> - <translation type="unfinished"></translation> + <translation>Archivos</translation> </message> <message> <location filename="mainwindow.ui" line="916"/> <source><html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html></source> - <translation type="unfinished"></translation> + <translation><html><head/><body><p>BSAs son paquetes de activos de juego (texturas, scripts, ...). Por defecto, el motor carga estos paquetes en una etapa distinta de archivos sueltos. MO puede gestionar esos archivos para alinear su orden de carga con la de archivos sueltos:</p><p>Si los archivos son <span style=" font-weight:600;">gestionados</span>, se especifica el orden de carga por la prioridad del mod correspondiente (panel izquierdo), lo mismo que los archivos sueltos. Puede activar manualmente cualquier BSA que no tiene un plugin correspondiente activo<br/></p><p>Si los archivos no son <span style=" font-weight:600;">gestionados</span> su orden de carga es especificado por la prioridad del plugin correspondiente (panel de la derecha, pestaña plugins). No podras, activar manualmente BSAs donde el plugin no está activo.</p><p>En cualquiera de los casos no se puede deshabilitar archivos si hay un plugin coincidente, el juego los cargará cueste lo que cueste.</p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="919"/> <source><html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html></source> - <translation type="unfinished"></translation> + <translation><html><head/><body><p>Dejar MO manejar archivos (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">leer más</span></a>)</p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="934"/> @@ -1566,8 +1560,8 @@ BSA marcado aquà se cargan de tal manera que su orden de instalación se cumple </message> <message> <location filename="mainwindow.ui" line="1016"/> - <location filename="mainwindow.cpp" line="3833"/> - <location filename="mainwindow.cpp" line="4705"/> + <location filename="mainwindow.cpp" line="3858"/> + <location filename="mainwindow.cpp" line="4738"/> <source>Refresh</source> <translation>Recargar</translation> </message> @@ -1602,8 +1596,8 @@ BSA marcado aquà se cargan de tal manera que su orden de instalación se cumple <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1747,7 +1741,7 @@ p, li { white-space: pre-wrap; } </message> <message> <location filename="mainwindow.ui" line="1412"/> - <location filename="mainwindow.cpp" line="4646"/> + <location filename="mainwindow.cpp" line="4679"/> <source>Update</source> <translation>Actualizacion</translation> </message> @@ -1791,19 +1785,19 @@ Ahora esto tiene una funcionalidad muy limitada</translation> </message> <message> <location filename="mainwindow.ui" line="1460"/> - <location filename="mainwindow.cpp" line="4728"/> + <location filename="mainwindow.cpp" line="4761"/> <source>Endorse Mod Organizer</source> <translation>Avalar Mod Organizer</translation> </message> <message> <location filename="mainwindow.ui" line="1465"/> <source>Copy Log to Clipboard</source> - <translation type="unfinished">Copiar al Portapapeles</translation> + <translation>Copiar Log al Portapapeles</translation> </message> <message> <location filename="mainwindow.ui" line="1468"/> <source>Ctrl+C</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+C</translation> </message> <message> <location filename="mainwindow.cpp" line="255"/> @@ -1921,6 +1915,25 @@ Ahora esto tiene una funcionalidad muy limitada</translation> <translation>Plugin "%1" fallido</translation> </message> <message> + <location filename="mainwindow.cpp" line="1098"/> + <source>Download?</source> + <translation>Descarga?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1099"/> + <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>Una descarga se ha iniciado, pero no hay página de plugin instalado reconocido. +Si lo descarga de todos modos ninguna información (ej. la versión) se asociará con la descarga. +Continuar?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1140"/> + <source>Browse Mod Page</source> + <translation>Explorar Página de Mod</translation> + </message> + <message> <location filename="mainwindow.cpp" line="1225"/> <source>failed to init plugin %1: %2</source> <translation>fallo al iniciar plugin %1: %2</translation> @@ -1953,6 +1966,11 @@ Ahora esto tiene una funcionalidad muy limitada</translation> <translation>Por favor, pulsa OK una vez que hayas iniciado sesión en steam.</translation> </message> <message> + <location filename="mainwindow.cpp" line="1337"/> + <source>Executable "%1" not found</source> + <translation>Ejecutable "%1" no encontrado</translation> + </message> + <message> <location filename="mainwindow.cpp" line="1351"/> <source>Start Steam?</source> <translation>¿Iniciar Steam?</translation> @@ -1963,924 +1981,889 @@ Ahora esto tiene una funcionalidad muy limitada</translation> <translation>Steam es requerido para iniciar correctamente el juego. ¿DeberÃa MO tratar de iniciar ahora steam?</translation> </message> <message> - <location filename="mainwindow.cpp" line="1562"/> + <location filename="mainwindow.cpp" line="1572"/> <source>Also in: <br></source> <translation>También en: <br></translation> </message> <message> - <location filename="mainwindow.cpp" line="1573"/> + <location filename="mainwindow.cpp" line="1583"/> <source>No conflict</source> <translation>Sin conflictos</translation> </message> <message> - <location filename="mainwindow.cpp" line="1742"/> + <location filename="mainwindow.cpp" line="1752"/> <source><Edit...></source> <translation><Editar...></translation> </message> <message> - <location filename="mainwindow.cpp" line="2008"/> + <location filename="mainwindow.cpp" line="1849"/> + <source>Failed to refresh list of esps: %1</source> + <translation>Fallo al actualizar la lista de esps: %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2025"/> <source>This bsa is enabled in the ini file so it may be required!</source> <translation>Esta bsa está habilitada en el archivo ini, por lo que puede ser necesario</translation> </message> <message> - <location filename="mainwindow.cpp" line="2070"/> + <location filename="mainwindow.cpp" line="2087"/> <source>Activating Network Proxy</source> <translation>Activación de proxy de red</translation> </message> <message> - <location filename="mainwindow.cpp" line="2310"/> - <location filename="mainwindow.cpp" line="4349"/> - <source>Installation successful</source> - <translation>Instalacion completada</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2321"/> - <location filename="mainwindow.cpp" line="4361"/> - <source>Configure Mod</source> - <translation>Configurar Mod</translation> + <location filename="mainwindow.cpp" line="2201"/> + <location filename="mainwindow.cpp" line="2208"/> + <source>Failed to write settings</source> + <translation>Error al escribir la configuración</translation> </message> <message> - <location filename="mainwindow.cpp" line="2322"/> - <location filename="mainwindow.cpp" line="4362"/> - <source>This mod contains ini tweaks. Do you want to configure them now?</source> - <translation>Este mod contiene ajustes del ini. ¿Quieres configurarlos ahora?</translation> + <location filename="mainwindow.cpp" line="2202"/> + <location filename="mainwindow.cpp" line="2209"/> + <source>An error occured trying to write back MO settings: %1</source> + <translation>Ha ocurrido un error tratando de escribir de nuevo la configuración de MO: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2329"/> - <location filename="mainwindow.cpp" line="4369"/> - <source>mod "%1" not found</source> - <translation>mod "%1" no encontrado</translation> + <location filename="mainwindow.cpp" line="2205"/> + <source>File is write protected</source> + <translation>El archivo está protegido contra escritura</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>Installation cancelled</source> - <translation>Instalación cancelada</translation> + <location filename="mainwindow.cpp" line="2206"/> + <source>Invalid file format (probably a bug)</source> + <translation>Formato de archivo no válido (probablemente sea un bug)</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>The mod was not installed completely.</source> - <translation>El mod no fue instalado completamente.</translation> + <location filename="mainwindow.cpp" line="2207"/> + <source>Unknown error %1</source> + <translation>Error desconocido %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2237"/> + <location filename="mainwindow.cpp" line="2254"/> <source>Some plugins could not be loaded</source> <translation>Algún plugins no se pudo cargar</translation> </message> <message> - <location filename="mainwindow.cpp" line="2240"/> + <location filename="mainwindow.cpp" line="2257"/> <source>Too many esps and esms enabled</source> <translation>Demasiados esps y esms habilitado</translation> </message> <message> - <location filename="mainwindow.cpp" line="2243"/> - <location filename="mainwindow.cpp" line="2264"/> + <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2281"/> <source>Description missing</source> <translation>Falta la descripción</translation> </message> <message> - <location filename="mainwindow.cpp" line="2252"/> + <location filename="mainwindow.cpp" line="2269"/> <source>The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:</source> <translation>Los siguientes plugins no se pudieron cargar. La razón puede ser dependencias faltantes (es decir python) o una versión obsoleta:</translation> </message> <message> - <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2277"/> <source>The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></source> <translation>El juego no permite cargar más de 255 plugins activos (incluidos los oficiales). Tienes que desactivar algunos plugins no utilizados o fusionar algunos plugins en uno solo. Aquà podras encontrar una guÃa: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></translation> </message> <message> - <location filename="mainwindow.cpp" line="2286"/> + <location filename="mainwindow.cpp" line="2303"/> <source>Choose Mod</source> <translation>Seleccione Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="2287"/> + <location filename="mainwindow.cpp" line="2304"/> <source>Mod Archive</source> <translation>Archivo Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="2541"/> + <location filename="mainwindow.cpp" line="2327"/> + <location filename="mainwindow.cpp" line="4382"/> + <source>Installation successful</source> + <translation>Instalacion completada</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2338"/> + <location filename="mainwindow.cpp" line="4394"/> + <source>Configure Mod</source> + <translation>Configurar Mod</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2339"/> + <location filename="mainwindow.cpp" line="4395"/> + <source>This mod contains ini tweaks. Do you want to configure them now?</source> + <translation>Este mod contiene ajustes del ini. ¿Quieres configurarlos ahora?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2346"/> + <location filename="mainwindow.cpp" line="4402"/> + <source>mod "%1" not found</source> + <translation>mod "%1" no encontrado</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>Installation cancelled</source> + <translation>Instalación cancelada</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>The mod was not installed completely.</source> + <translation>El mod no fue instalado completamente.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2558"/> <source>Start Tutorial?</source> <translation>Iniciar tutorial?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2542"/> + <location filename="mainwindow.cpp" line="2559"/> <source>You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue?</source> <translation>Estás a punto de iniciar un tutorial. Por razones técnicas, no es posible terminar el tutorial antes de tiempo. ¿Desea continuar?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2686"/> - <location filename="mainwindow.cpp" line="4274"/> + <location filename="mainwindow.cpp" line="2703"/> + <location filename="mainwindow.cpp" line="4307"/> <source>Download started</source> <translation>Descarga iniciada</translation> </message> <message> - <location filename="mainwindow.cpp" line="2747"/> + <location filename="mainwindow.cpp" line="2764"/> <source>failed to update mod list: %1</source> <translation>Fallo al actualizar la lista de Mods: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2791"/> + <location filename="mainwindow.cpp" line="2808"/> <source>failed to spawn notepad.exe: %1</source> <translation>Fallo al cargar el Bloc de notas: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2828"/> + <location filename="mainwindow.cpp" line="2845"/> <source>failed to open %1</source> <translation>Fallo al abrir %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2903"/> + <location filename="mainwindow.cpp" line="2920"/> <source>failed to change origin name: %1</source> <translation>fallo al cambiar el nombre original del fichero %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="1337"/> - <source>Executable "%1" not found</source> - <translation>Ejecutable "%1" no encontrado</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1839"/> - <source>Failed to refresh list of esps: %1</source> - <translation>Fallo al actualizar la lista de esps: %1</translation> + <location filename="mainwindow.cpp" line="2950"/> + <source>failed to move "%1" from mod "%2" to "%3": %4</source> + <translation>Error al mover "%1" desde mod "%2" to "%3": %4</translation> </message> <message> - <location filename="mainwindow.cpp" line="2933"/> - <source>failed to move "%1" from mod "%2" to "%3": %4</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2973"/> + <source><Contains %1></source> + <translation><Contiene %1></translation> </message> <message> - <location filename="mainwindow.cpp" line="2983"/> + <location filename="mainwindow.cpp" line="3006"/> <source><Checked></source> <translation><Marcado></translation> </message> <message> - <location filename="mainwindow.cpp" line="2984"/> + <location filename="mainwindow.cpp" line="3007"/> <source><Unchecked></source> <translation><Desmarcado></translation> </message> <message> - <location filename="mainwindow.cpp" line="2985"/> + <location filename="mainwindow.cpp" line="3008"/> <source><Update></source> <translation><Actualizacion></translation> </message> <message> - <location filename="mainwindow.cpp" line="2988"/> + <location filename="mainwindow.cpp" line="3009"/> + <source><Managed by MO></source> + <translation><Gestionado por MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3010"/> + <source><Managed outside MO></source> + <translation><Gestionado fuera MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3011"/> <source><No category></source> <translation><No categorÃa></translation> </message> <message> - <location filename="mainwindow.cpp" line="2989"/> + <location filename="mainwindow.cpp" line="3012"/> <source><Conflicted></source> <translation><En conflicto></translation> </message> <message> - <location filename="mainwindow.cpp" line="2990"/> + <location filename="mainwindow.cpp" line="3013"/> <source><Not Endorsed></source> <translation><No Avalado></translation> </message> <message> - <location filename="mainwindow.cpp" line="3026"/> + <location filename="mainwindow.cpp" line="3051"/> <source>failed to rename mod: %1</source> <translation>fallo al renombrar el mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3039"/> + <location filename="mainwindow.cpp" line="3064"/> <source>Overwrite?</source> - <translation>¿Sobrescribir?</translation> + <translation>Sobrescribir?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3040"/> + <location filename="mainwindow.cpp" line="3065"/> <source>This will replace the existing mod "%1". Continue?</source> <translation>Esto reemplazará el vigente mod "%1". ¿Desea continuar?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3043"/> + <location filename="mainwindow.cpp" line="3068"/> <source>failed to remove mod "%1"</source> <translation>Fallo eliminando mod "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3047"/> - <location filename="mainwindow.cpp" line="4547"/> - <location filename="mainwindow.cpp" line="4571"/> + <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="4580"/> + <location filename="mainwindow.cpp" line="4604"/> <source>failed to rename "%1" to "%2"</source> <translation>Fallo al renombrar "%1" a "%2"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="3097"/> <source>Multiple esps activated, please check that they don't conflict.</source> <translation>Múltiples esps activados, por favor verifique que no entren en conflicto.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3121"/> - <location filename="mainwindow.cpp" line="3746"/> - <location filename="mainwindow.cpp" line="3754"/> - <location filename="mainwindow.cpp" line="3981"/> + <location filename="mainwindow.cpp" line="3146"/> + <location filename="mainwindow.cpp" line="3771"/> + <location filename="mainwindow.cpp" line="3779"/> + <location filename="mainwindow.cpp" line="4014"/> <source>Confirm</source> <translation>Confirmar</translation> </message> <message> - <location filename="mainwindow.cpp" line="3122"/> + <location filename="mainwindow.cpp" line="3147"/> <source>Remove the following mods?<br><ul>%1</ul></source> <translation>¿Quitar el siguiente mods?<br><ul>%1</ul></translation> </message> <message> - <location filename="mainwindow.cpp" line="3133"/> + <location filename="mainwindow.cpp" line="3158"/> <source>failed to remove mod: %1</source> <translation>fallo al eliminar mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> - <location filename="mainwindow.cpp" line="3171"/> + <location filename="mainwindow.cpp" line="3193"/> + <location filename="mainwindow.cpp" line="3196"/> <source>Failed</source> <translation>Fallo</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> + <location filename="mainwindow.cpp" line="3193"/> <source>Installation file no longer exists</source> <translation>El archivo de instalación ya no existe</translation> </message> <message> - <location filename="mainwindow.cpp" line="3172"/> + <location filename="mainwindow.cpp" line="3197"/> <source>Mods installed with old versions of MO can't be reinstalled in this way.</source> <translation>Mods instalados con las viejas versiones de MO no pueden ser instalados de nuevo de este modo.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3203"/> - <location filename="mainwindow.cpp" line="3230"/> - <source>You need to be logged in with Nexus to endorse</source> - <translation>Necesita estar conectado con Nexus para avalar</translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="3981"/> - <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="4095"/> - <source>Delete %n save(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> - </message> - <message> - <location filename="mainwindow.cpp" line="4974"/> - <source>Extract BSA</source> - <translation>Extraer BSA</translation> + <location filename="mainwindow.cpp" line="3212"/> + <source>You need to be logged in with Nexus to resume a download</source> + <translation>Tienes que estar conectado con Nexus para reanudar una descarga</translation> </message> <message> - <location filename="mainwindow.cpp" line="4931"/> - <location filename="mainwindow.cpp" line="4982"/> - <source>failed to read %1: %2</source> - <translation>fallo al leer %1: %2</translation> + <location filename="mainwindow.cpp" line="3228"/> + <location filename="mainwindow.cpp" line="3255"/> + <source>You need to be logged in with Nexus to endorse</source> + <translation>Necesita estar conectado con Nexus para avalar</translation> </message> <message> - <location filename="mainwindow.cpp" line="4993"/> - <source>This archive contains invalid hashes. Some files may be broken.</source> - <translation>Este archivo contiene hashes no válidos. Algunos archivos pueden estar rotos.</translation> + <location filename="mainwindow.cpp" line="3289"/> + <source>Failed to display overwrite dialog: %1</source> + <translation>No se pudo mostrar diálogo de sobreescritura: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3382"/> + <location filename="mainwindow.cpp" line="3407"/> <source>Nexus ID for this Mod is unknown</source> <translation>Se desconoce la ID en Nexus para este Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="1098"/> - <source>Download?</source> - <translation type="unfinished">Descargas</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1099"/> - <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="mainwindow.cpp" line="1140"/> - <source>Browse Mod Page</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2184"/> - <location filename="mainwindow.cpp" line="2191"/> - <source>Failed to write settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2185"/> - <location filename="mainwindow.cpp" line="2192"/> - <source>An error occured trying to write back MO settings: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2188"/> - <source>File is write protected</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2189"/> - <source>Invalid file format (probably a bug)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2190"/> - <source>Unknown error %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2986"/> - <source><Managed by MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2987"/> - <source><Managed outside MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3187"/> - <source>You need to be logged in with Nexus to resume a download</source> - <translation type="unfinished">Necesita estar conectado con Nexus para avalar</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3264"/> - <source>Failed to display overwrite dialog: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3421"/> - <location filename="mainwindow.cpp" line="3861"/> + <location filename="mainwindow.cpp" line="3446"/> + <location filename="mainwindow.cpp" line="3886"/> <source>Create Mod...</source> <translation>Crear Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3422"/> + <location filename="mainwindow.cpp" line="3447"/> <source>This will move all files from overwrite into a new, regular mod. Please enter a name:</source> <translation>Esto moverá todos los archivos de sobrescritura en un nuevo mod, regular. Por favor, introduzca un nombre:</translation> </message> <message> - <location filename="mainwindow.cpp" line="3431"/> + <location filename="mainwindow.cpp" line="3456"/> <source>A mod with this name already exists</source> <translation>Ya existe un mod con este nombre</translation> </message> <message> - <location filename="mainwindow.cpp" line="3672"/> + <location filename="mainwindow.cpp" line="3697"/> <source>Continue?</source> <translation>¿Continuar?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3673"/> + <location filename="mainwindow.cpp" line="3698"/> <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>El esquema de versiones decide qué versión es considerada más nueva una que otra. Esta función adivinará el esquema de versiones bajo el supuesto de que la versión instalada es obsoleta.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3693"/> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="3718"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry</source> <translation>Lo siento</translation> </message> <message> - <location filename="mainwindow.cpp" line="3694"/> + <location filename="mainwindow.cpp" line="3719"/> <source>I don't know a versioning scheme where %1 is newer than %2.</source> <translation>Se desconoce un esquema de versiones donde %1 es más reciente que %2.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3746"/> + <location filename="mainwindow.cpp" line="3771"/> <source>Really enable all visible mods?</source> <translation>¿Permitir realmente todos los mods visibles?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3754"/> + <location filename="mainwindow.cpp" line="3779"/> <source>Really disable all visible mods?</source> <translation>¿Realmente desactivar todos los mods visibles?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3762"/> + <location filename="mainwindow.cpp" line="3787"/> <source>Choose what to export</source> <translation>Elija un archivo a exportar</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>Everything</source> <translation>Todo</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>All installed mods are included in the list</source> <translation>Todos los mods instalados están incluidos en la lista</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Active Mods</source> <translation>Mods Activos</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Only active (checked) mods from your current profile are included</source> <translation>Mods sólo activos (Marcados) es incluido de su perfil actual</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>Visible</source> <translation>Visible</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>All mods visible in the mod list are included</source> <translation>Todo mods visible en la lista de mod son incluidos</translation> </message> <message> - <location filename="mainwindow.cpp" line="3809"/> + <location filename="mainwindow.cpp" line="3834"/> <source>export failed: %1</source> <translation>Falló al exportar: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3826"/> + <location filename="mainwindow.cpp" line="3851"/> <source>Install Mod...</source> <translation>Instalar Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3828"/> + <location filename="mainwindow.cpp" line="3853"/> <source>Enable all visible</source> <translation>Activar todos los visibles</translation> </message> <message> - <location filename="mainwindow.cpp" line="3829"/> + <location filename="mainwindow.cpp" line="3854"/> <source>Disable all visible</source> <translation>Desactivar todo lo visible</translation> </message> <message> - <location filename="mainwindow.cpp" line="3831"/> + <location filename="mainwindow.cpp" line="3856"/> <source>Check all for update</source> <translation>Comprobar todo para actualizar</translation> </message> <message> - <location filename="mainwindow.cpp" line="3835"/> + <location filename="mainwindow.cpp" line="3860"/> <source>Export to csv...</source> <translation>Exportar a CSV...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3854"/> + <location filename="mainwindow.cpp" line="3879"/> <source>All Mods</source> - <translation type="unfinished"></translation> + <translation>Todo los Mods</translation> </message> <message> - <location filename="mainwindow.cpp" line="3860"/> + <location filename="mainwindow.cpp" line="3885"/> <source>Sync to Mods...</source> <translation>Sincronizar con Mods...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3864"/> + <location filename="mainwindow.cpp" line="3889"/> <source>Restore Backup</source> <translation>Restaurar copia de seguridad</translation> </message> <message> - <location filename="mainwindow.cpp" line="3865"/> + <location filename="mainwindow.cpp" line="3890"/> <source>Remove Backup...</source> <translation>Eliminar copia de seguridad...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3869"/> + <location filename="mainwindow.cpp" line="3894"/> <source>Add/Remove Categories</source> <translation>Añadir/Quitar CategorÃas</translation> </message> <message> - <location filename="mainwindow.cpp" line="3874"/> + <location filename="mainwindow.cpp" line="3899"/> <source>Replace Categories</source> <translation>Remplazar CategorÃas</translation> </message> <message> - <location filename="mainwindow.cpp" line="3879"/> + <location filename="mainwindow.cpp" line="3904"/> <source>Primary Category</source> <translation>CategorÃa Primaria</translation> </message> <message> - <location filename="mainwindow.cpp" line="3886"/> + <location filename="mainwindow.cpp" line="3911"/> <source>Change versioning scheme</source> <translation>Cambiar esquema de versiones</translation> </message> <message> - <location filename="mainwindow.cpp" line="3890"/> + <location filename="mainwindow.cpp" line="3915"/> <source>Un-ignore update</source> <translation>No ignorar actualización</translation> </message> <message> - <location filename="mainwindow.cpp" line="3892"/> + <location filename="mainwindow.cpp" line="3917"/> <source>Ignore update</source> <translation>No Ignorar actualización</translation> </message> <message> - <location filename="mainwindow.cpp" line="3897"/> + <location filename="mainwindow.cpp" line="3922"/> <source>Rename Mod...</source> <translation>Renombrar Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3898"/> + <location filename="mainwindow.cpp" line="3923"/> <source>Remove Mod...</source> <translation>Quitar Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3899"/> + <location filename="mainwindow.cpp" line="3924"/> <source>Reinstall Mod</source> <translation>Reinstalar Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3902"/> + <location filename="mainwindow.cpp" line="3927"/> <source>Un-Endorse</source> <translation>No Avalado</translation> </message> <message> - <location filename="mainwindow.cpp" line="3905"/> - <location filename="mainwindow.cpp" line="3909"/> + <location filename="mainwindow.cpp" line="3930"/> + <location filename="mainwindow.cpp" line="3934"/> <source>Endorse</source> <translation>Avalado</translation> </message> <message> - <location filename="mainwindow.cpp" line="3906"/> + <location filename="mainwindow.cpp" line="3931"/> <source>Won't endorse</source> - <translation>No avalar</translation> + <translation>No avalado</translation> </message> <message> - <location filename="mainwindow.cpp" line="3912"/> + <location filename="mainwindow.cpp" line="3937"/> <source>Endorsement state unknown</source> <translation>Estado de avalado desconocido</translation> </message> <message> - <location filename="mainwindow.cpp" line="3919"/> + <location filename="mainwindow.cpp" line="3944"/> <source>Ignore missing data</source> <translation>Ignorar data desaparecido</translation> </message> <message> - <location filename="mainwindow.cpp" line="3922"/> + <location filename="mainwindow.cpp" line="3947"/> <source>Visit on Nexus</source> <translation>Visite Nexus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3923"/> + <location filename="mainwindow.cpp" line="3948"/> <source>Open in explorer</source> <translation>Abrir en explorador</translation> </message> <message> - <location filename="mainwindow.cpp" line="3927"/> + <location filename="mainwindow.cpp" line="3952"/> <source>Information...</source> <translation>Informacion...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3934"/> - <location filename="mainwindow.cpp" line="5192"/> + <location filename="mainwindow.cpp" line="3959"/> + <location filename="mainwindow.cpp" line="5225"/> <source>Exception: </source> <translation>Excepción:</translation> </message> <message> - <location filename="mainwindow.cpp" line="3936"/> - <location filename="mainwindow.cpp" line="5194"/> + <location filename="mainwindow.cpp" line="3961"/> + <location filename="mainwindow.cpp" line="5227"/> <source>Unknown exception</source> <translation>Excepción desconocida</translation> </message> <message> - <location filename="mainwindow.cpp" line="3955"/> + <location filename="mainwindow.cpp" line="3988"/> <source><All></source> <translation><Todo></translation> </message> <message> - <location filename="mainwindow.cpp" line="3957"/> + <location filename="mainwindow.cpp" line="3990"/> <source><Multiple></source> <translation><Multiple></translation> </message> - <message> - <location filename="mainwindow.cpp" line="5450"/> - <source>Please wait while LOOT is running</source> - <translation type="unfinished"></translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4014"/> + <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> + <translation><numerusform>Seguro que desea eliminar el siguiente %n salvado(s)?<br><ul>%1</ul><br>Los salvados Eliminados serán enviados a la papelera de reciclaje.</numerusform><numerusform>Seguro que desea eliminar el siguiente %n salvado(s)?<br><ul>%1</ul><br>Los salvados Eliminados serán enviados a la papelera de reciclaje.</numerusform></translation> </message> <message> - <source>Really delete "%1"?</source> - <translation type="obsolete">Realmente desea borrar "%1"?</translation> + <location filename="mainwindow.cpp" line="5483"/> + <source>Please wait while LOOT is running</source> + <translation>Por favor espera mientras se está ejecutando LOOT</translation> </message> <message> - <location filename="mainwindow.cpp" line="4093"/> + <location filename="mainwindow.cpp" line="4126"/> <source>Fix Mods...</source> - <translation>Fix Mods...</translation> + <translation>Arreglar Mods...</translation> </message> - <message> - <source>Delete</source> - <translation type="obsolete">Eliminar</translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4128"/> + <source>Delete %n save(s)</source> + <translation><numerusform>Eliminar %n guardado(s)</numerusform><numerusform>Eliminar %n guardo(s)</numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="4122"/> <location filename="mainwindow.cpp" line="4155"/> + <location filename="mainwindow.cpp" line="4188"/> <source>failed to remove %1</source> <translation>Fallo eliminando %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4139"/> - <location filename="mainwindow.cpp" line="4171"/> + <location filename="mainwindow.cpp" line="4172"/> + <location filename="mainwindow.cpp" line="4204"/> <source>failed to create %1</source> <translation>Fallo al crear %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4195"/> + <location filename="mainwindow.cpp" line="4228"/> <source>Can't change download directory while downloads are in progress!</source> <translation>No se puede cambiar el directorio de descarga, mientras que las descargas están en curso</translation> </message> <message> - <location filename="mainwindow.cpp" line="4277"/> + <location filename="mainwindow.cpp" line="4310"/> <source>Download failed</source> <translation>Descarga fallida</translation> </message> <message> - <location filename="mainwindow.cpp" line="4424"/> + <location filename="mainwindow.cpp" line="4457"/> <source>failed to write to file %1</source> <translation>Fallo de escritura en el fichero %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4430"/> + <location filename="mainwindow.cpp" line="4463"/> <source>%1 written</source> <translation>%1 escrito</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Select binary</source> <translation>Selecciona el binario</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Binary</source> <translation>Binario</translation> </message> <message> - <location filename="mainwindow.cpp" line="4495"/> + <location filename="mainwindow.cpp" line="4528"/> <source>Enter Name</source> <translation>Introducir Nombre</translation> </message> <message> - <location filename="mainwindow.cpp" line="4496"/> + <location filename="mainwindow.cpp" line="4529"/> <source>Please enter a name for the executable</source> <translation>Por favor, introduce un nombre para el ejecutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>Not an executable</source> <translation>No es un ejecutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>This is not a recognized executable.</source> <translation>Esto no es un ejecutable reconocido.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4565"/> + <location filename="mainwindow.cpp" line="4590"/> <source>Replace file?</source> <translation>¿Reemplazar archivo?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> + <location filename="mainwindow.cpp" line="4565"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>Ya existe una versión oculta de este archivo. Reemplazarlo?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>File operation failed</source> <translation>La operación del archivo falló</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>Fallo al eliminar "%1". ¿Tal vez no tengas los permisos necesarios?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4590"/> <source>There already is a visible version of this file. Replace it?</source> <translation>Ya existe una versión visible de este archivo. ¿Reemplazarlo?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4590"/> + <location filename="mainwindow.cpp" line="4623"/> <source>file not found: %1</source> <translation>archivo no encontrado: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4603"/> + <location filename="mainwindow.cpp" line="4636"/> <source>failed to generate preview for %1</source> <translation>fallo al generar vista anticipada para %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry, can't preview anything. This function currently does not support extracting from bsas.</source> <translation>Lo sentimos, no se puede obtener una vista previa de nada. Esta función no admite la extracción de bsas.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4648"/> + <location filename="mainwindow.cpp" line="4681"/> <source>Update available</source> <translation>Actualización disponible</translation> </message> <message> - <location filename="mainwindow.cpp" line="4685"/> + <location filename="mainwindow.cpp" line="4718"/> <source>Open/Execute</source> <translation>Abrir/Ejecutar</translation> </message> <message> - <location filename="mainwindow.cpp" line="4686"/> + <location filename="mainwindow.cpp" line="4719"/> <source>Add as Executable</source> <translation>Añadir un ejecutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4690"/> + <location filename="mainwindow.cpp" line="4723"/> <source>Preview</source> <translation>Previsualizar</translation> </message> <message> - <location filename="mainwindow.cpp" line="4696"/> + <location filename="mainwindow.cpp" line="4729"/> <source>Un-Hide</source> <translation>Desocultar</translation> </message> <message> - <location filename="mainwindow.cpp" line="4698"/> + <location filename="mainwindow.cpp" line="4731"/> <source>Hide</source> <translation>Ocultar</translation> </message> <message> - <location filename="mainwindow.cpp" line="4704"/> + <location filename="mainwindow.cpp" line="4737"/> <source>Write To File...</source> <translation>Escribir al fichero...</translation> </message> <message> - <location filename="mainwindow.cpp" line="4729"/> + <location filename="mainwindow.cpp" line="4762"/> <source>Do you want to endorse Mod Organizer on %1 now?</source> <translation>¿Quieres avalar Mod Organizer en %1 ahora?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you!</source> - <translation type="unfinished"></translation> + <translation>Gracias!</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you for your endorsement!</source> - <translation type="unfinished"></translation> + <translation>Gracias por su respaldo!</translation> </message> <message> - <location filename="mainwindow.cpp" line="4860"/> + <location filename="mainwindow.cpp" line="4893"/> <source>Request to Nexus failed: %1</source> <translation>Solicitud de Nexus ha fallado: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4867"/> - <location filename="mainwindow.cpp" line="4885"/> + <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4918"/> <source>login successful</source> <translation>login correcto</translation> </message> <message> - <location filename="mainwindow.cpp" line="4894"/> + <location filename="mainwindow.cpp" line="4927"/> <source>login failed: %1. Trying to download anyway</source> <translation>login fallado: %1. Intentando descarga de todos modos</translation> </message> <message> - <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4933"/> <source>login failed: %1</source> <translation>Falló el inicio de sesión: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4910"/> + <location filename="mainwindow.cpp" line="4943"/> <source>login failed: %1. You need to log-in with Nexus to update MO.</source> <translation>login fallido: %1. Necesitas hacer login con Nexus para actualizar MO.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4964"/> + <location filename="mainwindow.cpp" line="5015"/> + <source>failed to read %1: %2</source> + <translation>fallo al leer %1: %2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="4976"/> <source>Error</source> <translation>Error</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4976"/> <source>failed to extract %1 (errorcode %2)</source> <translation>fallo al extraer %1 (Código de error %2)</translation> </message> <message> - <location filename="mainwindow.cpp" line="5038"/> + <location filename="mainwindow.cpp" line="5007"/> + <source>Extract BSA</source> + <translation>Extraer BSA</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5026"/> + <source>This archive contains invalid hashes. Some files may be broken.</source> + <translation>Este archivo contiene hashes no válidos. Algunos archivos pueden estar rotos.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5071"/> <source>Extract...</source> <translation>Extraer...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5100"/> + <location filename="mainwindow.cpp" line="5133"/> <source>Edit Categories...</source> <translation>Editar CategorÃas...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5101"/> + <location filename="mainwindow.cpp" line="5134"/> <source>Deselect filter</source> - <translation type="unfinished"></translation> + <translation>Deselecciona filtro</translation> </message> <message> - <location filename="mainwindow.cpp" line="5152"/> + <location filename="mainwindow.cpp" line="5185"/> <source>Remove</source> <translation>Eliminar</translation> </message> <message> - <location filename="mainwindow.cpp" line="5163"/> + <location filename="mainwindow.cpp" line="5196"/> <source>Enable all</source> <translation>Activar todo</translation> </message> <message> - <location filename="mainwindow.cpp" line="5164"/> + <location filename="mainwindow.cpp" line="5197"/> <source>Disable all</source> <translation>Desactivar todos</translation> </message> <message> - <location filename="mainwindow.cpp" line="5183"/> + <location filename="mainwindow.cpp" line="5216"/> <source>Unlock load order</source> <translation>Desbloquear el orden de carga</translation> </message> <message> - <location filename="mainwindow.cpp" line="5186"/> + <location filename="mainwindow.cpp" line="5219"/> <source>Lock load order</source> <translation>Orden de carga bloqueado</translation> </message> <message> - <location filename="mainwindow.cpp" line="5319"/> + <location filename="mainwindow.cpp" line="5352"/> <source>depends on missing "%1"</source> - <translation type="unfinished"></translation> + <translation>depende de que falta "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="5323"/> + <location filename="mainwindow.cpp" line="5356"/> <source>incompatible with "%1"</source> - <translation type="unfinished"></translation> + <translation>incompatible con "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="5343"/> + <location filename="mainwindow.cpp" line="5376"/> <source>No profile set</source> - <translation type="unfinished"></translation> + <translation>No conjunto de perfil</translation> </message> <message> - <source>LOOT working</source> - <translation type="obsolete">BOSS trabajando</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="5540"/> + <location filename="mainwindow.cpp" line="5573"/> <source>loot failed. Exit code was: %1</source> - <translation type="unfinished"></translation> + <translation>loot falló. Código de salida fue: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5546"/> + <location filename="mainwindow.cpp" line="5579"/> <source>failed to start loot</source> - <translation type="unfinished"></translation> + <translation>Error al iniciar loot</translation> </message> <message> - <location filename="mainwindow.cpp" line="5549"/> + <location filename="mainwindow.cpp" line="5582"/> <source>failed to run loot: %1</source> - <translation type="unfinished">fallo al ejecutar boss: %1</translation> + <translation>Error al ejecutar loot: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5552"/> + <location filename="mainwindow.cpp" line="5585"/> <source>Errors occured</source> - <translation type="unfinished"></translation> + <translation>Se han producido errores</translation> </message> <message> - <location filename="mainwindow.cpp" line="5601"/> + <location filename="mainwindow.cpp" line="5636"/> <source>Backup of load order created</source> - <translation type="unfinished"></translation> + <translation>Copia de seguridad de orden de carga creado</translation> </message> <message> - <location filename="mainwindow.cpp" line="5611"/> + <location filename="mainwindow.cpp" line="5646"/> <source>Choose backup to restore</source> - <translation type="unfinished"></translation> + <translation>Elije copia de seguridad para restaurar</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>No Backups</source> - <translation type="unfinished"></translation> + <translation>No hay copias de seguridad</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>There are no backups to restore</source> - <translation type="unfinished"></translation> + <translation>No hay copias de seguridad para restaurar</translation> </message> <message> - <location filename="mainwindow.cpp" line="5645"/> - <location filename="mainwindow.cpp" line="5666"/> + <location filename="mainwindow.cpp" line="5680"/> + <location filename="mainwindow.cpp" line="5701"/> <source>Restore failed</source> - <translation type="unfinished"></translation> + <translation>Error en la restauración</translation> </message> <message> - <location filename="mainwindow.cpp" line="5646"/> - <location filename="mainwindow.cpp" line="5667"/> + <location filename="mainwindow.cpp" line="5681"/> + <location filename="mainwindow.cpp" line="5702"/> <source>Failed to restore the backup. Errorcode: %1</source> - <translation type="unfinished"></translation> + <translation>Error al restaurar la copia de seguridad. Código de error: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5657"/> + <location filename="mainwindow.cpp" line="5692"/> <source>Backup of modlist created</source> - <translation type="unfinished"></translation> + <translation>Copia de seguridad de la lista de mod creado</translation> </message> </context> <context> @@ -2895,8 +2878,63 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers <context> <name>ModInfo</name> <message> - <location filename="modinfo.cpp" line="106"/> - <location filename="modinfo.cpp" line="135"/> + <location filename="modinfo.cpp" line="87"/> + <source>Plugins</source> + <translation>Plugins</translation> + </message> + <message> + <location filename="modinfo.cpp" line="88"/> + <source>Textures</source> + <translation>Texturas</translation> + </message> + <message> + <location filename="modinfo.cpp" line="89"/> + <source>Meshes</source> + <translation>Meshes</translation> + </message> + <message> + <location filename="modinfo.cpp" line="90"/> + <source>UI Changes</source> + <translation>UI Cambios</translation> + </message> + <message> + <location filename="modinfo.cpp" line="91"/> + <source>Music</source> + <translation>Music</translation> + </message> + <message> + <location filename="modinfo.cpp" line="92"/> + <source>Sound Effects</source> + <translation>Efectos de Sonido</translation> + </message> + <message> + <location filename="modinfo.cpp" line="93"/> + <source>Scripts</source> + <translation>Scripts</translation> + </message> + <message> + <location filename="modinfo.cpp" line="94"/> + <source>SKSE Plugins</source> + <translation>SKSE Plugins</translation> + </message> + <message> + <location filename="modinfo.cpp" line="95"/> + <source>SkyProc Tools</source> + <translation>SkyProc Tools</translation> + </message> + <message> + <location filename="modinfo.cpp" line="96"/> + <source>Strings</source> + <translation>Strings</translation> + </message> + <message> + <location filename="modinfo.cpp" line="97"/> + <source>invalid content type %1</source> + <translation>tipo de contenido inválido %1</translation> + </message> + <message> + <location filename="modinfo.cpp" line="120"/> + <location filename="modinfo.cpp" line="149"/> <source>invalid index %1</source> <translation>indice invalido %1</translation> </message> @@ -2904,7 +2942,7 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers <context> <name>ModInfoBackup</name> <message> - <location filename="modinfo.cpp" line="930"/> + <location filename="modinfo.cpp" line="949"/> <source>This is the backup of a mod</source> <translation>Esta es la copia de seguridad de un mod</translation> </message> @@ -2945,7 +2983,7 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers <message> <location filename="modinfodialog.ui" line="91"/> <source>Ini Files</source> - <translation type="unfinished"></translation> + <translation>Archivos Ini</translation> </message> <message> <location filename="modinfodialog.ui" line="104"/> @@ -2960,17 +2998,17 @@ Esta función adivinará el esquema de versiones bajo el supuesto de que la vers <message> <location filename="modinfodialog.ui" line="114"/> <source>Ini Tweaks</source> - <translation type="unfinished"></translation> + <translation>Ini Tweaks</translation> </message> <message> <location filename="modinfodialog.ui" line="130"/> <source>This is a list of ini tweaks (ini modifications that can be toggled).</source> - <translation type="unfinished"></translation> + <translation>Esta es una lista de ajustes ini (modificaciones INI que pueden activarse).</translation> </message> <message> <location filename="modinfodialog.ui" line="133"/> <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> + <translation>Esta es una lista de ajustes ini. los ajustes Ini son (generalmente pequeños) fragmentos de archivos ini que se aplican sobre los valores existentes en el skyrim.ini/skyrimprefs.ini. Cada truco se puede activar de forma individual. Debes comprobar la descripción del mod los ajustes son opcionales.</translation> </message> <message> <location filename="modinfodialog.ui" line="169"/> @@ -3120,7 +3158,7 @@ La mayorÃa de los mods no tienen esps opcionales, por lo que es muy probable qu <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3133,7 +3171,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3149,12 +3187,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="657"/> <source>Refresh</source> - <translation>Recargar</translation> + <translation>Refrescar</translation> </message> <message> <location filename="modinfodialog.ui" line="660"/> <source>Refresh all information from Nexus.</source> - <translation>Recargar toda la información de Nexus.</translation> + <translation>Refrescar toda la información de Nexus.</translation> </message> <message> <location filename="modinfodialog.ui" line="674"/> @@ -3166,7 +3204,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3187,7 +3225,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="748"/> <source>Filetree</source> - <translation>Contenido</translation> + <translation>Ãrbol de archivo</translation> </message> <message> <location filename="modinfodialog.ui" line="757"/> @@ -3199,14 +3237,14 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } +p, li { espacio blanco: pre envoltura; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Esta es una vista de directorio modificable del directorio mod. Puedes moverte por archivos mediante arrastrar y soltar; y cambiar su nombre con (doble clic).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Los cambios pasan inmediatamente sobre el disco, también hacen</span><span style=" font-size:8pt; font-weight:600;"> ser cuidadoso</span><span style=" font-size:8pt;">.</span></p></body></html></translation> </message> <message> @@ -3225,227 +3263,227 @@ p, li { white-space: pre-wrap; } <translation>Cerrar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="169"/> + <location filename="modinfodialog.cpp" line="170"/> <source>&Delete</source> - <translation>&Delete</translation> + <translation>&Borrar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="170"/> + <location filename="modinfodialog.cpp" line="171"/> <source>&Rename</source> - <translation>&Rename</translation> + <translation>&Renombrar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="171"/> + <location filename="modinfodialog.cpp" line="172"/> <source>&Hide</source> <translation>&Ocultar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="172"/> + <location filename="modinfodialog.cpp" line="173"/> <source>&Unhide</source> <translation>&Mostrar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="173"/> + <location filename="modinfodialog.cpp" line="174"/> <source>&Open</source> <translation>&Abrir</translation> </message> <message> - <location filename="modinfodialog.cpp" line="174"/> + <location filename="modinfodialog.cpp" line="175"/> <source>&New Folder</source> <translation>&Nueva Carpeta</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes?</source> - <translation>¿Guardar cambios?</translation> + <translation>Guardar cambios?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes to "%1"?</source> - <translation>¿Guardar cambios a %1?</translation> + <translation>Guardar cambios a %1?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>File Exists</source> - <translation>Existe el fichero</translation> + <translation>Archivo Existe</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>A file with that name exists, please enter a new one</source> <translation>Un fichero con ese nombre ya existe, por favor selecciona otro nombre</translation> </message> <message> - <location filename="modinfodialog.cpp" line="642"/> + <location filename="modinfodialog.cpp" line="643"/> <source>failed to move file</source> <translation>Error al mover el fichero</translation> </message> <message> - <location filename="modinfodialog.cpp" line="667"/> + <location filename="modinfodialog.cpp" line="668"/> <source>failed to create directory "optional"</source> <translation>Error al crear el directorio "optional"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="705"/> - <location filename="modinfodialog.cpp" line="1210"/> + <location filename="modinfodialog.cpp" line="706"/> + <location filename="modinfodialog.cpp" line="1211"/> <source>Info requested, please wait</source> <translation>Informacion solicitada, por favor espere</translation> </message> <message> - <location filename="modinfodialog.cpp" line="759"/> + <location filename="modinfodialog.cpp" line="760"/> <source>Main</source> <translation>Principal</translation> </message> <message> - <location filename="modinfodialog.cpp" line="760"/> + <location filename="modinfodialog.cpp" line="761"/> <source>Update</source> <translation>Actualizacion</translation> </message> <message> - <location filename="modinfodialog.cpp" line="761"/> + <location filename="modinfodialog.cpp" line="762"/> <source>Optional</source> <translation>Opcional</translation> </message> <message> - <location filename="modinfodialog.cpp" line="762"/> + <location filename="modinfodialog.cpp" line="763"/> <source>Old</source> <translation>Antiguo</translation> </message> <message> - <location filename="modinfodialog.cpp" line="763"/> + <location filename="modinfodialog.cpp" line="764"/> <source>Misc</source> <translation>Misc</translation> </message> <message> - <location filename="modinfodialog.cpp" line="764"/> + <location filename="modinfodialog.cpp" line="765"/> <source>Unknown</source> <translation>Desconocido</translation> </message> <message> - <location filename="modinfodialog.cpp" line="775"/> + <location filename="modinfodialog.cpp" line="776"/> <source>Current Version: %1</source> <translation>Version actual: %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="779"/> + <location filename="modinfodialog.cpp" line="780"/> <source>No update available</source> <translation>Sin actualizacion</translation> </message> <message> - <location filename="modinfodialog.cpp" line="820"/> + <location filename="modinfodialog.cpp" line="821"/> <source>(description incomplete, please visit nexus)</source> <translation>(descripción incompleta, por favor visite nexus)</translation> </message> <message> - <location filename="modinfodialog.cpp" line="835"/> + <location filename="modinfodialog.cpp" line="836"/> <source><a href="%1">Visit on Nexus</a></source> <translation><a href="%1">Visite en Nexus</a></translation> </message> <message> - <location filename="modinfodialog.cpp" line="914"/> + <location filename="modinfodialog.cpp" line="915"/> <source>Failed to delete %1</source> <translation>Error borrando %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="926"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Confirm</source> <translation>Confirma</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> + <location filename="modinfodialog.cpp" line="926"/> <source>Are sure you want to delete "%1"?</source> <translation>Estas seguro de querer borrar "%1"?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Are sure you want to delete the selected files?</source> <translation>Etas seguro de querer borrar los ficheros seleccionados?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1004"/> - <location filename="modinfodialog.cpp" line="1010"/> + <location filename="modinfodialog.cpp" line="1005"/> + <location filename="modinfodialog.cpp" line="1011"/> <source>New Folder</source> <translation>Nueva Carpeta</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1016"/> + <location filename="modinfodialog.cpp" line="1017"/> <source>Failed to create "%1"</source> <translation>Fallo al crear "%1"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1121"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>Replace file?</source> <translation>¿Reemplazar archivo?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> + <location filename="modinfodialog.cpp" line="1121"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>Ya existe una versión oculta de este archivo. Reemplazarlo?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>File operation failed</source> <translation>La operación de archivo falló.</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>Fallo al eliminar "%1". Tal vez no tienes los permisos necesarios?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1134"/> - <location filename="modinfodialog.cpp" line="1157"/> + <location filename="modinfodialog.cpp" line="1135"/> + <location filename="modinfodialog.cpp" line="1158"/> <source>failed to rename %1 to %2</source> <translation>Fallo al renombrar %1 a %2</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>There already is a visible version of this file. Replace it?</source> <translation>Ya existe una versión visible de este archivo. ¿Reemplazarlo?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1190"/> + <location filename="modinfodialog.cpp" line="1191"/> <source>Un-Hide</source> <translation>Desocultar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1192"/> + <location filename="modinfodialog.cpp" line="1193"/> <source>Hide</source> <translation>Ocultar</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Name</source> <translation>Nombre</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Please enter a name</source> <translation>Por favor, introduzca un nombre</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1238"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>Error</source> <translation>Error</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> + <location filename="modinfodialog.cpp" line="1238"/> <source>Invalid name. Must be a valid file name</source> <translation>Nombre no válido. Debe ser un nombre de archivo válido</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>A tweak by that name exists</source> <translation>Existe un ajuste con ese nombre</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1254"/> + <location filename="modinfodialog.cpp" line="1255"/> <source>Create Tweak</source> <translation>Crear Ajuste Fino</translation> </message> @@ -3453,15 +3491,15 @@ p, li { white-space: pre-wrap; } <context> <name>ModInfoForeign</name> <message> - <location filename="modinfo.cpp" line="1021"/> + <location filename="modinfo.cpp" line="1040"/> <source>This pseudo mod represents content managed outside MO. It isn't modified by MO.</source> - <translation type="unfinished"></translation> + <translation>Esta seudo mod representa contenido administrado fuera MO. No se modifica por MO.</translation> </message> </context> <context> <name>ModInfoOverwrite</name> <message> - <location filename="modinfo.cpp" line="975"/> + <location filename="modinfo.cpp" line="994"/> <source>This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)</source> <translation>Esta pseudo-mod contiene archivos en el árbol de datos virtual que fue modificado (es decir, mediante el kit de construcción)</translation> </message> @@ -3469,18 +3507,18 @@ p, li { white-space: pre-wrap; } <context> <name>ModInfoRegular</name> <message> - <location filename="modinfo.cpp" line="567"/> - <location filename="modinfo.cpp" line="570"/> + <location filename="modinfo.cpp" line="586"/> + <location filename="modinfo.cpp" line="589"/> <source>failed to write %1/meta.ini: error %2</source> - <translation type="unfinished">fallo al escribir %1/meta.ini: %2</translation> + <translation>error al escribir %1/meta.ini: error %2</translation> </message> <message> - <location filename="modinfo.cpp" line="843"/> + <location filename="modinfo.cpp" line="862"/> <source>%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory</source> <translation>%1 no contiene ningún esp/esm y ningún directorio activo (textures, meshes, interface, ...)</translation> </message> <message> - <location filename="modinfo.cpp" line="847"/> + <location filename="modinfo.cpp" line="866"/> <source>Categories: <br></source> <translation>Categorias: <br></translation> </message> @@ -3490,52 +3528,52 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="55"/> <source>Game plugins (esp/esm)</source> - <translation type="unfinished"></translation> + <translation>Plugins de Juego (esp/esm)</translation> </message> <message> <location filename="modlist.cpp" line="56"/> <source>Interface</source> - <translation type="unfinished"></translation> + <translation>Interfaz</translation> </message> <message> <location filename="modlist.cpp" line="57"/> <source>Meshes</source> - <translation type="unfinished"></translation> + <translation>Meshes</translation> </message> <message> <location filename="modlist.cpp" line="58"/> <source>Music</source> - <translation type="unfinished"></translation> + <translation>Music</translation> </message> <message> <location filename="modlist.cpp" line="59"/> <source>Scripts (Papyrus)</source> - <translation type="unfinished"></translation> + <translation>Scripts (Papyrus)</translation> </message> <message> <location filename="modlist.cpp" line="60"/> <source>Script Extender Plugin</source> - <translation type="unfinished"></translation> + <translation>Script Extender Plugin</translation> </message> <message> <location filename="modlist.cpp" line="61"/> <source>SkyProc Patcher</source> - <translation type="unfinished"></translation> + <translation>SkyProc Patcher</translation> </message> <message> <location filename="modlist.cpp" line="62"/> <source>Sound</source> - <translation type="unfinished"></translation> + <translation>Sound</translation> </message> <message> <location filename="modlist.cpp" line="63"/> <source>Strings</source> - <translation type="unfinished"></translation> + <translation>Strings</translation> </message> <message> <location filename="modlist.cpp" line="64"/> <source>Textures</source> - <translation type="unfinished"></translation> + <translation>Texturas</translation> </message> <message> <location filename="modlist.cpp" line="117"/> @@ -3580,7 +3618,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="208"/> <source>Non-MO</source> - <translation type="unfinished"></translation> + <translation>Non-MO</translation> </message> <message> <location filename="modlist.cpp" line="238"/> @@ -3590,7 +3628,6 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="364"/> <source>installed version: "%1", newest version: "%2"</source> - <oldsource>installed version: %1, newest version: %2</oldsource> <translation>version instalada: "%1", nueva version: "%2"</translation> </message> <message> @@ -3631,7 +3668,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="935"/> <source>Content</source> - <translation type="unfinished">Contenido</translation> + <translation>Contenido</translation> </message> <message> <location filename="modlist.cpp" line="936"/> @@ -3702,7 +3739,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="957"/> <source>Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></source> - <translation type="unfinished"></translation> + <translation>Representa el contenido del mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></translation> </message> <message> <location filename="modlist.cpp" line="969"/> @@ -3739,22 +3776,22 @@ p, li { white-space: pre-wrap; } <context> <name>NXMAccessManager</name> <message> - <location filename="nxmaccessmanager.cpp" line="144"/> + <location filename="nxmaccessmanager.cpp" line="152"/> <source>Logging into Nexus</source> <translation>Inicio de sesión en Nexus</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="159"/> + <location filename="nxmaccessmanager.cpp" line="167"/> <source>timeout</source> <translation>Tiempo de espera</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="178"/> + <location filename="nxmaccessmanager.cpp" line="186"/> <source>Unknown error</source> - <translation type="unfinished"></translation> + <translation>Error desconocido</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="204"/> + <location filename="nxmaccessmanager.cpp" line="212"/> <source>Please check your password</source> <translation>Por favor introduzca su contraseña</translation> </message> @@ -3812,7 +3849,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="109"/> <source>%1 not found</source> - <translation type="unfinished">%1 no encontrado</translation> + <translation>%1 no encontrado</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="144"/> @@ -3850,114 +3887,114 @@ p, li { white-space: pre-wrap; } <context> <name>PluginList</name> <message> - <location filename="pluginlist.cpp" line="103"/> + <location filename="pluginlist.cpp" line="104"/> <source>Name</source> <translation>Nombre</translation> </message> <message> - <location filename="pluginlist.cpp" line="104"/> + <location filename="pluginlist.cpp" line="105"/> <source>Priority</source> <translation>Prioridad</translation> </message> <message> - <location filename="pluginlist.cpp" line="105"/> + <location filename="pluginlist.cpp" line="106"/> <source>Mod Index</source> <translation>Ãndice de Mod</translation> </message> <message> - <location filename="pluginlist.cpp" line="106"/> + <location filename="pluginlist.cpp" line="107"/> <source>Flags</source> <translation>Banderas</translation> </message> <message> - <location filename="pluginlist.cpp" line="107"/> - <location filename="pluginlist.cpp" line="119"/> + <location filename="pluginlist.cpp" line="108"/> + <location filename="pluginlist.cpp" line="120"/> <source>unknown</source> <translation>Desconocido</translation> </message> <message> - <location filename="pluginlist.cpp" line="115"/> + <location filename="pluginlist.cpp" line="116"/> <source>Name of your mods</source> <translation>Nombre de tus mods</translation> </message> <message> - <location filename="pluginlist.cpp" line="116"/> + <location filename="pluginlist.cpp" line="117"/> <source>Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority.</source> <translation>Prioridad de carga de tu mod. Cuanto mayor sea, más "importante" es y por lo tanto sobrescribe los datos del plugins con menor prioridad.</translation> </message> <message> - <location filename="pluginlist.cpp" line="118"/> + <location filename="pluginlist.cpp" line="119"/> <source>The modindex determins the formids of objects originating from this mods.</source> <translation>El Ãndice de mod determins la forma ids de objetos que provienen de este mods.</translation> </message> <message> - <location filename="pluginlist.cpp" line="159"/> + <location filename="pluginlist.cpp" line="160"/> <source>failed to update esp info for file %1 (source id: %2), error: %3</source> <translation>fallo al actualizar información del esp del archivo %1 (fuente id: %2), error: %3</translation> </message> <message> - <location filename="pluginlist.cpp" line="227"/> + <location filename="pluginlist.cpp" line="228"/> <source>esp not found: %1</source> <translation>ESP no encontrado: %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="235"/> + <location filename="pluginlist.cpp" line="247"/> <source>Confirm</source> <translation>Confirmar</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> + <location filename="pluginlist.cpp" line="235"/> <source>Really enable all plugins?</source> <translation>¿Realmente habilitar todos los plugins?</translation> </message> <message> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="247"/> <source>Really disable all plugins?</source> <translation>¿Realmente deshabilitar todos los plugins?</translation> </message> <message> - <location filename="pluginlist.cpp" line="397"/> + <location filename="pluginlist.cpp" line="398"/> <source>The file containing locked plugin indices is broken</source> <translation>El fichero que contiene los Ãndices del plugin están bloqueados o rotos</translation> </message> <message> - <location filename="pluginlist.cpp" line="438"/> + <location filename="pluginlist.cpp" line="439"/> <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source> <translation>Algunos de los plugins tienen nombres no válidos! Estos plugins no pueden ser cargados por el juego. Por favor, consulte mo_interface.log para ver una lista de plugins afectados y cambiarles el nombre.</translation> </message> <message> <location filename="pluginlist.cpp" line="806"/> - <source><b>Origin</b>: %1</source> - <translation type="unfinished"></translation> + <source>This plugin can't be disabled (enforced by the game)</source> + <translation>Este plugin no se puede desactivar (impuesto por el juego)</translation> </message> <message> <location filename="pluginlist.cpp" line="808"/> + <source><b>Origin</b>: %1</source> + <translation><b>Origen</b>: %1</translation> + </message> + <message> + <location filename="pluginlist.cpp" line="810"/> <source>Author</source> <translation>Autor</translation> </message> <message> - <location filename="pluginlist.cpp" line="811"/> + <location filename="pluginlist.cpp" line="813"/> <source>Description</source> <translation>Descripcion</translation> </message> <message> - <location filename="pluginlist.cpp" line="804"/> - <source>This plugin can't be disabled (enforced by the game)</source> - <translation>Este plugin no se puede desactivar (impuesto por el juego)</translation> - </message> - <message> - <location filename="pluginlist.cpp" line="814"/> + <location filename="pluginlist.cpp" line="816"/> <source>Missing Masters</source> <translation>Maestros Desaparecidos</translation> </message> <message> - <location filename="pluginlist.cpp" line="821"/> + <location filename="pluginlist.cpp" line="823"/> <source>Enabled Masters</source> <translation>Activar Maestros</translation> </message> <message> - <location filename="pluginlist.cpp" line="972"/> + <location filename="pluginlist.cpp" line="974"/> <source>failed to restore load order for %1</source> <translation>fallo al restaurar el orden de carga %1</translation> </message> @@ -3987,7 +4024,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -4042,7 +4079,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="236"/> <source>"%1" is missing or inaccessible</source> - <translation type="unfinished"></translation> + <translation>"%1" no se encuentra o inaccesible</translation> </message> <message> <location filename="profile.cpp" line="282"/> @@ -4135,7 +4172,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html></source> @@ -4168,7 +4205,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4469,62 +4506,62 @@ p, li { white-space: pre-wrap; } <translation>Fallo al configurar la carga por proxy-dll</translation> </message> <message> - <location filename="main.cpp" line="121"/> + <location filename="main.cpp" line="122"/> <source>Permissions required</source> <translation>Se requieren permisos</translation> </message> <message> - <location filename="main.cpp" line="122"/> + <location filename="main.cpp" line="123"/> <source>The current user account doesn't have the required access rights to run Mod Organizer. The neccessary changes can be made automatically (the MO directory will be made writable for the current user account). You will be asked to run "helper.exe" with administrative rights.</source> <translation>La cuenta de usuario actual no tiene los permisos de acceso requeridos para ejecutar Mod Organizer. Los cambios necesarios se pueden hacer de forma automática (el directorio MO hará escritura para la cuenta de usuario actual). Se le pedirá ejecutar "helper.exe" con derechos administrativos.</translation> </message> <message> - <location filename="main.cpp" line="218"/> - <location filename="main.cpp" line="256"/> + <location filename="main.cpp" line="202"/> + <location filename="main.cpp" line="241"/> <source>Woops</source> <translation>Woops</translation> </message> <message> - <location filename="main.cpp" line="219"/> + <location filename="main.cpp" line="203"/> <source>ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened</source> <translation>¡ModOrganizer se ha estrellado! ¿Se debe crear un archivo de diagnóstico? Si me envÃa el fichero (%1) a sherb@gmx.net, el error es mucho más probable que se arregle. Por favor, incluya una breve descripción de lo que estaba haciendo cuando ocurrió el accidente</translation> </message> <message> - <location filename="main.cpp" line="257"/> + <location filename="main.cpp" line="242"/> <source>ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1</source> <translation>¡ModOrganizer se ha estrellado! Lamentablemente no fue capaz de escribir un archivo de diagnóstico: %1</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <location filename="settings.cpp" line="528"/> <source>Mod Organizer</source> <translation>Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <source>An instance of Mod Organizer is already running</source> <translation>Ya se está ejecutando una instancia de Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="397"/> <source>No game identified in "%1". The directory is required to contain the game binary and its launcher.</source> <translation>Juego no identificado en "%1". Se requiere que el directorio contenga el binario del juego y su lanzador.</translation> </message> <message> - <location filename="main.cpp" line="403"/> - <location filename="main.cpp" line="432"/> + <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="429"/> <source>Please select the game to manage</source> <translation>Por favor seleccione el juego</translation> </message> <message> - <location filename="main.cpp" line="458"/> + <location filename="main.cpp" line="456"/> <source>Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)</source> <translation>Por favor selecciona la edición del juego que tienes (MO no puede iniciar el juego correctamente si esto está mal ajustado!)</translation> </message> <message> - <location filename="main.cpp" line="547"/> + <location filename="main.cpp" line="545"/> <source>failed to start application: %1</source> - <translation type="unfinished"></translation> + <translation>Error al iniciar la aplicación: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="856"/> @@ -4532,28 +4569,28 @@ p, li { white-space: pre-wrap; } <translation>Por favor utilice "Ayuda" en la barra superior para obtener informacion sobre todos los elementos</translation> </message> <message> - <location filename="mainwindow.cpp" line="1649"/> - <location filename="mainwindow.cpp" line="4314"/> + <location filename="mainwindow.cpp" line="1659"/> + <location filename="mainwindow.cpp" line="4347"/> <source><Manage...></source> - <translation><Definir...></translation> + <translation><Gestionar...></translation> </message> <message> - <location filename="mainwindow.cpp" line="1667"/> + <location filename="mainwindow.cpp" line="1677"/> <source>failed to parse profile %1: %2</source> <translation>no se pudo analizar el perfil %1: %2</translation> </message> <message> - <location filename="pluginlist.cpp" line="352"/> + <location filename="pluginlist.cpp" line="353"/> <source>failed to find "%1"</source> <translation>fallo al encontrar %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="516"/> + <location filename="pluginlist.cpp" line="518"/> <source>failed to access %1</source> <translation>Fallo al acceder %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="530"/> + <location filename="pluginlist.cpp" line="532"/> <source>failed to set file time %1</source> <translation>Fallo al definir la hora al fihcero %1</translation> </message> @@ -4565,8 +4602,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="96"/> <source>"%1" is missing or inaccessible</source> - <oldsource>"%1" is missing</oldsource> - <translation type="unfinished"></translation> + <translation>"%1" no se encuentra o inaccesible</translation> </message> <message> <location filename="profilesdialog.cpp" line="80"/> @@ -4580,6 +4616,11 @@ p, li { white-space: pre-wrap; } <translation>Error</translation> </message> <message> + <location filename="safewritefile.cpp" line="33"/> + <source>failed to open temporary file</source> + <translation>Fallo al abrir el archivo temporal</translation> + </message> + <message> <location filename="savegamegamebryo.cpp" line="130"/> <location filename="savegamegamebryo.cpp" line="189"/> <location filename="savegamegamebryo.cpp" line="231"/> @@ -4602,17 +4643,17 @@ p, li { white-space: pre-wrap; } <translation>Proxy DLL</translation> </message> <message> - <location filename="spawn.cpp" line="133"/> + <location filename="spawn.cpp" line="140"/> <source>failed to spawn "%1"</source> <translation>Fallo al crear "%1"</translation> </message> <message> - <location filename="spawn.cpp" line="140"/> + <location filename="spawn.cpp" line="147"/> <source>Elevation required</source> <translation>Elevación requerida</translation> </message> <message> - <location filename="spawn.cpp" line="141"/> + <location filename="spawn.cpp" line="148"/> <source>This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" @@ -4627,30 +4668,25 @@ puede ser instalado para trabajar sin elevación. ¿Comenzar elevación de todos modos? (se le preguntará si desea permitir a Mod Organizer.exe realizar cambios en el sistema)</translation> </message> <message> - <location filename="spawn.cpp" line="156"/> + <location filename="spawn.cpp" line="163"/> <source>failed to spawn "%1": %2</source> <translation>Fallo al crear "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="165"/> + <location filename="spawn.cpp" line="172"/> <source>"%1" doesn't exist</source> <translation>"%1" no existe</translation> </message> <message> - <location filename="spawn.cpp" line="172"/> + <location filename="spawn.cpp" line="179"/> <source>failed to inject dll into "%1": %2</source> <translation>Fallo al injectar la dll en "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="190"/> + <location filename="spawn.cpp" line="197"/> <source>failed to run "%1"</source> <translation>Fallo al abrir %1</translation> </message> - <message> - <location filename="safewritefile.cpp" line="33"/> - <source>failed to open temporary file</source> - <translation>Fallo al abrir el archivo temporal</translation> - </message> </context> <context> <name>QueryOverwriteDialog</name> @@ -4868,12 +4904,12 @@ puede ser instalado para trabajar sin elevación. <message> <location filename="settings.cpp" line="115"/> <source>Failed</source> - <translation type="unfinished">Fallo</translation> + <translation>Error</translation> </message> <message> <location filename="settings.cpp" line="116"/> <source>Sorry, failed to start the helper application</source> - <translation type="unfinished"></translation> + <translation>Lo sentimos, no se pudo iniciar la aplicación auxiliar</translation> </message> <message> <location filename="settings.cpp" line="335"/> @@ -4919,7 +4955,7 @@ puede ser instalado para trabajar sin elevación. <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5013,27 +5049,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="199"/> <source>User interface</source> - <translation type="unfinished"></translation> + <translation>Interfaz de usuario</translation> </message> <message> <location filename="settingsdialog.ui" line="205"/> <source>If checked, the download interface will be more compact.</source> - <translation type="unfinished"></translation> + <translation>Si se marca, la interfaz de descarga será más compacto.</translation> </message> <message> <location filename="settingsdialog.ui" line="208"/> <source>Compact Download Interface</source> - <translation type="unfinished"></translation> + <translation>Interfaz de Descarga Compacto</translation> </message> <message> <location filename="settingsdialog.ui" line="215"/> <source>If checked, the download list will display meta information instead of file names.</source> - <translation type="unfinished"></translation> + <translation>Si se selecciona, la lista de descargas mostrará la información de metadatos en lugar de nombres de archivo.</translation> </message> <message> <location filename="settingsdialog.ui" line="218"/> <source>Download Meta Information</source> - <translation type="unfinished"></translation> + <translation>Descarga Información Meta</translation> </message> <message> <location filename="settingsdialog.ui" line="234"/> @@ -5077,7 +5113,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5205,7 +5241,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5243,7 +5279,7 @@ p, li { white-space: pre-wrap; } There are several means to do this: *Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam.</source> <translation>Mod Organizer necesita una dll que se inyecta en el juego para que todos los mods sean visibles a ella. @@ -5267,8 +5303,8 @@ Si utilizas la versión Steam de Oblivion por defecto NO funcionará. En este ca <message> <location filename="settingsdialog.ui" line="701"/> <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't need an update. Therefore you can configure the version to identify as here. -Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. +On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here. +Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</source> <translation>Mod Organizer utiliza una API proporcionada por Nexus para proporcionar caracterÃsticas como la comprobación de actualizaciones y descarga de archivos. Por desgracia, esta API no ha sido puesta a disposición oficialmente a terceros, como MO por lo que tenemos que pasar por el Nexus Mod Manager para ser permitido. @@ -5284,7 +5320,7 @@ tl;dr-version: Si Nexus-features no funciona, introduzca el número de la versià </message> <message> <location filename="settingsdialog.ui" line="726"/> - <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.</source> <translation>Parece que los juegos ocasionalmente cargan archivos ESP o ESM, incluso si ellos todavÃa no se ha activado como plugins. No, pero sabe cuáles son las circunstancias, pero informes de usuario implican en algunos casos no deseados. Si esto se comprueba, ESPs ESMs no marcadas en la lista son invisibles para el juego y no se pueden cargar.</translation> @@ -5314,20 +5350,23 @@ Desactiva esta opción si deseas utilizar Mod Organizer con conversiones totales <message> <location filename="settingsdialog.ui" line="754"/> <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> + <translation>Desactiva esto para más no mostrar mods instalado fuera de MO en la lista de mod (panel izquierdo). El activo de esos mods entonces serán tratados como si tuvieran prioridad más baja junto con el contenido original del juego.</translation> </message> <message> <location filename="settingsdialog.ui" line="757"/> <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't be resolved correctly. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</source> - <translation type="unfinished"></translation> + <translation>Por defecto Mod Organizer mostrará esp+bsa instalados con herramientas extranjeras como mods (panel izquierdo). Esto le permite controlar su prioridad en relación con otros mods. Esto es particularmente útil si también usas Steam Workshop para instalar mods. +Sin embargo, si has instalado mods de archivos sueltos fuera de MO que están en conflicto con BSA también instalara fuera de MO esos conflictos no se pueden resolver correctamente. + +i se desactiva esta función, MO sólo mostrará DLCs oficiales de esta manera. Tenga en cuenta que los plugins (ESP y ESM) que aparecen en el panel derecho seran completamente afectado por esta caracterÃstica.</translation> </message> <message> <location filename="settingsdialog.ui" line="763"/> <source>Display mods installed outside MO</source> - <translation type="unfinished"></translation> + <translation>Mostrar mods instalados fuera MO</translation> </message> <message> <location filename="settingsdialog.ui" line="773"/> @@ -5422,7 +5461,7 @@ Para el resto de los juegos no es un sustituto suficiente para AI</translation> <message> <location filename="singleinstance.cpp" line="88"/> <source>failed to communicate with running instance: %1</source> - <translation type="unfinished">Error al conectarse a la instancia en ejecución: %1</translation> + <translation>Error al comunicarse con instancia en ejecución: %1</translation> </message> <message> <location filename="singleinstance.cpp" line="100"/> @@ -5585,4 +5624,4 @@ C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves <translation>Mover todas las partidas guardadas "%1" para la localización global? Tenga en cuenta que esto se hace un lÃo con el número consecutivo de juegos salvados.</translation> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/src/organizer_fr.ts b/src/organizer_fr.ts index 9e5af1af..004499e8 100644 --- a/src/organizer_fr.ts +++ b/src/organizer_fr.ts @@ -1,48 +1,46 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.0" language="fr"> +<?xml version="1.0" ?><!DOCTYPE TS><TS language="fr" version="2.0"> <context> <name>AboutDialog</name> <message> <location filename="aboutdialog.ui" line="14"/> <location filename="aboutdialog.ui" line="53"/> <source>About</source> - <translation type="unfinished"></translation> + <translation>A propros</translation> </message> <message> <location filename="aboutdialog.ui" line="66"/> <source>Revision:</source> - <translation type="unfinished"></translation> + <translation>Révision :</translation> </message> <message> <location filename="aboutdialog.ui" line="104"/> <source>Used Software</source> - <translation type="unfinished"></translation> + <translation>Logiciel utilisé</translation> </message> <message> <location filename="aboutdialog.ui" line="117"/> <source>Credits</source> - <translation type="unfinished"></translation> + <translation>Crédits</translation> </message> <message> <location filename="aboutdialog.ui" line="123"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation>Traducteurs</translation> </message> <message> <location filename="aboutdialog.ui" line="189"/> <source>Others</source> - <translation type="unfinished"></translation> + <translation>Autres</translation> </message> <message> <location filename="aboutdialog.ui" line="266"/> <source>Close</source> - <translation type="unfinished">Fermer</translation> + <translation>Fermer</translation> </message> <message> <location filename="aboutdialog.cpp" line="80"/> <source>No license</source> - <translation type="unfinished"></translation> + <translation>Pas de license</translation> </message> </context> <context> @@ -62,7 +60,7 @@ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -159,22 +157,22 @@ Si un composant est nommée "00 Core"; il est habituellement nécessai <message> <location filename="browserdialog.ui" line="14"/> <source>Some Page</source> - <translation type="unfinished"></translation> + <translation>Quelques pages</translation> </message> <message> <location filename="browserdialog.ui" line="281"/> <source>Search</source> - <translation type="unfinished"></translation> + <translation>Rechercher</translation> </message> <message> <location filename="browserdialog.cpp" line="95"/> <source>new</source> - <translation type="unfinished"></translation> + <translation>nouveau</translation> </message> <message> <location filename="browserdialog.cpp" line="209"/> <source>failed to start download</source> - <translation type="unfinished"></translation> + <translation>échec du lancement du téléchargement</translation> </message> </context> <context> @@ -225,7 +223,7 @@ Si un composant est nommée "00 Core"; il est habituellement nécessai <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html></source> @@ -296,7 +294,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="directoryrefresher.cpp" line="146"/> <source>failed to read bsa: %1</source> - <translation>Échec de lecture bsa: %1</translation> + <translation>échec de lecture du bsa: %1</translation> </message> </context> <context> @@ -314,7 +312,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlist.cpp" line="66"/> <source>Done</source> - <translation type="unfinished">Terminé</translation> + <translation>Terminé</translation> </message> <message> <location filename="downloadlist.cpp" line="82"/> @@ -324,7 +322,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlist.cpp" line="89"/> <source>pending download</source> - <translation type="unfinished"></translation> + <translation>téléchargement en attente</translation> </message> </context> <context> @@ -333,7 +331,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidget.ui" line="17"/> <location filename="downloadlistwidget.ui" line="61"/> <source>Placeholder</source> - <translation>substitut</translation> + <translation>*Substitut*</translation> </message> <message> <location filename="downloadlistwidget.ui" line="99"/> @@ -367,7 +365,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidgetcompact.ui" line="17"/> <location filename="downloadlistwidgetcompact.ui" line="56"/> <source>Placeholder</source> - <translation>*substitut*</translation> + <translation>*Substitut*</translation> </message> <message> <location filename="downloadlistwidgetcompact.ui" line="122"/> @@ -380,17 +378,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="92"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation>< mod %1 file %2 ></translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="97"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>En attente</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="120"/> <source>Paused</source> - <translation type="unfinished">En pause</translation> + <translation>En pause</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="123"/> @@ -458,17 +456,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="306"/> <source>Delete</source> - <translation type="unfinished">Supprimer</translation> + <translation>Supprimer</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="308"/> <source>Un-Hide</source> - <translation type="unfinished"></translation> + <translation>Montrer</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="310"/> <source>Remove from View</source> - <translation>Enlever de la liste</translation> + <translation>Cacher de la liste</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="313"/> @@ -493,7 +491,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="322"/> <source>Delete Installed...</source> - <translation type="unfinished">Supprimer ceux installés...</translation> + <translation>Supprimer ceux installés...</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="323"/> @@ -516,12 +514,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="93"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation>< mod %1 file %2 ></translation> </message> <message> <location filename="downloadlistwidget.cpp" line="96"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>En attente</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="123"/> @@ -539,7 +537,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidget.cpp" line="276"/> <location filename="downloadlistwidget.cpp" line="285"/> <source>Are you sure?</source> - <translation>Êtes-vous certain?</translation> + <translation>Êtes-vous certain ?</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="259"/> @@ -574,17 +572,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="318"/> <source>Delete</source> - <translation type="unfinished">Supprimer</translation> + <translation>Supprimer</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="320"/> <source>Un-Hide</source> - <translation type="unfinished"></translation> + <translation>Montrer</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="322"/> <source>Remove from View</source> - <translation>Enlever de la liste</translation> + <translation>Cacher de la liste</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="325"/> @@ -619,12 +617,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="338"/> <source>Remove Installed...</source> - <translation>Enlever de la liste ceux installés...</translation> + <translation>Enlever ceux installés de la liste ...</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="339"/> <source>Remove All...</source> - <translation>Enlever tout de la liste...</translation> + <translation>Tour enlever de la liste...</translation> </message> </context> <context> @@ -632,12 +630,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="142"/> <source>failed to rename "%1" to "%2"</source> - <translation>Impossible de renommer "%1" en "%2"</translation> + <translation>impossible de renommer "%1" en "%2"</translation> </message> <message> <location filename="downloadmanager.cpp" line="321"/> <source>Memory allocation error (in refreshing directory).</source> - <translation type="unfinished"></translation> + <translation>Erreur d'allocation de la mémoire (dans le répertoire d'actualisation).</translation> </message> <message> <location filename="downloadmanager.cpp" line="369"/> @@ -652,17 +650,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="417"/> <source>failed to download %1: could not open output file: %2</source> - <translation>impossible de télécharger %1: impossible d'écrire le fichier: %2</translation> + <translation>impossible de télécharger %1: l'écriture sur le fichier à échouée : %2</translation> </message> <message> <location filename="downloadmanager.cpp" line="454"/> <source>Wrong Game</source> - <translation type="unfinished"></translation> + <translation>Jeu incorrect</translation> </message> <message> <location filename="downloadmanager.cpp" line="454"/> <source>The download link is for a mod for "%1" but this instance of MO has been set up for "%2".</source> - <translation type="unfinished"></translation> + <translation>Le lien de téléchargement est pour un mod pour "%1", mais cette instance de MO à été installée pour "%2".</translation> </message> <message> <location filename="downloadmanager.cpp" line="471"/> @@ -707,7 +705,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="640"/> <source>No known download urls. Sorry, this download can't be resumed.</source> - <translation type="unfinished"></translation> + <translation>Aucune adresse de téléchargement connue. Désolé, ce téléchargement ne peut être repris.</translation> </message> <message> <location filename="downloadmanager.cpp" line="695"/> @@ -722,42 +720,42 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="744"/> <source>Main</source> - <translation type="unfinished">Principal</translation> + <translation>Principal</translation> </message> <message> <location filename="downloadmanager.cpp" line="745"/> <source>Update</source> - <translation type="unfinished"></translation> + <translation>Mise à jour</translation> </message> <message> <location filename="downloadmanager.cpp" line="746"/> <source>Optional</source> - <translation type="unfinished">Optionnel</translation> + <translation>Optionnel</translation> </message> <message> <location filename="downloadmanager.cpp" line="747"/> <source>Old</source> - <translation type="unfinished">Ancien</translation> + <translation>Obsolète</translation> </message> <message> <location filename="downloadmanager.cpp" line="748"/> <source>Misc</source> - <translation type="unfinished">Divers</translation> + <translation>Divers</translation> </message> <message> <location filename="downloadmanager.cpp" line="749"/> <source>Unknown</source> - <translation type="unfinished">Inconnu</translation> + <translation>Inconnu</translation> </message> <message> <location filename="downloadmanager.cpp" line="999"/> <source>Memory allocation error (in processing progress event).</source> - <translation type="unfinished"></translation> + <translation>Erreur d'allocation de la mémoire (lors du traitement de la progression événementielle).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1012"/> <source>Memory allocation error (in processing downloaded data).</source> - <translation type="unfinished"></translation> + <translation>Erreur d'allocation de la mémoire (lors du traitement des données de téléchargement).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1141"/> @@ -783,12 +781,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="1328"/> <source>Failed to request file info from nexus: %1</source> - <translation>Impossible de demander l'info du fichier sur Nexus: %1</translation> + <translation>Impossible de demander l'information du fichier sur Nexus: %1</translation> </message> <message> <location filename="downloadmanager.cpp" line="1356"/> <source>Download failed. Server reported: %1</source> - <translation type="unfinished"></translation> + <translation>Téléchargement échoué : rapport du serveur : %1</translation> </message> <message> <location filename="downloadmanager.cpp" line="1358"/> @@ -943,7 +941,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <message> <location filename="editexecutablesdialog.ui" line="233"/> <source>Close</source> - <translation type="unfinished">Fermer</translation> + <translation>Fermer</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="125"/> @@ -953,7 +951,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <message> <location filename="editexecutablesdialog.cpp" line="125"/> <source>Executable (%1)</source> - <translation>Executable (%1)</translation> + <translation>Exécutable (%1)</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="149"/> @@ -989,13 +987,13 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <location filename="editexecutablesdialog.cpp" line="230"/> <location filename="editexecutablesdialog.cpp" line="278"/> <source>Save Changes?</source> - <translation type="unfinished"></translation> + <translation>Enregistrer les changements ?</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="231"/> <location filename="editexecutablesdialog.cpp" line="279"/> <source>You made changes to the current executable, do you want to save them?</source> - <translation type="unfinished"></translation> + <translation>Vous avez appliqué des modifications aux exécutables courants, voulez vous les enregistrer ? </translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="255"/> @@ -1013,19 +1011,19 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <message> <location filename="finddialog.ui" line="24"/> <source>Find what:</source> - <translation>Rechercher:</translation> + <translation>Rechercher :</translation> </message> <message> <location filename="finddialog.ui" line="31"/> <location filename="finddialog.ui" line="34"/> <source>Search term</source> - <translation>Expression à rechercher</translation> + <translation>Terme à rechercher</translation> </message> <message> <location filename="finddialog.ui" line="47"/> <location filename="finddialog.ui" line="50"/> <source>Find next occurence from current file position.</source> - <translation>Rechercher le suivant à partir de l'emplacement présent.</translation> + <translation>Rechercher l’occurrence suivante à partir de l'emplacement présent.</translation> </message> <message> <location filename="finddialog.ui" line="53"/> @@ -1135,7 +1133,7 @@ Actuellement le seul cas à ma connaissance ou ceci est nécessaire est le Creat <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1146,7 +1144,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="installdialog.ui" line="121"/> <source>Placeholder</source> - <translation>*substitut*</translation> + <translation>*Substitut*</translation> </message> <message> <location filename="installdialog.ui" line="141"/> @@ -1179,87 +1177,87 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="164"/> <location filename="installationmanager.cpp" line="248"/> - <location filename="installationmanager.cpp" line="530"/> + <location filename="installationmanager.cpp" line="532"/> <source>Extracting files</source> <translation>Extraction des fichiers</translation> </message> <message> - <location filename="installationmanager.cpp" line="439"/> + <location filename="installationmanager.cpp" line="441"/> <source>failed to create backup</source> - <translation>Impossible de créer une sauvegarde</translation> + <translation>Impossible de créer une sauvegarde de backup</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Mod Name</source> <translation>Nom du mod</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Name</source> <translation>Nom</translation> </message> <message> - <location filename="installationmanager.cpp" line="501"/> + <location filename="installationmanager.cpp" line="503"/> <source>Invalid name</source> <translation>Nom incorrect</translation> </message> <message> - <location filename="installationmanager.cpp" line="502"/> + <location filename="installationmanager.cpp" line="504"/> <source>The name you entered is invalid, please enter a different one.</source> <translation>Le nom que vous avez entré est invalide, essayez-en un autre SVP.</translation> </message> <message> - <location filename="installationmanager.cpp" line="610"/> + <location filename="installationmanager.cpp" line="612"/> <source>File format "%1" not supported</source> <translation>Format de fichier "%1" non supporté</translation> </message> <message> - <location filename="installationmanager.cpp" line="743"/> + <location filename="installationmanager.cpp" line="745"/> <source>None of the available installer plugins were able to handle that archive</source> <translation>Aucun des plugins installés n'arrive à traiter cette archive</translation> </message> <message> - <location filename="installationmanager.cpp" line="753"/> + <location filename="installationmanager.cpp" line="755"/> <source>no error</source> <translation>aucune erreur</translation> </message> <message> - <location filename="installationmanager.cpp" line="756"/> + <location filename="installationmanager.cpp" line="758"/> <source>7z.dll not found</source> <translation>7z.dll introuvable</translation> </message> <message> - <location filename="installationmanager.cpp" line="759"/> + <location filename="installationmanager.cpp" line="761"/> <source>7z.dll isn't valid</source> <translation>7z.dll invalide</translation> </message> <message> - <location filename="installationmanager.cpp" line="762"/> + <location filename="installationmanager.cpp" line="764"/> <source>archive not found</source> <translation>archive introuvable</translation> </message> <message> - <location filename="installationmanager.cpp" line="765"/> + <location filename="installationmanager.cpp" line="767"/> <source>failed to open archive</source> <translation>impossible d'ouvrir l'archive</translation> </message> <message> - <location filename="installationmanager.cpp" line="768"/> + <location filename="installationmanager.cpp" line="770"/> <source>unsupported archive type</source> <translation>type d'archive non supporté</translation> </message> <message> - <location filename="installationmanager.cpp" line="771"/> + <location filename="installationmanager.cpp" line="773"/> <source>internal library error</source> <translation>erreur de bibliothèque interne</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> + <location filename="installationmanager.cpp" line="776"/> <source>archive invalid</source> <translation>archive invalide</translation> </message> <message> - <location filename="installationmanager.cpp" line="778"/> + <location filename="installationmanager.cpp" line="780"/> <source>unknown archive error</source> <translation>erreur d'archive inconnue</translation> </message> @@ -1319,27 +1317,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="97"/> <source>Click blank area to deselect</source> - <translation type="unfinished"></translation> + <translation>Cliquer sur une zone blanche pour désélectionner </translation> </message> <message> <location filename="mainwindow.ui" line="116"/> <source>If checked, only mods that match all selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>Si coché, seul les mods correspondants à toutes les catégories sélectionnées sont affichés.</translation> </message> <message> <location filename="mainwindow.ui" line="119"/> <source>And</source> - <translation type="unfinished"></translation> + <translation>Et</translation> </message> <message> <location filename="mainwindow.ui" line="129"/> <source>If checked, all mods that match at least one of the selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>Si coché, tout les mods correspondants à au moins une des catégories sélectionnées sont affichés.</translation> </message> <message> <location filename="mainwindow.ui" line="132"/> <source>Or</source> - <translation type="unfinished"></translation> + <translation>Ou</translation> </message> <message> <location filename="mainwindow.ui" line="171"/> @@ -1356,7 +1354,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1367,6 +1365,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Veuillez noter que pour l'instant, l'ordre de chargement des ESPs est commun à tous les profils.</span></p></body></html></translation> </message> <message> + <location filename="mainwindow.ui" line="215"/> + <source>Open list options...</source> + <translation>Ouvre les options de liste...</translation> + </message> + <message> <location filename="mainwindow.ui" line="218"/> <source>Refresh list. This is usually not necessary unless you modified data outside the program.</source> <translation>Actualiser la liste. Normalement inutile à moins que vous n'ayez modifié des données à l'extérieur du programme.</translation> @@ -1375,13 +1378,13 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="238"/> <location filename="mainwindow.ui" line="739"/> <source>Restore Backup...</source> - <translation type="unfinished"></translation> + <translation>Restaurer Sauvegarde</translation> </message> <message> <location filename="mainwindow.ui" line="252"/> <location filename="mainwindow.ui" line="759"/> <source>Create Backup</source> - <translation type="unfinished"></translation> + <translation>Créer Sauvegarde</translation> </message> <message> <location filename="mainwindow.ui" line="368"/> @@ -1425,7 +1428,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1445,7 +1448,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1468,7 +1471,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1484,7 +1487,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="695"/> <source>Plugins</source> - <translation type="unfinished"></translation> + <translation>Plugins</translation> + </message> + <message> + <location filename="mainwindow.ui" line="715"/> + <source>Sort</source> + <translation>Ordonner</translation> </message> <message> <location filename="mainwindow.ui" line="821"/> @@ -1496,7 +1504,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1505,34 +1513,24 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Cette liste contient tous les ESPs et ESMs contenus dans les mods actifs. Ceux-ci requièrent leur propre ordre de chargement. Utilisez le glisser-déposer pour modifier cet ordre. Veuillez noter que MO enregistre l'ordre de chargement seulement pour les mods actif/cochés.<br />Il y a un excellent outil nommé &quot;BOSS&quot; qui classe automatiquement ces fichiers.</span></p></body></html></translation> </message> <message> - <location filename="mainwindow.ui" line="715"/> - <source>Sort</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.ui" line="215"/> - <source>Open list options...</source> - <translation type="unfinished"></translation> - </message> - <message> <location filename="mainwindow.ui" line="886"/> <source>Archives</source> - <translation type="unfinished"></translation> + <translation>Archives</translation> </message> <message> <location filename="mainwindow.ui" line="916"/> <source><html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="919"/> <source><html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="934"/> <source>List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order.</source> - <translation type="unfinished"></translation> + <translation>Liste des Besthesda Softworks Archives. Les archives non cochées ici ne sont pas gérées par MO et ignorent l’ordre d'installation.</translation> </message> <message> <location filename="mainwindow.ui" line="937"/> @@ -1540,226 +1538,223 @@ p, li { white-space: pre-wrap; } By default, BSAs that share their base name with an enabled ESP (i.e. plugin.esp and plugin.bsa) are automatically loaded and will have precedence over all loose files, the installation order you set up to the left is then ignored! BSAs checked here are loaded in such a way that your installation order is obeyed properly.</source> - <translation type="unfinished"></translation> + <translation>Les fichiers BSA sont des archives (comparables aux fichiers .zip) qui contiennent les données de ressource (meshes, textures,...) qui sont utilisées par le jeu. Ainsi, ils sont en "compétition" avec les fichiers "lâches" -non compressés- dans votre répertoire DATA. +Par défaut, les BSAs qui partagent leur nom de base avec un ESP actif (ex : plugin.esp et plugin.bsa) sont automatiquement chargés et ont la précédence sur tout les fichiers lâches; l'ordre d'installation que vous établissez sur la partie gauche est alors ignoré ! + +Les BSAs cochés ici sont chargés d'une telle manière que votre ordre d'installation est correctement respecté. </translation> </message> <message> <location filename="mainwindow.ui" line="983"/> <location filename="mainwindow.ui" line="1042"/> <source>File</source> - <translation type="unfinished">Fichier</translation> + <translation>Fichier</translation> </message> <message> <location filename="mainwindow.ui" line="992"/> <source>Data</source> - <translation type="unfinished">DATA</translation> + <translation>Data</translation> </message> <message> <location filename="mainwindow.ui" line="1010"/> <source>refresh data-directory overview</source> - <translation type="unfinished">Actualiser la vue d'ensemble du dossier DATA</translation> + <translation>actualiser la vue d’ensemble du répertoire data</translation> </message> <message> <location filename="mainwindow.ui" line="1013"/> <source>Refresh the overview. This may take a moment.</source> - <translation type="unfinished">Actualiser la vue d'ensemble. Ceci peut demander un moment.</translation> + <translation>Actualiser la vue d'ensemble. Ceci peut prendre un moment. </translation> </message> <message> <location filename="mainwindow.ui" line="1016"/> - <location filename="mainwindow.cpp" line="3833"/> - <location filename="mainwindow.cpp" line="4705"/> + <location filename="mainwindow.cpp" line="3858"/> + <location filename="mainwindow.cpp" line="4738"/> <source>Refresh</source> - <translation type="unfinished">Actualiser</translation> + <translation>Actualiser</translation> </message> <message> <location filename="mainwindow.ui" line="1032"/> <source>This is an overview of your data directory as visible to the game (and tools). </source> - <translation type="unfinished">Ceci est une vue d'ensemble du dossier DATA tel qu'il apparaît pour le jeu (et les outils).</translation> + <translation>Ceci est une vue d’ensemble du répertoire Data, tel qu'il apparaît à votre jeu (et outils) lancés dans MO.</translation> </message> <message> <location filename="mainwindow.ui" line="1047"/> <source>Mod</source> - <translation type="unfinished">Mod</translation> + <translation>Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1057"/> <location filename="mainwindow.ui" line="1060"/> <source>Filter the above list so that only conflicts are displayed.</source> - <translation type="unfinished">Filtrer la liste ci-dessus pour afficher seulement les conflits.</translation> + <translation>Filtrer la liste ci-dessus afin que seuls les conflits soient affichés.</translation> </message> <message> <location filename="mainwindow.ui" line="1063"/> <source>Show only conflicts</source> - <translation type="unfinished">Afficher seulement les conflits</translation> + <translation>Uniquement afficher les conflits</translation> </message> <message> <location filename="mainwindow.ui" line="1071"/> <source>Saves</source> - <translation type="unfinished">Sauvegardes</translation> + <translation>Sauvegardes</translation> </message> <message> <location filename="mainwindow.ui" line="1095"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ceci est une liste de toutes les parties sauvegardées pour ce jeu. Survolez une entrée de la liste pour obtenir des informations détaillées sur la sauvegarde, incluant une liste de tous les ESPs/EMSs utilisés lors de la sauvegarde mais actuellement désactivés ou absents.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Si vous cliquez &quot;Réparer Mods...&quot; dans le menu contextuel, MO tentera d'activer tous les mods, ESPs et ESMs nécessaires pour résoudre le problème. Rien ne sera désactivé!</span></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="1115"/> <source>Downloads</source> - <translation type="unfinished">Téléchargements</translation> + <translation>Téléchargements</translation> </message> <message> <location filename="mainwindow.ui" line="1147"/> <source>This is a list of mods you downloaded from Nexus. Double click one to install it.</source> - <translation type="unfinished">Ceci est une liste de mods que vous avez téléchargé de Nexus. Double-cliquez en un pour l'installer.</translation> + <translation>Ceci est une liste de mods que vous avez téléchargé depuis de Nexus. Double-clic sur un mod pour l'installer.</translation> </message> <message> <location filename="mainwindow.ui" line="1200"/> <source>Show Hidden</source> - <translation type="unfinished"></translation> + <translation>Montrer les éléments cachés</translation> </message> <message> <location filename="mainwindow.ui" line="1262"/> <source>Tool Bar</source> - <translation type="unfinished">Barre d'outils</translation> + <translation>Barre d'outil</translation> </message> <message> <location filename="mainwindow.ui" line="1304"/> <source>Install Mod</source> - <translation type="unfinished">Installer mod</translation> + <translation>Installer le Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1307"/> <source>Install &Mod</source> - <translation type="unfinished">Installer &mod</translation> + <translation>Installer &Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1310"/> <source>Install a new mod from an archive</source> - <translation type="unfinished">Installer un nouveau mod à partir d'une archive</translation> + <translation>Installe un nouveau mod depuis une archive</translation> </message> <message> <location filename="mainwindow.ui" line="1313"/> <source>Ctrl+M</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+M</translation> </message> <message> <location filename="mainwindow.ui" line="1322"/> <source>Profiles</source> - <translation type="unfinished">Profils</translation> + <translation>Profils</translation> </message> <message> <location filename="mainwindow.ui" line="1325"/> <source>&Profiles</source> - <translation type="unfinished">&Profils</translation> + <translation>&Profils</translation> </message> <message> <location filename="mainwindow.ui" line="1328"/> <source>Configure Profiles</source> - <translation type="unfinished">Configurer les profils</translation> + <translation>Configurer les Profils</translation> </message> <message> <location filename="mainwindow.ui" line="1331"/> <source>Ctrl+P</source> - <translation type="unfinished">Ctrl+P</translation> + <translation>Ctrl+P</translation> </message> <message> <location filename="mainwindow.ui" line="1340"/> <source>Executables</source> - <translation type="unfinished">Programmes</translation> + <translation>Exécutables</translation> </message> <message> <location filename="mainwindow.ui" line="1343"/> <source>&Executables</source> - <translation type="unfinished">Programm&es</translation> + <translation>&Exécutables</translation> </message> <message> <location filename="mainwindow.ui" line="1346"/> <source>Configure the executables that can be started through Mod Organizer</source> - <translation type="unfinished">Configure les programmes pouvant être lancés via Mod Organizer</translation> + <translation>Configure les exécutables qui peuvent êtres lancés à travers Mod Organizer</translation> </message> <message> <location filename="mainwindow.ui" line="1349"/> <source>Ctrl+E</source> - <translation type="unfinished">Ctrl+E</translation> + <translation>Ctrl+E</translation> </message> <message> <location filename="mainwindow.ui" line="1358"/> <location filename="mainwindow.ui" line="1364"/> <source>Tools</source> - <translation type="unfinished"></translation> + <translation>Outils</translation> </message> <message> <location filename="mainwindow.ui" line="1361"/> <source>&Tools</source> - <translation type="unfinished"></translation> + <translation>&Outils</translation> </message> <message> <location filename="mainwindow.ui" line="1367"/> <source>Ctrl+I</source> - <translation type="unfinished">Ctrl+H</translation> + <translation>Ctrl+I</translation> </message> <message> <location filename="mainwindow.ui" line="1376"/> <source>Settings</source> - <translation type="unfinished">Réglages</translation> + <translation>Paramètres</translation> </message> <message> <location filename="mainwindow.ui" line="1379"/> <source>&Settings</source> - <translation type="unfinished">Réglage&s</translation> + <translation>&Paramètres</translation> </message> <message> <location filename="mainwindow.ui" line="1382"/> <source>Configure settings and workarounds</source> - <translation type="unfinished">Configurer les réglages et solutions de rechange</translation> + <translation>Configure les paramètres et solutions alternatives</translation> </message> <message> <location filename="mainwindow.ui" line="1385"/> <source>Ctrl+S</source> - <translation type="unfinished">Ctrl+S</translation> + <translation>Ctrl+S</translation> </message> <message> <location filename="mainwindow.ui" line="1394"/> <source>Nexus</source> - <translation type="unfinished">Nexus</translation> + <translation>Nexus</translation> </message> <message> <location filename="mainwindow.ui" line="1397"/> <source>Search nexus network for more mods</source> - <translation type="unfinished">Effectuer une recherche sur Nexus pour plus de mods</translation> + <translation>Recherche sur le réseau nexus pour plus de mods</translation> </message> <message> <location filename="mainwindow.ui" line="1400"/> <source>Ctrl+N</source> - <translation type="unfinished">Ctrl+N</translation> + <translation>Ctrl+N</translation> </message> <message> <location filename="mainwindow.ui" line="1412"/> - <location filename="mainwindow.cpp" line="4646"/> + <location filename="mainwindow.cpp" line="4679"/> <source>Update</source> <translation>Mise-à -jour</translation> </message> <message> <location filename="mainwindow.ui" line="1415"/> <source>Mod Organizer is up-to-date</source> - <translation type="unfinished">Mod Organizer est à jour</translation> + <translation>Mod Organizer est à jour.</translation> </message> <message> <location filename="mainwindow.ui" line="1427"/> <location filename="mainwindow.cpp" line="573"/> <source>No Problems</source> - <translation type="unfinished"></translation> + <translation>Aucun problèmes</translation> </message> <message> <location filename="mainwindow.ui" line="1430"/> @@ -1767,1101 +1762,1107 @@ p, li { white-space: pre-wrap; } !Work in progress! Right now this has very limited functionality</source> - <translation type="unfinished"></translation> + <translation>Ce bouton apparaît en surbrillance si MO découvre des problèmes potentiels avec votre configuration et offre une aide pour les résoudre. +!Work in progress! +Actuellement une fonctionnalité encore très limitée.</translation> </message> <message> <location filename="mainwindow.ui" line="1442"/> <location filename="mainwindow.ui" line="1445"/> <source>Help</source> - <translation type="unfinished">Aide</translation> + <translation>Aide</translation> </message> <message> <location filename="mainwindow.ui" line="1448"/> <source>Ctrl+H</source> - <translation type="unfinished">Ctrl+H</translation> + <translation>Ctrl+H</translation> </message> <message> <location filename="mainwindow.ui" line="1457"/> <source>Endorse MO</source> - <translation type="unfinished"></translation> + <translation>Recommander MO</translation> </message> <message> <location filename="mainwindow.ui" line="1460"/> - <location filename="mainwindow.cpp" line="4728"/> + <location filename="mainwindow.cpp" line="4761"/> <source>Endorse Mod Organizer</source> - <translation type="unfinished"></translation> + <translation>Recommander Mod Organizer</translation> </message> <message> <location filename="mainwindow.ui" line="1465"/> <source>Copy Log to Clipboard</source> - <translation type="unfinished"></translation> + <translation>Copier les Logs dans le Presse-papier</translation> </message> <message> <location filename="mainwindow.ui" line="1468"/> <source>Ctrl+C</source> - <translation type="unfinished"></translation> + <translation>Ctrl+C</translation> </message> <message> <location filename="mainwindow.cpp" line="255"/> <source>Toolbar</source> - <translation type="unfinished">Barre d'outils</translation> + <translation>Barre d'outil</translation> </message> <message> <location filename="mainwindow.cpp" line="256"/> <source>Desktop</source> - <translation type="unfinished"></translation> + <translation>Bureau</translation> </message> <message> <location filename="mainwindow.cpp" line="257"/> <source>Start Menu</source> - <translation type="unfinished"></translation> + <translation>Menu démarrer</translation> </message> <message> <location filename="mainwindow.cpp" line="561"/> <source>Problems</source> - <translation type="unfinished"></translation> + <translation>Problèmes</translation> </message> <message> <location filename="mainwindow.cpp" line="562"/> <source>There are potential problems with your setup</source> - <translation type="unfinished"></translation> + <translation>Il y a des problèmes potentiels dans votre configuration</translation> </message> <message> <location filename="mainwindow.cpp" line="574"/> <source>Everything seems to be in order</source> - <translation type="unfinished"></translation> + <translation>Tout semble en ordre</translation> </message> <message> <location filename="mainwindow.cpp" line="635"/> <source>Help on UI</source> - <translation type="unfinished"></translation> + <translation>Aide sur l'interface</translation> </message> <message> <location filename="mainwindow.cpp" line="639"/> <source>Documentation Wiki</source> - <translation type="unfinished"></translation> + <translation>Wiki de Documentation</translation> </message> <message> <location filename="mainwindow.cpp" line="643"/> <source>Report Issue</source> - <translation type="unfinished"></translation> + <translation>Reporter un problème</translation> </message> <message> <location filename="mainwindow.cpp" line="647"/> <source>Tutorials</source> - <translation type="unfinished"></translation> + <translation>Tutoriels</translation> </message> <message> <location filename="mainwindow.cpp" line="686"/> <source>About</source> - <translation type="unfinished"></translation> + <translation>A propos</translation> </message> <message> <location filename="mainwindow.cpp" line="687"/> <source>About Qt</source> - <translation type="unfinished"></translation> + <translation>A propos de Qt</translation> </message> <message> <location filename="mainwindow.cpp" line="782"/> <source>failed to save load order: %1</source> - <translation type="unfinished">impossible d'enregistrer l'ordre de chargement: %1</translation> + <translation>Échec de l'enregistrement de l’ordre de chargement : %1</translation> </message> <message> <location filename="mainwindow.cpp" line="793"/> <source>Name</source> - <translation type="unfinished">Nom</translation> + <translation>Nom</translation> </message> <message> <location filename="mainwindow.cpp" line="794"/> <source>Please enter a name for the new profile</source> - <translation type="unfinished">Veuillez inscrire un nom pour le nouveau profil</translation> + <translation>Veuillez entrer un nom pour le nouveau profil</translation> </message> <message> <location filename="mainwindow.cpp" line="802"/> <source>failed to create profile: %1</source> - <translation type="unfinished">impossible de créer le profil: %1</translation> + <translation>création de profil échouée : %1 </translation> </message> <message> <location filename="mainwindow.cpp" line="843"/> <source>Show tutorial?</source> - <translation type="unfinished"></translation> + <translation>Afficher le tutoriel ?</translation> </message> <message> <location filename="mainwindow.cpp" line="844"/> <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 "Help"-menu.</source> - <translation type="unfinished"></translation> + <translation>Vous lancez Mod Organizer pour la première fois. Voulez-vous afficher un tutoriel concernant ses fonctionnalité élémentaires ? Si vous choisissez non, vous pouvez toujours démarrer le tutoriel depuis le menu "Aide".</translation> </message> <message> <location filename="mainwindow.cpp" line="875"/> <source>Downloads in progress</source> - <translation type="unfinished">Téléchargements en cours</translation> + <translation>Téléchargement en cours</translation> </message> <message> <location filename="mainwindow.cpp" line="876"/> <source>There are still downloads in progress, do you really want to quit?</source> - <translation type="unfinished">Il encore des téléchargements en cours, voulez-vous vraiment quitter?</translation> + <translation>Il y a toujours des téléchargements en cours, voulez vous vraiment quitter ?</translation> </message> <message> <location filename="mainwindow.cpp" line="930"/> <source>failed to read savegame: %1</source> - <translation type="unfinished">impossible de lire la sauvegarde: %1</translation> + <translation>échec de lecture de la sauvegarde : %1 </translation> </message> <message> <location filename="mainwindow.cpp" line="1053"/> <source>Plugin "%1" failed: %2</source> - <translation type="unfinished"></translation> + <translation>Le Plugin "%1" à échoué: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1055"/> <source>Plugin "%1" failed</source> - <translation type="unfinished"></translation> + <translation>Le Plugin "%1" à échoué</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1098"/> + <source>Download?</source> + <translation>Télécharger ?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1099"/> + <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"/> + </message> + <message> + <location filename="mainwindow.cpp" line="1140"/> + <source>Browse Mod Page</source> + <translation>Consulter la page-web du Mod</translation> </message> <message> <location filename="mainwindow.cpp" line="1225"/> <source>failed to init plugin %1: %2</source> - <translation type="unfinished"></translation> + <translation>impossible d'initialiser le plugin %1: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1263"/> <source>Plugin error</source> - <translation type="unfinished"></translation> + <translation>Erreur de plugin</translation> </message> <message> <location filename="mainwindow.cpp" line="1264"/> <source>It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem)</source> - <translation type="unfinished"></translation> + <translation>Il semble que le plugin "%1" n'a pas pu être chargé lors du démarrage précédent, provoquant un crash de MO. Voulez vous le désactiver ? +(Note : si il s'agit de la première fois que vous voyez ce message pour ce plugin, vous devriez tenter à nouveau l'opération. Le plugin pourrait cette fois être en mesure de corriger le problème).</translation> </message> <message> <location filename="mainwindow.cpp" line="1323"/> <source>Failed to start "%1"</source> - <translation type="unfinished">impossible de lancer "%1"</translation> + <translation>Échec du lancement de "%1"</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> <source>Waiting</source> - <translation type="unfinished">Attente</translation> + <translation>Attente</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> <source>Please press OK once you're logged into steam.</source> - <translation type="unfinished">Veuillez cliquer OK une fois connecté à steam.</translation> + <translation>Veuillez appuyer sur OK une fois connecté à Steam.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1337"/> + <source>Executable "%1" not found</source> + <translation>Exécutable "%1" introuvable</translation> </message> <message> <location filename="mainwindow.cpp" line="1351"/> <source>Start Steam?</source> - <translation type="unfinished"></translation> + <translation>Démarrer Steam ?</translation> </message> <message> <location filename="mainwindow.cpp" line="1352"/> <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> + <translation>Steam doit être déjà démarré afin de correctement lancer le jeu. MO devrait-il essayer de lancer Steam maintenant ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="1562"/> + <location filename="mainwindow.cpp" line="1572"/> <source>Also in: <br></source> - <translation type="unfinished"></translation> + <translation>Aussi dans : <br></translation> </message> <message> - <location filename="mainwindow.cpp" line="1573"/> + <location filename="mainwindow.cpp" line="1583"/> <source>No conflict</source> - <translation type="unfinished">Aucun conflit</translation> + <translation>Aucun conflit</translation> </message> <message> - <location filename="mainwindow.cpp" line="1742"/> + <location filename="mainwindow.cpp" line="1752"/> <source><Edit...></source> - <translation type="unfinished"><Modifier...></translation> + <translation><Editer...></translation> </message> <message> - <location filename="mainwindow.cpp" line="2008"/> - <source>This bsa is enabled in the ini file so it may be required!</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="1849"/> + <source>Failed to refresh list of esps: %1</source> + <translation>Impossible d'actualiser la liste des esps : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2070"/> - <source>Activating Network Proxy</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2025"/> + <source>This bsa is enabled in the ini file so it may be required!</source> + <translation>Ce bsa étant activé dans le fichier ini, cela devrait être requis !</translation> </message> <message> - <location filename="mainwindow.cpp" line="2310"/> - <location filename="mainwindow.cpp" line="4349"/> - <source>Installation successful</source> - <translation type="unfinished">Installation réussie</translation> + <location filename="mainwindow.cpp" line="2087"/> + <source>Activating Network Proxy</source> + <translation>Activation du Proxy de Réseau.</translation> </message> <message> - <location filename="mainwindow.cpp" line="2321"/> - <location filename="mainwindow.cpp" line="4361"/> - <source>Configure Mod</source> - <translation type="unfinished">Configurer mod</translation> + <location filename="mainwindow.cpp" line="2201"/> + <location filename="mainwindow.cpp" line="2208"/> + <source>Failed to write settings</source> + <translation>Échec de l'écriture des paramètres</translation> </message> <message> - <location filename="mainwindow.cpp" line="2322"/> - <location filename="mainwindow.cpp" line="4362"/> - <source>This mod contains ini tweaks. Do you want to configure them now?</source> - <translation type="unfinished">Ce mod contient des ajustement pour les fichiers ini. Désirez-vous les configurer maintenant?</translation> + <location filename="mainwindow.cpp" line="2202"/> + <location filename="mainwindow.cpp" line="2209"/> + <source>An error occured trying to write back MO settings: %1</source> + <translation>Une erreur est survenue lors de la récupération des paramètres de MO : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2329"/> - <location filename="mainwindow.cpp" line="4369"/> - <source>mod "%1" not found</source> - <translation type="unfinished">"%1" introuvable</translation> + <location filename="mainwindow.cpp" line="2205"/> + <source>File is write protected</source> + <translation>Le fichier est protégé en écriture</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>Installation cancelled</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2206"/> + <source>Invalid file format (probably a bug)</source> + <translation>Format de fichier invalide (probablement un bug)</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>The mod was not installed completely.</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2207"/> + <source>Unknown error %1</source> + <translation>Erreur inconnue %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2237"/> + <location filename="mainwindow.cpp" line="2254"/> <source>Some plugins could not be loaded</source> - <translation type="unfinished"></translation> + <translation>Certains plugins n'ont pas pu être chargés</translation> </message> <message> - <location filename="mainwindow.cpp" line="2240"/> + <location filename="mainwindow.cpp" line="2257"/> <source>Too many esps and esms enabled</source> - <translation type="unfinished"></translation> + <translation>Trop d'esps et d'esms activés</translation> </message> <message> - <location filename="mainwindow.cpp" line="2243"/> - <location filename="mainwindow.cpp" line="2264"/> + <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2281"/> <source>Description missing</source> - <translation type="unfinished"></translation> + <translation>Description manquante</translation> </message> <message> - <location filename="mainwindow.cpp" line="2252"/> + <location filename="mainwindow.cpp" line="2269"/> <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> + <translation>Les plugins suivants n'ont pas pu être chargés. Cela peut être dû à des dépendances manquantes (ex : python) ou une version obsolète :</translation> </message> <message> - <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2277"/> <source>The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></source> - <translation type="unfinished"></translation> + <translation>Le jeu n'autorise pas le plus de 255 plugins actifs (plugins officiels inclus) à être chargés. Vous devriez désactiver les plugins inusités ou fusionner certains plugins dans un seul. Vous pouvez trouver un guide ici : <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></translation> </message> <message> - <location filename="mainwindow.cpp" line="2286"/> + <location filename="mainwindow.cpp" line="2303"/> <source>Choose Mod</source> - <translation type="unfinished">Choisir mod</translation> + <translation>Choisissez un Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="2287"/> + <location filename="mainwindow.cpp" line="2304"/> <source>Mod Archive</source> - <translation type="unfinished">Archive de mod</translation> + <translation>Archive de Mod</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2327"/> + <location filename="mainwindow.cpp" line="4382"/> + <source>Installation successful</source> + <translation>Installation réussie</translation> </message> <message> - <location filename="mainwindow.cpp" line="2541"/> + <location filename="mainwindow.cpp" line="2338"/> + <location filename="mainwindow.cpp" line="4394"/> + <source>Configure Mod</source> + <translation>Configurer le Mod</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2339"/> + <location filename="mainwindow.cpp" line="4395"/> + <source>This mod contains ini tweaks. Do you want to configure them now?</source> + <translation>Ce mod contient des ini tweaks. Désirez-vous les configurer maintenant?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2346"/> + <location filename="mainwindow.cpp" line="4402"/> + <source>mod "%1" not found</source> + <translation>mod "%1" introuvable</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>Installation cancelled</source> + <translation>Installation annulée </translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>The mod was not installed completely.</source> + <translation>Le mod n'a pas été installé complètement</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2558"/> <source>Start Tutorial?</source> - <translation type="unfinished"></translation> + <translation>Démarrer le Tutoriel ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2542"/> + <location filename="mainwindow.cpp" line="2559"/> <source>You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue?</source> - <translation type="unfinished"></translation> + <translation>Vous allez commencer un tutoriel. Pour des raisons techniques, il n'est pas possible de quitter le tutoriel en cours de route. Continuer ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2686"/> - <location filename="mainwindow.cpp" line="4274"/> + <location filename="mainwindow.cpp" line="2703"/> + <location filename="mainwindow.cpp" line="4307"/> <source>Download started</source> - <translation type="unfinished">Téléchargement commencé</translation> + <translation>Le téléchargement vient de démarrer</translation> </message> <message> - <location filename="mainwindow.cpp" line="2747"/> + <location filename="mainwindow.cpp" line="2764"/> <source>failed to update mod list: %1</source> - <translation type="unfinished">impossible de mettre à jour la liste de mods: %1</translation> + <translation>échec lors de l'actualisation de la liste de Mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2791"/> + <location filename="mainwindow.cpp" line="2808"/> <source>failed to spawn notepad.exe: %1</source> - <translation type="unfinished">impossible de lancer notepad.exe: %1</translation> + <translation>impossible d'invoquer notepad.exe : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2828"/> + <location filename="mainwindow.cpp" line="2845"/> <source>failed to open %1</source> - <translation type="unfinished">impossible d'ouvrir %1</translation> + <translation>impossible d'ouvrir %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2903"/> + <location filename="mainwindow.cpp" line="2920"/> <source>failed to change origin name: %1</source> - <translation type="unfinished">impossible de changer le nom d'origine: %1</translation> + <translation>impossible de changer le nom d'origine : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="1337"/> - <source>Executable "%1" not found</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1839"/> - <source>Failed to refresh list of esps: %1</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2950"/> + <source>failed to move "%1" from mod "%2" to "%3": %4</source> + <translation>impossible de déplacer "%1" depuis le mod "%2" vers "%3" : %4</translation> </message> <message> - <location filename="mainwindow.cpp" line="2933"/> - <source>failed to move "%1" from mod "%2" to "%3": %4</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2973"/> + <source><Contains %1></source> + <translation><Contient %1></translation> </message> <message> - <location filename="mainwindow.cpp" line="2983"/> + <location filename="mainwindow.cpp" line="3006"/> <source><Checked></source> - <translation type="unfinished"><Cochés></translation> + <translation><Coché></translation> </message> <message> - <location filename="mainwindow.cpp" line="2984"/> + <location filename="mainwindow.cpp" line="3007"/> <source><Unchecked></source> - <translation type="unfinished"><Décochés></translation> + <translation><Décoché></translation> </message> <message> - <location filename="mainwindow.cpp" line="2985"/> + <location filename="mainwindow.cpp" line="3008"/> <source><Update></source> - <translation type="unfinished"><Rafraichir></translation> + <translation><Mise à jour disponible></translation> </message> <message> - <location filename="mainwindow.cpp" line="2988"/> + <location filename="mainwindow.cpp" line="3009"/> + <source><Managed by MO></source> + <translation><Géré par MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3010"/> + <source><Managed outside MO></source> + <translation><Géré à l’extérieur de MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3011"/> <source><No category></source> - <translation type="unfinished"></translation> + <translation><Sans catégorie></translation> </message> <message> - <location filename="mainwindow.cpp" line="2989"/> + <location filename="mainwindow.cpp" line="3012"/> <source><Conflicted></source> - <translation type="unfinished"></translation> + <translation><Conflits></translation> </message> <message> - <location filename="mainwindow.cpp" line="2990"/> + <location filename="mainwindow.cpp" line="3013"/> <source><Not Endorsed></source> - <translation type="unfinished"></translation> + <translation><Non Recommandé></translation> </message> <message> - <location filename="mainwindow.cpp" line="3026"/> + <location filename="mainwindow.cpp" line="3051"/> <source>failed to rename mod: %1</source> - <translation type="unfinished">impossible de renommer le mod: %1</translation> + <translation>impossible de renommer le Mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3039"/> + <location filename="mainwindow.cpp" line="3064"/> <source>Overwrite?</source> - <translation type="unfinished"></translation> + <translation>Écraser ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3040"/> + <location filename="mainwindow.cpp" line="3065"/> <source>This will replace the existing mod "%1". Continue?</source> - <translation type="unfinished"></translation> + <translation>Cela va remplacer le Mod existant "%1". Continuer ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3043"/> + <location filename="mainwindow.cpp" line="3068"/> <source>failed to remove mod "%1"</source> - <translation type="unfinished">Impossible de supprimer %1</translation> + <translation>Impossible de supprimer le Mod "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3047"/> - <location filename="mainwindow.cpp" line="4547"/> - <location filename="mainwindow.cpp" line="4571"/> + <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="4580"/> + <location filename="mainwindow.cpp" line="4604"/> <source>failed to rename "%1" to "%2"</source> - <translation type="unfinished">Impossible de renommer %1 en %2</translation> + <translation>Impossible de renommer "%1" en "%2"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="3097"/> <source>Multiple esps activated, please check that they don't conflict.</source> - <translation type="unfinished"></translation> + <translation>Plusieurs esps activés, veuillez vérifier qu'ils n'entrent pas en conflit.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3121"/> - <location filename="mainwindow.cpp" line="3746"/> - <location filename="mainwindow.cpp" line="3754"/> - <location filename="mainwindow.cpp" line="3981"/> + <location filename="mainwindow.cpp" line="3146"/> + <location filename="mainwindow.cpp" line="3771"/> + <location filename="mainwindow.cpp" line="3779"/> + <location filename="mainwindow.cpp" line="4014"/> <source>Confirm</source> - <translation type="unfinished">Confirmer</translation> + <translation>Confirmer</translation> </message> <message> - <location filename="mainwindow.cpp" line="3122"/> + <location filename="mainwindow.cpp" line="3147"/> <source>Remove the following mods?<br><ul>%1</ul></source> - <translation type="unfinished"></translation> + <translation>Supprimer les Mods suivants?<br><ul>%1</ul></translation> </message> <message> - <location filename="mainwindow.cpp" line="3133"/> + <location filename="mainwindow.cpp" line="3158"/> <source>failed to remove mod: %1</source> - <translation type="unfinished">impossible de renommer le mod: %1</translation> + <translation>Impossible de supprimer le Mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> - <location filename="mainwindow.cpp" line="3171"/> + <location filename="mainwindow.cpp" line="3193"/> + <location filename="mainwindow.cpp" line="3196"/> <source>Failed</source> - <translation type="unfinished"></translation> + <translation>Échec </translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> + <location filename="mainwindow.cpp" line="3193"/> <source>Installation file no longer exists</source> - <translation type="unfinished"></translation> + <translation>Les fichiers d'installations n'existent plus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3172"/> + <location filename="mainwindow.cpp" line="3197"/> <source>Mods installed with old versions of MO can't be reinstalled in this way.</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3203"/> - <location filename="mainwindow.cpp" line="3230"/> - <source>You need to be logged in with Nexus to endorse</source> - <translation type="unfinished"></translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="3981"/> - <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="4095"/> - <source>Delete %n save(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> + <translation>Les Mods installés avec une anciennes versions de MO ne peuvent être réinstaller de cette manière.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4974"/> - <source>Extract BSA</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="3212"/> + <source>You need to be logged in with Nexus to resume a download</source> + <translation>Vous devez être connecté à Nexus pour continuer le téléchargement</translation> </message> <message> - <location filename="mainwindow.cpp" line="4931"/> - <location filename="mainwindow.cpp" line="4982"/> - <source>failed to read %1: %2</source> - <translation type="unfinished">Échec de lecture %1: %2</translation> + <location filename="mainwindow.cpp" line="3228"/> + <location filename="mainwindow.cpp" line="3255"/> + <source>You need to be logged in with Nexus to endorse</source> + <translation>Vous devez être connecté à Nexus pour recommander un mod.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4993"/> - <source>This archive contains invalid hashes. Some files may be broken.</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="3289"/> + <source>Failed to display overwrite dialog: %1</source> + <translation>Impossible d'afficher la boite de dialogue overwrite : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3382"/> + <location filename="mainwindow.cpp" line="3407"/> <source>Nexus ID for this Mod is unknown</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1098"/> - <source>Download?</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1099"/> - <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="mainwindow.cpp" line="1140"/> - <source>Browse Mod Page</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2184"/> - <location filename="mainwindow.cpp" line="2191"/> - <source>Failed to write settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2185"/> - <location filename="mainwindow.cpp" line="2192"/> - <source>An error occured trying to write back MO settings: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2188"/> - <source>File is write protected</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2189"/> - <source>Invalid file format (probably a bug)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2190"/> - <source>Unknown error %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2986"/> - <source><Managed by MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2987"/> - <source><Managed outside MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3187"/> - <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="3264"/> - <source>Failed to display overwrite dialog: %1</source> - <translation type="unfinished"></translation> + <translation>L'ID Nexus de ce Mod est inconnu</translation> </message> <message> - <location filename="mainwindow.cpp" line="3421"/> - <location filename="mainwindow.cpp" line="3861"/> + <location filename="mainwindow.cpp" line="3446"/> + <location filename="mainwindow.cpp" line="3886"/> <source>Create Mod...</source> - <translation type="unfinished"></translation> + <translation>Crée le Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3422"/> + <location filename="mainwindow.cpp" line="3447"/> <source>This will move all files from overwrite into a new, regular mod. Please enter a name:</source> - <translation type="unfinished"></translation> + <translation>Ceci va déplacer tout les fichiers présent dans Overwrite dans un nouveau mod ordinaire. +Veuillez nommer ce mod : </translation> </message> <message> - <location filename="mainwindow.cpp" line="3431"/> + <location filename="mainwindow.cpp" line="3456"/> <source>A mod with this name already exists</source> - <translation type="unfinished"></translation> + <translation>Un Mod avec ce nom existe déjà </translation> </message> <message> - <location filename="mainwindow.cpp" line="3672"/> + <location filename="mainwindow.cpp" line="3697"/> <source>Continue?</source> - <translation type="unfinished"></translation> + <translation>Continuer ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3673"/> + <location filename="mainwindow.cpp" line="3698"/> <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> + <translation>Le système de syntaxe de version décide quelle version est considérée plus récente qu'une autre. +Cette fonction va deviner quel système de version utiliser dans l'hypothèse que la version installée est obsolète.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3693"/> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="3718"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry</source> - <translation type="unfinished"></translation> + <translation>Désolé</translation> </message> <message> - <location filename="mainwindow.cpp" line="3694"/> + <location filename="mainwindow.cpp" line="3719"/> <source>I don't know a versioning scheme where %1 is newer than %2.</source> - <translation type="unfinished"></translation> + <translation>Je ne connait pas un système de version dans lequel %1 est plus récent que %2.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3746"/> + <location filename="mainwindow.cpp" line="3771"/> <source>Really enable all visible mods?</source> - <translation type="unfinished"></translation> + <translation>Voulez vous vraiment activer tout les mods visibles ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3754"/> + <location filename="mainwindow.cpp" line="3779"/> <source>Really disable all visible mods?</source> - <translation type="unfinished"></translation> + <translation>Voulez vous vraiment désactiver tout les mods visibles ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3762"/> + <location filename="mainwindow.cpp" line="3787"/> <source>Choose what to export</source> - <translation type="unfinished"></translation> + <translation>Choisissez ce que vous voulez exporter </translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>Everything</source> - <translation type="unfinished"></translation> + <translation>Tout</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>All installed mods are included in the list</source> - <translation type="unfinished"></translation> + <translation>Tous les Mods installés sont inclus dans cette liste</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Active Mods</source> - <translation type="unfinished">Activer Mods</translation> + <translation>Mods actifs</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Only active (checked) mods from your current profile are included</source> - <translation type="unfinished"></translation> + <translation>Seuls les mods actifs (cochés) de votre profil actif seront inclus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>Visible</source> - <translation type="unfinished"></translation> + <translation>Visible</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>All mods visible in the mod list are included</source> - <translation type="unfinished"></translation> + <translation>Tout les mods visible dans la liste de mod sont inclus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3809"/> + <location filename="mainwindow.cpp" line="3834"/> <source>export failed: %1</source> - <translation type="unfinished"></translation> + <translation>échec de l'exportation : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3826"/> + <location filename="mainwindow.cpp" line="3851"/> <source>Install Mod...</source> - <translation type="unfinished">Installer mod...</translation> + <translation>Installer le Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3828"/> + <location filename="mainwindow.cpp" line="3853"/> <source>Enable all visible</source> - <translation type="unfinished">Activer tous les mods visibles</translation> + <translation>Activer tout mod visible</translation> </message> <message> - <location filename="mainwindow.cpp" line="3829"/> + <location filename="mainwindow.cpp" line="3854"/> <source>Disable all visible</source> - <translation type="unfinished">Désactiver tous les mods visibles</translation> + <translation>Désactiver tout mod visible</translation> </message> <message> - <location filename="mainwindow.cpp" line="3831"/> + <location filename="mainwindow.cpp" line="3856"/> <source>Check all for update</source> - <translation type="unfinished">Vérifier toutes les mises à jour</translation> + <translation>Vérifier toutes les mises à jour</translation> </message> <message> - <location filename="mainwindow.cpp" line="3835"/> + <location filename="mainwindow.cpp" line="3860"/> <source>Export to csv...</source> - <translation type="unfinished"></translation> + <translation>Exporter en csv...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3854"/> + <location filename="mainwindow.cpp" line="3879"/> <source>All Mods</source> - <translation type="unfinished"></translation> + <translation>Tout les Mods</translation> </message> <message> - <location filename="mainwindow.cpp" line="3860"/> + <location filename="mainwindow.cpp" line="3885"/> <source>Sync to Mods...</source> - <translation type="unfinished"></translation> + <translation>Synchroniser vers les Mods...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3864"/> + <location filename="mainwindow.cpp" line="3889"/> <source>Restore Backup</source> - <translation type="unfinished"></translation> + <translation>Restaurer la sauvegarde</translation> </message> <message> - <location filename="mainwindow.cpp" line="3865"/> + <location filename="mainwindow.cpp" line="3890"/> <source>Remove Backup...</source> - <translation type="unfinished"></translation> + <translation>Supprimer la sauvegarde...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3869"/> + <location filename="mainwindow.cpp" line="3894"/> <source>Add/Remove Categories</source> - <translation type="unfinished"></translation> + <translation>Ajouter/Enlever des catégories</translation> </message> <message> - <location filename="mainwindow.cpp" line="3874"/> + <location filename="mainwindow.cpp" line="3899"/> <source>Replace Categories</source> - <translation type="unfinished"></translation> + <translation>Remplacer les catégories</translation> </message> <message> - <location filename="mainwindow.cpp" line="3879"/> + <location filename="mainwindow.cpp" line="3904"/> <source>Primary Category</source> - <translation type="unfinished"></translation> + <translation>Catégorie primaire</translation> </message> <message> - <location filename="mainwindow.cpp" line="3886"/> + <location filename="mainwindow.cpp" line="3911"/> <source>Change versioning scheme</source> - <translation type="unfinished"></translation> + <translation>Changer le système de version</translation> </message> <message> - <location filename="mainwindow.cpp" line="3890"/> + <location filename="mainwindow.cpp" line="3915"/> <source>Un-ignore update</source> - <translation type="unfinished"></translation> + <translation>Ne plus ignorer les mises à jour</translation> </message> <message> - <location filename="mainwindow.cpp" line="3892"/> + <location filename="mainwindow.cpp" line="3917"/> <source>Ignore update</source> - <translation type="unfinished"></translation> + <translation>Ignorer la Mà J</translation> </message> <message> - <location filename="mainwindow.cpp" line="3897"/> + <location filename="mainwindow.cpp" line="3922"/> <source>Rename Mod...</source> - <translation type="unfinished">Renommer mod...</translation> + <translation>Renommer le Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3898"/> + <location filename="mainwindow.cpp" line="3923"/> <source>Remove Mod...</source> - <translation type="unfinished">Supprimer mod...</translation> + <translation>Supprimer le Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3899"/> + <location filename="mainwindow.cpp" line="3924"/> <source>Reinstall Mod</source> - <translation type="unfinished">Installer mod</translation> + <translation>Réinstaller le Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3902"/> + <location filename="mainwindow.cpp" line="3927"/> <source>Un-Endorse</source> - <translation type="unfinished"></translation> + <translation>Ne plus recommander</translation> </message> <message> - <location filename="mainwindow.cpp" line="3905"/> - <location filename="mainwindow.cpp" line="3909"/> + <location filename="mainwindow.cpp" line="3930"/> + <location filename="mainwindow.cpp" line="3934"/> <source>Endorse</source> - <translation type="unfinished"></translation> + <translation>Recommander</translation> </message> <message> - <location filename="mainwindow.cpp" line="3906"/> + <location filename="mainwindow.cpp" line="3931"/> <source>Won't endorse</source> - <translation type="unfinished"></translation> + <translation>Ne vais pas recommander</translation> </message> <message> - <location filename="mainwindow.cpp" line="3912"/> + <location filename="mainwindow.cpp" line="3937"/> <source>Endorsement state unknown</source> - <translation type="unfinished"></translation> + <translation>Statut de recommandation inconnu</translation> </message> <message> - <location filename="mainwindow.cpp" line="3919"/> + <location filename="mainwindow.cpp" line="3944"/> <source>Ignore missing data</source> - <translation type="unfinished"></translation> + <translation>Ignorer les données manquantes</translation> </message> <message> - <location filename="mainwindow.cpp" line="3922"/> + <location filename="mainwindow.cpp" line="3947"/> <source>Visit on Nexus</source> - <translation type="unfinished"></translation> + <translation>Aller à la page Nexus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3923"/> + <location filename="mainwindow.cpp" line="3948"/> <source>Open in explorer</source> - <translation type="unfinished"></translation> + <translation>Ouvrir dans l'exploreur</translation> </message> <message> - <location filename="mainwindow.cpp" line="3927"/> + <location filename="mainwindow.cpp" line="3952"/> <source>Information...</source> - <translation type="unfinished">Information...</translation> + <translation>Informations...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3934"/> - <location filename="mainwindow.cpp" line="5192"/> + <location filename="mainwindow.cpp" line="3959"/> + <location filename="mainwindow.cpp" line="5225"/> <source>Exception: </source> - <translation type="unfinished"></translation> + <translation>Exception :</translation> </message> <message> - <location filename="mainwindow.cpp" line="3936"/> - <location filename="mainwindow.cpp" line="5194"/> + <location filename="mainwindow.cpp" line="3961"/> + <location filename="mainwindow.cpp" line="5227"/> <source>Unknown exception</source> - <translation type="unfinished"></translation> + <translation>Exception Inconnue</translation> </message> <message> - <location filename="mainwindow.cpp" line="3955"/> + <location filename="mainwindow.cpp" line="3988"/> <source><All></source> - <translation type="unfinished"><Tous></translation> + <translation><Tous></translation> </message> <message> - <location filename="mainwindow.cpp" line="3957"/> + <location filename="mainwindow.cpp" line="3990"/> <source><Multiple></source> - <translation type="unfinished"></translation> + <translation><Multiple></translation> + </message> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4014"/> + <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> + <translation><numerusform>Voulez vraiment supprimer les/la sauvegarde(s) suivante %n ?<br> +<ul>%1</ul> <br>Les sauvegardes supprimées seront envoyée dans la corbeille.</numerusform><numerusform>Voulez vraiment supprimer les/la sauvegarde(s) suivante %n ?<br> +<ul>%1</ul> <br>Les sauvegardes supprimées seront envoyée dans la corbeille.</numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="5450"/> + <location filename="mainwindow.cpp" line="5483"/> <source>Please wait while LOOT is running</source> - <translation type="unfinished"></translation> + <translation>Veuillez patienter pendant que LOOT s'exécute</translation> </message> <message> - <location filename="mainwindow.cpp" line="4093"/> + <location filename="mainwindow.cpp" line="4126"/> <source>Fix Mods...</source> - <translation type="unfinished">Réparer mods...</translation> + <translation>Corriger les Mods...</translation> + </message> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4128"/> + <source>Delete %n save(s)</source> + <translation><numerusform>Supprimer %n sauvegarde(s)</numerusform><numerusform>Supprimer %n sauvegarde(s)</numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="4122"/> <location filename="mainwindow.cpp" line="4155"/> + <location filename="mainwindow.cpp" line="4188"/> <source>failed to remove %1</source> - <translation type="unfinished">Impossible de supprimer %1</translation> + <translation>Impossible d'enlever %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4139"/> - <location filename="mainwindow.cpp" line="4171"/> + <location filename="mainwindow.cpp" line="4172"/> + <location filename="mainwindow.cpp" line="4204"/> <source>failed to create %1</source> - <translation type="unfinished">impossible de créer %1</translation> + <translation>Impossible de créer %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4195"/> + <location filename="mainwindow.cpp" line="4228"/> <source>Can't change download directory while downloads are in progress!</source> - <translation type="unfinished"></translation> + <translation>Vous ne pouvez pas changer le répertoire de téléchargement pendant qu'un téléchargement est en cours !</translation> </message> <message> - <location filename="mainwindow.cpp" line="4277"/> + <location filename="mainwindow.cpp" line="4310"/> <source>Download failed</source> - <translation type="unfinished">Téléchargement commencé</translation> + <translation>Téléchargement échoué</translation> </message> <message> - <location filename="mainwindow.cpp" line="4424"/> + <location filename="mainwindow.cpp" line="4457"/> <source>failed to write to file %1</source> - <translation type="unfinished">impossible d'écrire dans le fichier %1</translation> + <translation>Échec de l'écriture sur le fichier %1 </translation> </message> <message> - <location filename="mainwindow.cpp" line="4430"/> + <location filename="mainwindow.cpp" line="4463"/> <source>%1 written</source> - <translation type="unfinished">%1 écrit</translation> + <translation>%1 écrit</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Select binary</source> - <translation type="unfinished">Choisir un programme</translation> + <translation>Sélectionner un exécutable binaire</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Binary</source> - <translation type="unfinished">Programme</translation> + <translation>Exécutable binaire</translation> </message> <message> - <location filename="mainwindow.cpp" line="4495"/> + <location filename="mainwindow.cpp" line="4528"/> <source>Enter Name</source> - <translation type="unfinished"></translation> + <translation>Entrez un nom</translation> </message> <message> - <location filename="mainwindow.cpp" line="4496"/> + <location filename="mainwindow.cpp" line="4529"/> <source>Please enter a name for the executable</source> - <translation type="unfinished">Veuillez inscrire un nom pour le nouveau profil</translation> + <translation>Veuillez entrer un nom pour l'exécutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>Not an executable</source> - <translation type="unfinished">Ajouter un programme</translation> + <translation>Pas un exécutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>This is not a recognized executable.</source> - <translation type="unfinished"></translation> + <translation>Ceci n'est pas un exécutable reconnu.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4565"/> + <location filename="mainwindow.cpp" line="4590"/> <source>Replace file?</source> - <translation type="unfinished"></translation> + <translation>Remplacer le fichier?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> + <location filename="mainwindow.cpp" line="4565"/> <source>There already is a hidden version of this file. Replace it?</source> - <translation type="unfinished"></translation> + <translation>Ceci est déjà une version cachée de ce fichier. La remplacer ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>File operation failed</source> - <translation type="unfinished"></translation> + <translation>Échec de l'opération sur les fichiers</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> - <translation type="unfinished"></translation> + <translation>Impossible de retirer "%1". Peut-être n'avez vous pas les permissions nécessaires sur le fichier. </translation> </message> <message> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4590"/> <source>There already is a visible version of this file. Replace it?</source> - <translation type="unfinished"></translation> + <translation>Il existe déjà une version visible de ce fichier. La remplacer ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4590"/> + <location filename="mainwindow.cpp" line="4623"/> <source>file not found: %1</source> - <translation type="unfinished"></translation> + <translation>fichier introuvable : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4603"/> + <location filename="mainwindow.cpp" line="4636"/> <source>failed to generate preview for %1</source> - <translation type="unfinished"></translation> + <translation>impossible de générer l'aperçu de %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry, can't preview anything. This function currently does not support extracting from bsas.</source> - <translation type="unfinished"></translation> + <translation>Désolé, impossible de générer tout aperçu. Cette fonction ne supporte actuellement pas l'extraction d'un bsa. </translation> </message> <message> - <location filename="mainwindow.cpp" line="4648"/> + <location filename="mainwindow.cpp" line="4681"/> <source>Update available</source> - <translation type="unfinished">Mise à jour disponible</translation> + <translation>Mise à jour disponible</translation> </message> <message> - <location filename="mainwindow.cpp" line="4685"/> + <location filename="mainwindow.cpp" line="4718"/> <source>Open/Execute</source> - <translation type="unfinished"></translation> + <translation>Ouvrir/Exécuter</translation> </message> <message> - <location filename="mainwindow.cpp" line="4686"/> + <location filename="mainwindow.cpp" line="4719"/> <source>Add as Executable</source> - <translation type="unfinished">Ajouter un programme</translation> + <translation>Ajouter en tant qu'Exécutable</translation> </message> <message> - <location filename="mainwindow.cpp" line="4690"/> + <location filename="mainwindow.cpp" line="4723"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation>Aperçu</translation> </message> <message> - <location filename="mainwindow.cpp" line="4696"/> + <location filename="mainwindow.cpp" line="4729"/> <source>Un-Hide</source> - <translation type="unfinished"></translation> + <translation>Montrer</translation> </message> <message> - <location filename="mainwindow.cpp" line="4698"/> + <location filename="mainwindow.cpp" line="4731"/> <source>Hide</source> - <translation type="unfinished"></translation> + <translation>Cacher</translation> </message> <message> - <location filename="mainwindow.cpp" line="4704"/> + <location filename="mainwindow.cpp" line="4737"/> <source>Write To File...</source> - <translation type="unfinished">Écriture du fichier...</translation> + <translation>Écriture du fichier...</translation> </message> <message> - <location filename="mainwindow.cpp" line="4729"/> + <location filename="mainwindow.cpp" line="4762"/> <source>Do you want to endorse Mod Organizer on %1 now?</source> - <translation type="unfinished"></translation> + <translation>Désirez vous recommander Mod Organizer sur %1 maintenant ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you!</source> - <translation type="unfinished"></translation> + <translation>Merci !</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you for your endorsement!</source> - <translation type="unfinished"></translation> + <translation>Merci de votre recommandation !</translation> </message> <message> - <location filename="mainwindow.cpp" line="4860"/> + <location filename="mainwindow.cpp" line="4893"/> <source>Request to Nexus failed: %1</source> - <translation type="unfinished"></translation> + <translation>La requête au Nexus à échouée : %1 </translation> </message> <message> - <location filename="mainwindow.cpp" line="4867"/> - <location filename="mainwindow.cpp" line="4885"/> + <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4918"/> <source>login successful</source> - <translation type="unfinished"></translation> + <translation>connexion réussie</translation> </message> <message> - <location filename="mainwindow.cpp" line="4894"/> + <location filename="mainwindow.cpp" line="4927"/> <source>login failed: %1. Trying to download anyway</source> - <translation type="unfinished"></translation> + <translation>échec de login : %1. Tentative de téléchargement malgré tout</translation> </message> <message> - <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4933"/> <source>login failed: %1</source> - <translation type="unfinished"></translation> + <translation>échec de login : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4910"/> + <location filename="mainwindow.cpp" line="4943"/> <source>login failed: %1. You need to log-in with Nexus to update MO.</source> - <translation type="unfinished"></translation> + <translation>échec de login : %1. Vous devez vous connecter au Nexus pour mettre à jour MO.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4964"/> + <location filename="mainwindow.cpp" line="5015"/> + <source>failed to read %1: %2</source> + <translation>impossible de lire %1 : %2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="4976"/> <source>Error</source> - <translation type="unfinished">Erreur</translation> + <translation>Erreur</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4976"/> <source>failed to extract %1 (errorcode %2)</source> - <translation type="unfinished"></translation> + <translation>impossible d'extraire %1 (code d'erreur %2)</translation> </message> <message> - <location filename="mainwindow.cpp" line="5038"/> + <location filename="mainwindow.cpp" line="5007"/> + <source>Extract BSA</source> + <translation>Extraire le BSA</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5026"/> + <source>This archive contains invalid hashes. Some files may be broken.</source> + <translation>Cette archive contient des données de hachages invalides. Certains fichiers peuvent être corrompus.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5071"/> <source>Extract...</source> - <translation type="unfinished"></translation> + <translation>Extraire...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5100"/> + <location filename="mainwindow.cpp" line="5133"/> <source>Edit Categories...</source> - <translation type="unfinished"></translation> + <translation>Modfier les catégories</translation> </message> <message> - <location filename="mainwindow.cpp" line="5101"/> + <location filename="mainwindow.cpp" line="5134"/> <source>Deselect filter</source> - <translation type="unfinished"></translation> + <translation>Filtre de déselection</translation> </message> <message> - <location filename="mainwindow.cpp" line="5152"/> + <location filename="mainwindow.cpp" line="5185"/> <source>Remove</source> <translation>Supprimer</translation> </message> <message> - <location filename="mainwindow.cpp" line="5163"/> + <location filename="mainwindow.cpp" line="5196"/> <source>Enable all</source> - <translation type="unfinished"></translation> + <translation>Activer tout</translation> </message> <message> - <location filename="mainwindow.cpp" line="5164"/> + <location filename="mainwindow.cpp" line="5197"/> <source>Disable all</source> - <translation type="unfinished"></translation> + <translation>Désactiver tout</translation> </message> <message> - <location filename="mainwindow.cpp" line="5183"/> + <location filename="mainwindow.cpp" line="5216"/> <source>Unlock load order</source> - <translation type="unfinished"></translation> + <translation>Déverrouiller l'ordre de chargement </translation> </message> <message> - <location filename="mainwindow.cpp" line="5186"/> + <location filename="mainwindow.cpp" line="5219"/> <source>Lock load order</source> - <translation type="unfinished"></translation> + <translation>Verrouiller l’ordre de chargement</translation> </message> <message> - <location filename="mainwindow.cpp" line="5319"/> + <location filename="mainwindow.cpp" line="5352"/> <source>depends on missing "%1"</source> - <translation type="unfinished"></translation> + <translation>dépend de "%1" manquant</translation> </message> <message> - <location filename="mainwindow.cpp" line="5323"/> + <location filename="mainwindow.cpp" line="5356"/> <source>incompatible with "%1"</source> - <translation type="unfinished"></translation> + <translation>incompatible avec "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="5343"/> + <location filename="mainwindow.cpp" line="5376"/> <source>No profile set</source> - <translation type="unfinished"></translation> + <translation>Aucun profil </translation> </message> <message> - <location filename="mainwindow.cpp" line="5540"/> + <location filename="mainwindow.cpp" line="5573"/> <source>loot failed. Exit code was: %1</source> - <translation type="unfinished"></translation> + <translation>échec de LOOT. Le code de fermeture était : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5546"/> + <location filename="mainwindow.cpp" line="5579"/> <source>failed to start loot</source> - <translation type="unfinished"></translation> + <translation>impossible de démarrer LOOT</translation> </message> <message> - <location filename="mainwindow.cpp" line="5549"/> + <location filename="mainwindow.cpp" line="5582"/> <source>failed to run loot: %1</source> - <translation type="unfinished"></translation> + <translation>impossible d'exécuter LOOT : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5552"/> + <location filename="mainwindow.cpp" line="5585"/> <source>Errors occured</source> - <translation type="unfinished"></translation> + <translation>Erreurs survenues</translation> </message> <message> - <location filename="mainwindow.cpp" line="5601"/> + <location filename="mainwindow.cpp" line="5636"/> <source>Backup of load order created</source> - <translation type="unfinished"></translation> + <translation>Backup de l'ordre de chargement créé </translation> </message> <message> - <location filename="mainwindow.cpp" line="5611"/> + <location filename="mainwindow.cpp" line="5646"/> <source>Choose backup to restore</source> - <translation type="unfinished"></translation> + <translation>Choisissez le backup à restaurer</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>No Backups</source> - <translation type="unfinished"></translation> + <translation>Aucun Backups</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>There are no backups to restore</source> - <translation type="unfinished"></translation> + <translation>Il n'y a aucun backup à restaurer</translation> </message> <message> - <location filename="mainwindow.cpp" line="5645"/> - <location filename="mainwindow.cpp" line="5666"/> + <location filename="mainwindow.cpp" line="5680"/> + <location filename="mainwindow.cpp" line="5701"/> <source>Restore failed</source> - <translation type="unfinished"></translation> + <translation>Restauration échouée</translation> </message> <message> - <location filename="mainwindow.cpp" line="5646"/> - <location filename="mainwindow.cpp" line="5667"/> + <location filename="mainwindow.cpp" line="5681"/> + <location filename="mainwindow.cpp" line="5702"/> <source>Failed to restore the backup. Errorcode: %1</source> - <translation type="unfinished"></translation> + <translation>Échec de la restauration du backup. Code d'erreur : %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5657"/> + <location filename="mainwindow.cpp" line="5692"/> <source>Backup of modlist created</source> - <translation type="unfinished"></translation> + <translation>Backup de la liste de mods créé</translation> </message> </context> <context> @@ -2870,14 +2871,69 @@ This function will guess the versioning scheme under the assumption that the ins <location filename="messagedialog.ui" line="150"/> <location filename="messagedialog.ui" line="180"/> <source>Placeholder</source> - <translation>Signet</translation> + <translation>*Substitut*</translation> </message> </context> <context> <name>ModInfo</name> <message> - <location filename="modinfo.cpp" line="106"/> - <location filename="modinfo.cpp" line="135"/> + <location filename="modinfo.cpp" line="87"/> + <source>Plugins</source> + <translation>Plugins</translation> + </message> + <message> + <location filename="modinfo.cpp" line="88"/> + <source>Textures</source> + <translation>Textures</translation> + </message> + <message> + <location filename="modinfo.cpp" line="89"/> + <source>Meshes</source> + <translation>Meshes</translation> + </message> + <message> + <location filename="modinfo.cpp" line="90"/> + <source>UI Changes</source> + <translation>Modifications de l'UI</translation> + </message> + <message> + <location filename="modinfo.cpp" line="91"/> + <source>Music</source> + <translation>Musiques</translation> + </message> + <message> + <location filename="modinfo.cpp" line="92"/> + <source>Sound Effects</source> + <translation>Sons</translation> + </message> + <message> + <location filename="modinfo.cpp" line="93"/> + <source>Scripts</source> + <translation>Scripts</translation> + </message> + <message> + <location filename="modinfo.cpp" line="94"/> + <source>SKSE Plugins</source> + <translation>Plugins SKSE</translation> + </message> + <message> + <location filename="modinfo.cpp" line="95"/> + <source>SkyProc Tools</source> + <translation>Outils SkyProc</translation> + </message> + <message> + <location filename="modinfo.cpp" line="96"/> + <source>Strings</source> + <translation>Strings</translation> + </message> + <message> + <location filename="modinfo.cpp" line="97"/> + <source>invalid content type %1</source> + <translation>type de contenu invalide %1</translation> + </message> + <message> + <location filename="modinfo.cpp" line="120"/> + <location filename="modinfo.cpp" line="149"/> <source>invalid index %1</source> <translation>index invalide %1</translation> </message> @@ -2885,9 +2941,9 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfoBackup</name> <message> - <location filename="modinfo.cpp" line="930"/> + <location filename="modinfo.cpp" line="949"/> <source>This is the backup of a mod</source> - <translation type="unfinished"></translation> + <translation>Ceci est le backup d'un mod</translation> </message> </context> <context> @@ -2926,7 +2982,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="91"/> <source>Ini Files</source> - <translation type="unfinished"></translation> + <translation>Fichiers INI</translation> </message> <message> <location filename="modinfodialog.ui" line="104"/> @@ -2941,17 +2997,17 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="114"/> <source>Ini Tweaks</source> - <translation type="unfinished"></translation> + <translation>Tweaks INI</translation> </message> <message> <location filename="modinfodialog.ui" line="130"/> <source>This is a list of ini tweaks (ini modifications that can be toggled).</source> - <translation type="unfinished"></translation> + <translation>Ceci est une liste des tweaks ini (modifications d'ini qui peuvent être activées).</translation> </message> <message> <location filename="modinfodialog.ui" line="133"/> <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> + <translation>Ceci est une liste des tweaks ini. Les tweaks ini sont des fragments de fichiers INI (usuellement petits) qui sont appliqués par dessus les paramètres existants dans skyrim.ini/skyrimprefs.ini. Chaque tweak peut être activé individuellement. Vous devriez vérifier la description du mod quand à savoir si les tweaks sont réellement optionnels. </translation> </message> <message> <location filename="modinfodialog.ui" line="169"/> @@ -2976,7 +3032,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="243"/> <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> + <translation>Ceci liste toutes les images (.jpg et .png) présentes dans le répertoire du mod, comme les screenshots et autres. Cliquez sur l'objet pour obtenir une vue plus large.</translation> </message> <message> <location filename="modinfodialog.ui" line="276"/> @@ -2995,7 +3051,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="310"/> @@ -3035,48 +3091,48 @@ Most mods do not have optional esps, so chances are good you are looking at an e <message> <location filename="modinfodialog.ui" line="395"/> <source>Conflicts</source> - <translation type="unfinished"></translation> + <translation>Conflits</translation> </message> <message> <location filename="modinfodialog.ui" line="403"/> <source>The following conflicted files are provided by this mod</source> - <translation type="unfinished"></translation> + <translation>Les fichiers conflictuels suivants sont originaire de ce mod</translation> </message> <message> <location filename="modinfodialog.ui" line="453"/> <location filename="modinfodialog.ui" line="503"/> <source>File</source> - <translation type="unfinished">Fichier</translation> + <translation>Fichier</translation> </message> <message> <location filename="modinfodialog.ui" line="458"/> <source>Overwritten Mods</source> - <translation type="unfinished"></translation> + <translation>Mods écrasés</translation> </message> <message> <location filename="modinfodialog.ui" line="468"/> <source>The following conflicted files are provided by other mods</source> - <translation type="unfinished"></translation> + <translation>Les fichiers conflictuels suivants sont originaires d'autres mods</translation> </message> <message> <location filename="modinfodialog.ui" line="508"/> <source>Providing Mod</source> - <translation type="unfinished"></translation> + <translation>Mod source</translation> </message> <message> <location filename="modinfodialog.ui" line="518"/> <source>Non-Conflicted files</source> - <translation type="unfinished"></translation> + <translation>Fichiers non conflictuels</translation> </message> <message> <location filename="modinfodialog.ui" line="538"/> <source>Categories</source> - <translation type="unfinished">Catégories</translation> + <translation>Catégories</translation> </message> <message> <location filename="modinfodialog.ui" line="561"/> <source>Primary Category</source> - <translation type="unfinished"></translation> + <translation>Catégorie primaire</translation> </message> <message> <location filename="modinfodialog.ui" line="578"/> @@ -3098,20 +3154,16 @@ Most mods do not have optional esps, so chances are good you are looking at an e <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ID de ce mod sur Nexus. Rempli automatiquement si vous téléchargez et installez un mod à partir de MO. Sinon, vous pouvez l'inscrire manuellement. Pour connaître le bon ID, trouvez le mod sur Nexus. L'URL ressemblera à ceci: <a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" text-decoration: underline; color:#0000ff;">http://www.skyrimnexus.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" color:#000000;">. Dans cet example, 1334 est l'ID que vous cherchez. En passant: Ce lien est celui de Mod Organizer sur le Nexus. Pourquoi ne pas le visiter et lui donner votre aval?</span></a></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="620"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3127,12 +3179,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="657"/> <source>Refresh</source> - <translation type="unfinished">Actualiser</translation> + <translation>Actualiser</translation> </message> <message> <location filename="modinfodialog.ui" line="660"/> <source>Refresh all information from Nexus.</source> - <translation type="unfinished"></translation> + <translation>Actualiser toutes les informations provenant du Nexus</translation> </message> <message> <location filename="modinfodialog.ui" line="674"/> @@ -3144,19 +3196,23 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></translation> </message> <message> <location filename="modinfodialog.ui" line="724"/> <source>Endorse</source> - <translation type="unfinished"></translation> + <translation>Recommander</translation> </message> <message> <location filename="modinfodialog.ui" line="738"/> <source>Notes</source> - <translation type="unfinished"></translation> + <translation>Notes</translation> </message> <message> <location filename="modinfodialog.ui" line="748"/> @@ -3173,7 +3229,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3186,7 +3242,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="787"/> <source>Previous</source> - <translation type="unfinished"></translation> + <translation>Précédant</translation> </message> <message> <location filename="modinfodialog.ui" line="794"/> @@ -3199,264 +3255,264 @@ p, li { white-space: pre-wrap; } <translation>Fermer</translation> </message> <message> - <location filename="modinfodialog.cpp" line="169"/> + <location filename="modinfodialog.cpp" line="170"/> <source>&Delete</source> <translation>Supprimer</translation> </message> <message> - <location filename="modinfodialog.cpp" line="170"/> + <location filename="modinfodialog.cpp" line="171"/> <source>&Rename</source> <translation>&Renommer</translation> </message> <message> - <location filename="modinfodialog.cpp" line="171"/> + <location filename="modinfodialog.cpp" line="172"/> <source>&Hide</source> - <translation type="unfinished"></translation> + <translation>&Cacher</translation> </message> <message> - <location filename="modinfodialog.cpp" line="172"/> + <location filename="modinfodialog.cpp" line="173"/> <source>&Unhide</source> - <translation type="unfinished"></translation> + <translation>&Ne plus cacher</translation> </message> <message> - <location filename="modinfodialog.cpp" line="173"/> + <location filename="modinfodialog.cpp" line="174"/> <source>&Open</source> <translation>&Ouvrir</translation> </message> <message> - <location filename="modinfodialog.cpp" line="174"/> + <location filename="modinfodialog.cpp" line="175"/> <source>&New Folder</source> <translation>&Nouveau dossier</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes?</source> - <translation type="unfinished">Enregistrer les changements?</translation> + <translation>Enregistrer les changements?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes to "%1"?</source> - <translation type="unfinished"></translation> + <translation>Enregistrer les changements sur "%1" ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>File Exists</source> <translation>Un fichier du même nom existe</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>A file with that name exists, please enter a new one</source> <translation>Un fichier ainsi nommé existe déjà , veuillez entrer un nouveau nom</translation> </message> <message> - <location filename="modinfodialog.cpp" line="642"/> + <location filename="modinfodialog.cpp" line="643"/> <source>failed to move file</source> <translation>impossible de déplacer le fchier</translation> </message> <message> - <location filename="modinfodialog.cpp" line="667"/> + <location filename="modinfodialog.cpp" line="668"/> <source>failed to create directory "optional"</source> - <translation>Impossible de créer le dossier "optional"</translation> + <translation>impossible de créer le dossier "optional"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="705"/> - <location filename="modinfodialog.cpp" line="1210"/> + <location filename="modinfodialog.cpp" line="706"/> + <location filename="modinfodialog.cpp" line="1211"/> <source>Info requested, please wait</source> <translation>Info demandée, veuillez patienter</translation> </message> <message> - <location filename="modinfodialog.cpp" line="759"/> + <location filename="modinfodialog.cpp" line="760"/> <source>Main</source> <translation>Principal</translation> </message> <message> - <location filename="modinfodialog.cpp" line="760"/> + <location filename="modinfodialog.cpp" line="761"/> <source>Update</source> <translation>Mise-à -jour</translation> </message> <message> - <location filename="modinfodialog.cpp" line="761"/> + <location filename="modinfodialog.cpp" line="762"/> <source>Optional</source> <translation>Optionnel</translation> </message> <message> - <location filename="modinfodialog.cpp" line="762"/> + <location filename="modinfodialog.cpp" line="763"/> <source>Old</source> <translation>Ancien</translation> </message> <message> - <location filename="modinfodialog.cpp" line="763"/> + <location filename="modinfodialog.cpp" line="764"/> <source>Misc</source> <translation>Divers</translation> </message> <message> - <location filename="modinfodialog.cpp" line="764"/> + <location filename="modinfodialog.cpp" line="765"/> <source>Unknown</source> <translation>Inconnu</translation> </message> <message> - <location filename="modinfodialog.cpp" line="775"/> + <location filename="modinfodialog.cpp" line="776"/> <source>Current Version: %1</source> <translation>Version courante: %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="779"/> + <location filename="modinfodialog.cpp" line="780"/> <source>No update available</source> <translation>Aucune mise-à -jour disponible</translation> </message> <message> - <location filename="modinfodialog.cpp" line="820"/> + <location filename="modinfodialog.cpp" line="821"/> <source>(description incomplete, please visit nexus)</source> - <translation type="unfinished"></translation> + <translation>(description incomplète, veuillez aller sur le Nexus)</translation> </message> <message> - <location filename="modinfodialog.cpp" line="835"/> + <location filename="modinfodialog.cpp" line="836"/> <source><a href="%1">Visit on Nexus</a></source> <translation><a href="%1">Visiter sur Nexus</a></translation> </message> <message> - <location filename="modinfodialog.cpp" line="914"/> + <location filename="modinfodialog.cpp" line="915"/> <source>Failed to delete %1</source> - <translation>impossible d'effacer %1</translation> + <translation>Impossible d'effacer %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="926"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Confirm</source> <translation>Confirmer</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> + <location filename="modinfodialog.cpp" line="926"/> <source>Are sure you want to delete "%1"?</source> - <translation>Voulez-vous vraiment supprimer "%1"?</translation> + <translation>Voulez-vous vraiment supprimer "%1" ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Are sure you want to delete the selected files?</source> - <translation>Voulez-vous vraiment supprimer les fichiers sélectionnés?</translation> + <translation>Voulez-vous vraiment supprimer les fichiers sélectionnés ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1004"/> - <location filename="modinfodialog.cpp" line="1010"/> + <location filename="modinfodialog.cpp" line="1005"/> + <location filename="modinfodialog.cpp" line="1011"/> <source>New Folder</source> <translation>Nouveau dossier</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1016"/> + <location filename="modinfodialog.cpp" line="1017"/> <source>Failed to create "%1"</source> <translation>Impossible de créer "%1"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1121"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>Replace file?</source> - <translation type="unfinished"></translation> + <translation>Remplacer le fichier ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> + <location filename="modinfodialog.cpp" line="1121"/> <source>There already is a hidden version of this file. Replace it?</source> - <translation type="unfinished"></translation> + <translation>Ceci est déjà une version cachée de ce fichier. La remplacer ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>File operation failed</source> - <translation type="unfinished"></translation> + <translation>Opération de fichier échouée</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> - <translation type="unfinished"></translation> + <translation>Impossible de supprimer "%1". Peut-être n'avez vous pas les permissions nécessaires sur le fichier.</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1134"/> - <location filename="modinfodialog.cpp" line="1157"/> + <location filename="modinfodialog.cpp" line="1135"/> + <location filename="modinfodialog.cpp" line="1158"/> <source>failed to rename %1 to %2</source> - <translation type="unfinished">Impossible de renommer %1 en %2</translation> + <translation>impossible de renommer %1 en %2</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>There already is a visible version of this file. Replace it?</source> - <translation type="unfinished"></translation> + <translation>Il existe déjà une version visible de ce fichier. La remplacer ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1190"/> + <location filename="modinfodialog.cpp" line="1191"/> <source>Un-Hide</source> - <translation type="unfinished"></translation> + <translation>Ne plus cacher</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1192"/> + <location filename="modinfodialog.cpp" line="1193"/> <source>Hide</source> - <translation type="unfinished"></translation> + <translation>Cacher</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Name</source> <translation>Nom</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Please enter a name</source> - <translation type="unfinished"></translation> + <translation>Veuillez entrer un nom</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1238"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>Error</source> - <translation type="unfinished">Erreur</translation> + <translation>Erreur</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> + <location filename="modinfodialog.cpp" line="1238"/> <source>Invalid name. Must be a valid file name</source> - <translation type="unfinished"></translation> + <translation>Nom invalide. Veuillez entrer un nom valide</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>A tweak by that name exists</source> - <translation type="unfinished"></translation> + <translation>Un tweak de ce nom existe déjà </translation> </message> <message> - <location filename="modinfodialog.cpp" line="1254"/> + <location filename="modinfodialog.cpp" line="1255"/> <source>Create Tweak</source> - <translation type="unfinished"></translation> + <translation>Créer un Tweak</translation> </message> </context> <context> <name>ModInfoForeign</name> <message> - <location filename="modinfo.cpp" line="1021"/> + <location filename="modinfo.cpp" line="1040"/> <source>This pseudo mod represents content managed outside MO. It isn't modified by MO.</source> - <translation type="unfinished"></translation> + <translation>Ce pseudo mod représente un contenu géré à l’extérieur de MO. Il n'est pas modifié par MO.</translation> </message> </context> <context> <name>ModInfoOverwrite</name> <message> - <location filename="modinfo.cpp" line="975"/> + <location filename="modinfo.cpp" line="994"/> <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> + <translation>Ce pseudo mod contient des fichiers provenant du répertoire Data virtualisé qui ont été modifiés (ex : par le construction kit)</translation> </message> </context> <context> <name>ModInfoRegular</name> <message> - <location filename="modinfo.cpp" line="567"/> - <location filename="modinfo.cpp" line="570"/> + <location filename="modinfo.cpp" line="586"/> + <location filename="modinfo.cpp" line="589"/> <source>failed to write %1/meta.ini: error %2</source> - <translation type="unfinished"></translation> + <translation>impossible d'écrire %1/meta.ini : erreur %2</translation> </message> <message> - <location filename="modinfo.cpp" line="843"/> + <location filename="modinfo.cpp" line="862"/> <source>%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory</source> - <translation type="unfinished">%1 ne contient ni esp/esm, ni dossier d'éléments de jeu (textures, meshes, interface, ...)</translation> + <translation>%1 ne contient ni esp/esm, ni dossier d'éléments de jeu (textures, meshes, interface, ...)</translation> </message> <message> - <location filename="modinfo.cpp" line="847"/> + <location filename="modinfo.cpp" line="866"/> <source>Categories: <br></source> - <translation type="unfinished"></translation> + <translation>Catégories : <br></translation> </message> </context> <context> @@ -3464,118 +3520,117 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="55"/> <source>Game plugins (esp/esm)</source> - <translation type="unfinished"></translation> + <translation>Elder Scrolls Plugins (esp/esm)</translation> </message> <message> <location filename="modlist.cpp" line="56"/> <source>Interface</source> - <translation type="unfinished"></translation> + <translation>Interface</translation> </message> <message> <location filename="modlist.cpp" line="57"/> <source>Meshes</source> - <translation type="unfinished"></translation> + <translation>Meshes</translation> </message> <message> <location filename="modlist.cpp" line="58"/> <source>Music</source> - <translation type="unfinished"></translation> + <translation>Music</translation> </message> <message> <location filename="modlist.cpp" line="59"/> <source>Scripts (Papyrus)</source> - <translation type="unfinished"></translation> + <translation>Scripts (Papyrus)</translation> </message> <message> <location filename="modlist.cpp" line="60"/> <source>Script Extender Plugin</source> - <translation type="unfinished"></translation> + <translation>Script Extender Plugin</translation> </message> <message> <location filename="modlist.cpp" line="61"/> <source>SkyProc Patcher</source> - <translation type="unfinished"></translation> + <translation>SkyProc Patcher</translation> </message> <message> <location filename="modlist.cpp" line="62"/> <source>Sound</source> - <translation type="unfinished"></translation> + <translation>Sound</translation> </message> <message> <location filename="modlist.cpp" line="63"/> <source>Strings</source> - <translation type="unfinished"></translation> + <translation>Strings</translation> </message> <message> <location filename="modlist.cpp" line="64"/> <source>Textures</source> - <translation type="unfinished"></translation> + <translation>Textures</translation> </message> <message> <location filename="modlist.cpp" line="117"/> <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> + <translation>Cette entrée contient des fichiers qui ont été créés à l'intérieur du répertoire Data virtualisé (ex : par le construction kit)</translation> </message> <message> <location filename="modlist.cpp" line="126"/> <source>Backup</source> - <translation type="unfinished"></translation> + <translation>Backup</translation> </message> <message> <location filename="modlist.cpp" line="127"/> <source>No valid game data</source> - <translation type="unfinished"></translation> + <translation>Aucune donnée de jeu valide</translation> </message> <message> <location filename="modlist.cpp" line="128"/> <source>Not endorsed yet</source> - <translation type="unfinished"></translation> + <translation>Pas encore recommandé</translation> </message> <message> <location filename="modlist.cpp" line="130"/> <source>Overwrites files</source> - <translation type="unfinished"></translation> + <translation>Fichiers d'Overwrite</translation> </message> <message> <location filename="modlist.cpp" line="131"/> <source>Overwritten files</source> - <translation type="unfinished"></translation> + <translation>Fichiers écrasés</translation> </message> <message> <location filename="modlist.cpp" line="132"/> <source>Overwrites & Overwritten</source> - <translation type="unfinished"></translation> + <translation>Overwrites & Overwritten</translation> </message> <message> <location filename="modlist.cpp" line="133"/> <source>Redundant</source> - <translation type="unfinished"></translation> + <translation>Redondant</translation> </message> <message> <location filename="modlist.cpp" line="208"/> <source>Non-MO</source> - <translation type="unfinished"></translation> + <translation>Non-MO</translation> </message> <message> <location filename="modlist.cpp" line="238"/> <source>invalid</source> - <translation type="unfinished"></translation> + <translation>invalide</translation> </message> <message> <location filename="modlist.cpp" line="364"/> <source>installed version: "%1", newest version: "%2"</source> - <oldsource>installed version: %1, newest version: %2</oldsource> - <translation type="unfinished"></translation> + <translation>version installée : "%1", nouvelle version : "%2"</translation> </message> <message> <location filename="modlist.cpp" line="366"/> <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 "upgrade".</source> - <translation type="unfinished"></translation> + <translation>La version la plus récente disponible sur le Nexus semble être plus ancienne que celle que vous avez installée. Ceci peut signifier que la version que vous utiliser à été retirée (ex : pour cause de bug) ou que l'auteur utilise une syntaxe de version non standardisée et que la dernière version est en fait plus récente. D'une manière ou d'une autre vous pourriez vouloir "mettre à jour". </translation> </message> <message> <location filename="modlist.cpp" line="374"/> <source>Categories: <br></source> - <translation type="unfinished"></translation> + <translation>Catégories : <br></translation> </message> <message> <location filename="modlist.cpp" line="403"/> @@ -3585,7 +3640,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="814"/> <source>drag&drop failed: %1</source> - <translation type="unfinished"></translation> + <translation>le glissé&déposé à échoué : %1</translation> </message> <message> <location filename="modlist.cpp" line="877"/> @@ -3600,12 +3655,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="934"/> <source>Flags</source> - <translation type="unfinished"></translation> + <translation>Flags</translation> </message> <message> <location filename="modlist.cpp" line="935"/> <source>Content</source> - <translation type="unfinished">Contenu</translation> + <translation>Contenu</translation> </message> <message> <location filename="modlist.cpp" line="936"/> @@ -3625,28 +3680,28 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="939"/> <source>Category</source> - <translation type="unfinished"></translation> + <translation>Catégorie</translation> </message> <message> <location filename="modlist.cpp" line="940"/> <source>Nexus ID</source> - <translation type="unfinished">IDs Nexus</translation> + <translation>ID Nexus</translation> </message> <message> <location filename="modlist.cpp" line="941"/> <source>Installation</source> - <translation type="unfinished"></translation> + <translation>Installation</translation> </message> <message> <location filename="modlist.cpp" line="942"/> <location filename="modlist.cpp" line="970"/> <source>unknown</source> - <translation type="unfinished">Inconnu</translation> + <translation>inconnu</translation> </message> <message> <location filename="modlist.cpp" line="950"/> <source>Name of your mods</source> - <translation type="unfinished"></translation> + <translation>Nom de vos mods</translation> </message> <message> <location filename="modlist.cpp" line="951"/> @@ -3661,27 +3716,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="954"/> <source>Category of the mod.</source> - <translation type="unfinished"></translation> + <translation>Catégorie du mod.</translation> </message> <message> <location filename="modlist.cpp" line="955"/> <source>Id of the mod as used on Nexus.</source> - <translation type="unfinished"></translation> + <translation>ID du mod sur le Nexus</translation> </message> <message> <location filename="modlist.cpp" line="956"/> <source>Emblemes to highlight things that might require attention.</source> - <translation type="unfinished"></translation> + <translation>Emblèmes pour mettre en évidence les choses qui pourraient devoir retenir votre attention.</translation> </message> <message> <location filename="modlist.cpp" line="957"/> <source>Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></source> - <translation type="unfinished"></translation> + <translation>Représente le contenu du mod ::<br><img src=":/MO/gui/content/plugin" width=32/>Plugins de jeu (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></translation> </message> <message> <location filename="modlist.cpp" line="969"/> <source>Time this mod was installed</source> - <translation type="unfinished"></translation> + <translation>Date à laquelle le mod a été installé</translation> </message> </context> <context> @@ -3689,12 +3744,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="motddialog.ui" line="14"/> <source>Message of the Day</source> - <translation type="unfinished"></translation> + <translation>Message du Jour</translation> </message> <message> <location filename="motddialog.ui" line="42"/> <source>OK</source> - <translation type="unfinished">OK</translation> + <translation>OK</translation> </message> </context> <context> @@ -3702,35 +3757,35 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="47"/> <source>Overwrites</source> - <translation type="unfinished"></translation> + <translation>Overwrites</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="59"/> <source>not implemented</source> - <translation type="unfinished"></translation> + <translation>non implémenté</translation> </message> </context> <context> <name>NXMAccessManager</name> <message> - <location filename="nxmaccessmanager.cpp" line="144"/> + <location filename="nxmaccessmanager.cpp" line="152"/> <source>Logging into Nexus</source> - <translation type="unfinished"></translation> + <translation>Connexion au Nexus</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="159"/> + <location filename="nxmaccessmanager.cpp" line="167"/> <source>timeout</source> - <translation type="unfinished"></translation> + <translation>session expirée</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="178"/> + <location filename="nxmaccessmanager.cpp" line="186"/> <source>Unknown error</source> - <translation type="unfinished"></translation> + <translation>Erreur inconnue</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="204"/> + <location filename="nxmaccessmanager.cpp" line="212"/> <source>Please check your password</source> - <translation type="unfinished"></translation> + <translation>Veuillez vérifier votre mot de passe</translation> </message> </context> <context> @@ -3738,17 +3793,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="nexusinterface.cpp" line="216"/> <source>Failed to guess mod id for "%1", please pick the correct one</source> - <translation type="unfinished"></translation> + <translation>Impossible de deviner l'ID de mod pour "%1", veuillez déterminer la bonne</translation> </message> <message> <location filename="nexusinterface.cpp" line="482"/> <source>empty response</source> - <translation type="unfinished"></translation> + <translation>réponse nulle</translation> </message> <message> <location filename="nexusinterface.cpp" line="511"/> <source>invalid response</source> - <translation type="unfinished"></translation> + <translation>réponse invalide</translation> </message> </context> <context> @@ -3756,184 +3811,184 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.ui" line="14"/> <source>Overwrite</source> - <translation type="unfinished"></translation> + <translation>Overwrite</translation> </message> <message> <location filename="overwriteinfodialog.ui" line="39"/> <source>You can use drag&drop to move files and directories to regular mods.</source> - <translation type="unfinished"></translation> + <translation>Vous pouvez glisser&déposer pour déplacer les fichiers et les répertoires dans les mods usuels.</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="88"/> <source>&Delete</source> - <translation type="unfinished">Supprimer</translation> + <translation>&Supprimer</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="89"/> <source>&Rename</source> - <translation type="unfinished">&Renommer</translation> + <translation>&Renommer</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="90"/> <source>&Open</source> - <translation type="unfinished">&Ouvrir</translation> + <translation>&Ouvrir</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="91"/> <source>&New Folder</source> - <translation type="unfinished">&Nouveau dossier</translation> + <translation>&Nouveau dossier</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="109"/> <source>%1 not found</source> - <translation type="unfinished">%1 introuvable</translation> + <translation>%1 introuvable</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="144"/> <source>Failed to delete "%1"</source> - <translation type="unfinished">impossible d'effacer %1</translation> + <translation>impossible d'effacer "%1"</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="155"/> <location filename="overwriteinfodialog.cpp" line="160"/> <source>Confirm</source> - <translation type="unfinished">Confirmer</translation> + <translation>Confirmer</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="155"/> <source>Are sure you want to delete "%1"?</source> - <translation type="unfinished">Voulez-vous vraiment supprimer "%1"?</translation> + <translation>Voulez-vous vraiment supprimer "%1" ?</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="160"/> <source>Are sure you want to delete the selected files?</source> - <translation type="unfinished">Voulez-vous vraiment supprimer les fichiers sélectionnés?</translation> + <translation>Voulez-vous vraiment supprimer les fichiers sélectionnés ?</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="210"/> <location filename="overwriteinfodialog.cpp" line="216"/> <source>New Folder</source> - <translation type="unfinished">Nouveau dossier</translation> + <translation>Nouveau dossier</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="222"/> <source>Failed to create "%1"</source> - <translation type="unfinished">Impossible de créer "%1"</translation> + <translation>Impossible de créer "%1"</translation> </message> </context> <context> <name>PluginList</name> <message> - <location filename="pluginlist.cpp" line="103"/> + <location filename="pluginlist.cpp" line="104"/> <source>Name</source> <translation>Nom</translation> </message> <message> - <location filename="pluginlist.cpp" line="104"/> + <location filename="pluginlist.cpp" line="105"/> <source>Priority</source> <translation>Priorité</translation> </message> <message> - <location filename="pluginlist.cpp" line="105"/> + <location filename="pluginlist.cpp" line="106"/> <source>Mod Index</source> - <translation type="unfinished"></translation> + <translation>Index du mod</translation> </message> <message> - <location filename="pluginlist.cpp" line="106"/> + <location filename="pluginlist.cpp" line="107"/> <source>Flags</source> - <translation type="unfinished"></translation> + <translation>Flags</translation> </message> <message> - <location filename="pluginlist.cpp" line="107"/> - <location filename="pluginlist.cpp" line="119"/> + <location filename="pluginlist.cpp" line="108"/> + <location filename="pluginlist.cpp" line="120"/> <source>unknown</source> - <translation type="unfinished">Inconnu</translation> + <translation>inconnu</translation> </message> <message> - <location filename="pluginlist.cpp" line="115"/> + <location filename="pluginlist.cpp" line="116"/> <source>Name of your mods</source> - <translation type="unfinished"></translation> + <translation>Nom de vos mods</translation> </message> <message> - <location filename="pluginlist.cpp" line="116"/> + <location filename="pluginlist.cpp" line="117"/> <source>Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority.</source> - <translation type="unfinished"></translation> + <translation>Priorité de chargement de votre mod. Plus elle est élevée, plus le mod est "important" et écrasera donc les fichiers des mods de priorité inférieure.</translation> </message> <message> - <location filename="pluginlist.cpp" line="118"/> + <location filename="pluginlist.cpp" line="119"/> <source>The modindex determins the formids of objects originating from this mods.</source> - <translation type="unfinished"></translation> + <translation>L'index des mods détermine les "formids" des objets provenant de ces mods.</translation> </message> <message> - <location filename="pluginlist.cpp" line="159"/> + <location filename="pluginlist.cpp" line="160"/> <source>failed to update esp info for file %1 (source id: %2), error: %3</source> - <translation type="unfinished"></translation> + <translation>impossible de mettre à jour les informations d'esp pour le fichier %1 (source ID : %2), erreur : %3</translation> </message> <message> - <location filename="pluginlist.cpp" line="227"/> + <location filename="pluginlist.cpp" line="228"/> <source>esp not found: %1</source> <translation>ESP introuvable: %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="235"/> + <location filename="pluginlist.cpp" line="247"/> <source>Confirm</source> <translation>Confirmer</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> + <location filename="pluginlist.cpp" line="235"/> <source>Really enable all plugins?</source> - <translation type="unfinished"></translation> + <translation>Voulez vous vraiment activer tout les plugins ?</translation> </message> <message> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="247"/> <source>Really disable all plugins?</source> - <translation type="unfinished"></translation> + <translation>Voulez vous vraiment désactiver tout les plugins ?</translation> </message> <message> - <location filename="pluginlist.cpp" line="397"/> + <location filename="pluginlist.cpp" line="398"/> <source>The file containing locked plugin indices is broken</source> - <translation type="unfinished"></translation> + <translation>Le fichier contenant l'indice des plugins verrouillés est corrompu</translation> </message> <message> - <location filename="pluginlist.cpp" line="438"/> + <location filename="pluginlist.cpp" line="439"/> <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source> - <translation type="unfinished"></translation> + <translation>Certains de vos plugins ont un nom invalide ! Ces plugions ne peuvent pas être chargés par le jeu. Veuillez vous référer à mo_interface.log pour la liste de tout les plugins affectés et les renommer.</translation> </message> <message> <location filename="pluginlist.cpp" line="806"/> - <source><b>Origin</b>: %1</source> - <translation type="unfinished"></translation> + <source>This plugin can't be disabled (enforced by the game)</source> + <translation>Ce plugin ne peut être désactivé (forcé par le jeu)</translation> </message> <message> <location filename="pluginlist.cpp" line="808"/> - <source>Author</source> - <translation type="unfinished">Auteur</translation> + <source><b>Origin</b>: %1</source> + <translation><b>Origine</b> : %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="811"/> - <source>Description</source> - <translation type="unfinished">Description</translation> + <location filename="pluginlist.cpp" line="810"/> + <source>Author</source> + <translation>Auteur</translation> </message> <message> - <location filename="pluginlist.cpp" line="804"/> - <source>This plugin can't be disabled (enforced by the game)</source> - <translation type="unfinished"></translation> + <location filename="pluginlist.cpp" line="813"/> + <source>Description</source> + <translation>Description </translation> </message> <message> - <location filename="pluginlist.cpp" line="814"/> + <location filename="pluginlist.cpp" line="816"/> <source>Missing Masters</source> - <translation type="unfinished"></translation> + <translation>Masters manquants</translation> </message> <message> - <location filename="pluginlist.cpp" line="821"/> + <location filename="pluginlist.cpp" line="823"/> <source>Enabled Masters</source> - <translation type="unfinished"></translation> + <translation>Masters activés</translation> </message> <message> - <location filename="pluginlist.cpp" line="972"/> + <location filename="pluginlist.cpp" line="974"/> <source>failed to restore load order for %1</source> - <translation type="unfinished"></translation> + <translation>La restauration de l’ordre de chargement à échouée pour %1</translation> </message> </context> <context> @@ -3941,12 +3996,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="previewdialog.ui" line="14"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation>Aperçu</translation> </message> <message> <location filename="previewdialog.ui" line="78"/> <source>Close</source> - <translation type="unfinished">Fermer</translation> + <translation>Fermer</translation> </message> </context> <context> @@ -3954,16 +4009,20 @@ p, li { white-space: pre-wrap; } <message> <location filename="problemsdialog.ui" line="14"/> <source>Problems</source> - <translation type="unfinished"></translation> + <translation>Problèmes</translation> </message> <message> <location filename="problemsdialog.ui" line="49"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></translation> </message> <message> <location filename="problemsdialog.ui" line="75"/> @@ -3974,12 +4033,12 @@ p, li { white-space: pre-wrap; } <location filename="problemsdialog.cpp" line="44"/> <location filename="problemsdialog.cpp" line="45"/> <source>Fix</source> - <translation type="unfinished"></translation> + <translation>Corriger</translation> </message> <message> <location filename="problemsdialog.cpp" line="49"/> <source>No guided fix</source> - <translation type="unfinished"></translation> + <translation>Aucune guide de correction </translation> </message> </context> <context> @@ -3987,32 +4046,32 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="59"/> <source>invalid profile name %1</source> - <translation type="unfinished"></translation> + <translation>nom du profil invalide %1</translation> </message> <message> <location filename="profile.cpp" line="63"/> <source>failed to create %1</source> - <translation type="unfinished">impossible de créer %1</translation> + <translation>impossible de créer %1</translation> </message> <message> <location filename="profile.cpp" line="184"/> <source>failed to write mod list: %1</source> - <translation type="unfinished">impossible de mettre à jour la liste de mods: %1</translation> + <translation>impossible d'écrire la liste de mod : %1</translation> </message> <message> <location filename="profile.cpp" line="195"/> <source>failed to update tweaked ini file, wrong settings may be used: %1</source> - <translation type="unfinished"></translation> + <translation>impossible de mettre à jour le fichier de tweak ini : des paramètres incorrects pourraient être utilisés : %1</translation> </message> <message> <location filename="profile.cpp" line="226"/> <source>failed to create tweaked ini: %1</source> - <translation type="unfinished"></translation> + <translation>impossible de créer le fichier de tweak ini : %1</translation> </message> <message> <location filename="profile.cpp" line="236"/> <source>"%1" is missing or inaccessible</source> - <translation type="unfinished"></translation> + <translation>"%1" est manquant ou inaccessible </translation> </message> <message> <location filename="profile.cpp" line="282"/> @@ -4026,7 +4085,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="397"/> <source>Overwrite directory couldn't be parsed</source> - <translation type="unfinished"></translation> + <translation>le répertoire Overwrite n'a pas pu être traité</translation> </message> <message> <location filename="profile.cpp" line="406"/> @@ -4041,23 +4100,23 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="624"/> <source>failed to parse ini file (%1): %2</source> - <translation type="unfinished">impossible d'analyser le profil %1: %2</translation> + <translation>impossible de traiter le fichier ini (%1) : %2</translation> </message> <message> <location filename="profile.cpp" line="648"/> <location filename="profile.cpp" line="685"/> <source>failed to modify "%1"</source> - <translation type="unfinished">impossible de trouver "%1"</translation> + <translation>impossible de modifier "%1"</translation> </message> <message> <location filename="profile.cpp" line="713"/> <source>Delete savegames?</source> - <translation type="unfinished"></translation> + <translation>Supprimer les sauvegardes ?</translation> </message> <message> <location filename="profile.cpp" line="714"/> <source>Do you want to delete local savegames? (If you select "No", the save games will show up again if you re-enable local savegames)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4065,27 +4124,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="profileinputdialog.ui" line="14"/> <source>Dialog</source> - <translation type="unfinished"></translation> + <translation>Dialogue</translation> </message> <message> <location filename="profileinputdialog.ui" line="20"/> <source>Please enter a name for the new profile</source> - <translation type="unfinished">Veuillez inscrire un nom pour le nouveau profil</translation> + <translation>Veuillez entrer un nom pour le nouveau profil</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> + <translation>Si coché, le nouveau profil utilisera les paramètres de jeu par défaut.</translation> </message> <message> <location filename="profileinputdialog.ui" line="33"/> <source>If checked, the new profile will use the default game settings instead of the "global" settings. Global settings are the settings you configure when running the game launcher directly, without MO.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profileinputdialog.ui" line="36"/> <source>Default Game Settings</source> - <translation type="unfinished"></translation> + <translation>Paramètres de jeu par défaut</translation> </message> </context> <context> @@ -4105,7 +4164,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html></source> @@ -4121,12 +4180,12 @@ p, li { white-space: pre-wrap; } <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> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="44"/> <source>Local Savegames</source> - <translation type="unfinished"></translation> + <translation>Sauvegardes locales</translation> </message> <message> <location filename="profilesdialog.ui" line="51"/> @@ -4138,7 +4197,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4147,7 +4206,7 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Les jeux Oblivion, Fallout 3 et Fallout NV contiennent un bug empêchant le fonctionnement des textures et modèles remplaceant ceux déjà existants dans le jeu.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Les jeux Oblivion, Fallout 3 et Fallout NV contiennent un bug empêchant le fonctionnement des textures et modèles remplaçant ceux déjà existants dans le jeu.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod Organizer utilise une méthode nommée &quot;BSA redirection&quot; (google est votre ami) pour circonvenir le problème une fois pour toute. Activez simplement et n'y pensez plus.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Avec Skyrim, le problème semble partiellement résolu, mais l'activation d'un mod dans le jeu dépends toujours des dates des fichiers. Il est donc encore préférable de l'activer..</span></p></body></html></translation> @@ -4197,18 +4256,18 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.ui" line="123"/> <source>Rename</source> - <translation type="unfinished">&Renommer</translation> + <translation>Renommer</translation> </message> <message> <location filename="profilesdialog.ui" line="133"/> <location filename="profilesdialog.ui" line="136"/> <source>Transfer save games to the selected profile.</source> - <translation type="unfinished"></translation> + <translation>Transférer les sauvegardes de jeu vers le profil sélectionné.</translation> </message> <message> <location filename="profilesdialog.ui" line="139"/> <source>Transfer Saves</source> - <translation type="unfinished"></translation> + <translation>Transférer les Sauvegardes</translation> </message> <message> <location filename="profilesdialog.ui" line="162"/> @@ -4239,7 +4298,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="162"/> <source>failed to copy profile: %1</source> - <translation>impossible de copier le profil: %1</translation> + <translation>impossible de copier le profil : %1</translation> </message> <message> <location filename="profilesdialog.cpp" line="165"/> @@ -4249,7 +4308,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="165"/> <source>Invalid profile name</source> - <translation type="unfinished"></translation> + <translation>Nom de profil invalide</translation> </message> <message> <location filename="profilesdialog.cpp" line="172"/> @@ -4259,27 +4318,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="172"/> <source>Are you sure you want to remove this profile (including local savegames if any)?</source> - <translation type="unfinished"></translation> + <translation>Voulez-vous vraiment supprimer ce profil (y compris ses sauvegardes locales s'il y en a) ? </translation> </message> <message> <location filename="profilesdialog.cpp" line="182"/> <source>Profile broken</source> - <translation type="unfinished"></translation> + <translation>Profil corrompu</translation> </message> <message> <location filename="profilesdialog.cpp" line="183"/> <source>This profile you're about to delete seems to be broken or the path is invalid. I'm about to delete the following folder: "%1". Proceed?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="215"/> <source>Rename Profile</source> - <translation type="unfinished"></translation> + <translation>Renommer le Profil</translation> </message> <message> <location filename="profilesdialog.cpp" line="215"/> <source>New Name</source> - <translation type="unfinished"></translation> + <translation>Nouveau Nom</translation> </message> <message> <location filename="profilesdialog.cpp" line="252"/> @@ -4310,52 +4369,52 @@ p, li { white-space: pre-wrap; } <message> <location filename="categories.cpp" line="284"/> <source>invalid category id %1</source> - <translation type="unfinished"></translation> + <translation>ID de catégorie invalide %1</translation> </message> <message> <location filename="csvbuilder.cpp" line="70"/> <source>invalid field name "%1"</source> - <translation type="unfinished"></translation> + <translation>nom de champ invalide "%1"</translation> </message> <message> <location filename="csvbuilder.cpp" line="76"/> <source>invalid type for "%1" (should be integer)</source> - <translation type="unfinished"></translation> + <translation>type invalide pour "%1" (devrait être entier)</translation> </message> <message> <location filename="csvbuilder.cpp" line="81"/> <source>invalid type for "%1" (should be string)</source> - <translation type="unfinished"></translation> + <translation>type invalide pour "%1" (devrait être un "string")</translation> </message> <message> <location filename="csvbuilder.cpp" line="86"/> <source>invalid type for "%1" (should be float)</source> - <translation type="unfinished"></translation> + <translation>type invalide pour "%1" (devrait être "flottant")</translation> </message> <message> <location filename="csvbuilder.cpp" line="103"/> <source>no fields set up yet!</source> - <translation type="unfinished"></translation> + <translation>encore aucun champs installé !</translation> </message> <message> <location filename="csvbuilder.cpp" line="140"/> <source>field not set "%1"</source> - <translation type="unfinished"></translation> + <translation>champ non déterminé "%1"</translation> </message> <message> <location filename="csvbuilder.cpp" line="237"/> <source>invalid character in field "%1"</source> - <translation type="unfinished"></translation> + <translation>caractère invalide dans le champ "%1"</translation> </message> <message> <location filename="csvbuilder.cpp" line="240"/> <source>empty field name</source> - <translation type="unfinished"></translation> + <translation>nom du champ vide</translation> </message> <message> <location filename="gameinfoimpl.cpp" line="41"/> <source>invalid game type %1</source> - <translation type="unfinished"></translation> + <translation>type de jeu invalide %1</translation> </message> <message> <location filename="helper.cpp" line="53"/> @@ -4439,62 +4498,62 @@ p, li { white-space: pre-wrap; } <translation>Impossible de mettre en place le chargement via DLL par procuration</translation> </message> <message> - <location filename="main.cpp" line="121"/> + <location filename="main.cpp" line="122"/> <source>Permissions required</source> <translation>Permissions requises</translation> </message> <message> - <location filename="main.cpp" line="122"/> + <location filename="main.cpp" line="123"/> <source>The current user account doesn't have the required access rights to run Mod Organizer. The neccessary changes can be made automatically (the MO directory will be made writable for the current user account). You will be asked to run "helper.exe" with administrative rights.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="218"/> - <location filename="main.cpp" line="256"/> + <location filename="main.cpp" line="202"/> + <location filename="main.cpp" line="241"/> <source>Woops</source> - <translation type="unfinished"></translation> + <translation>Oups</translation> </message> <message> - <location filename="main.cpp" line="219"/> + <location filename="main.cpp" line="203"/> <source>ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="257"/> + <location filename="main.cpp" line="242"/> <source>ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <location filename="settings.cpp" line="528"/> <source>Mod Organizer</source> <translation>Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <source>An instance of Mod Organizer is already running</source> <translation>Une copie du Mod Organizer tourne déjà </translation> </message> <message> - <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="397"/> <source>No game identified in "%1". The directory is required to contain the game binary and its launcher.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="403"/> - <location filename="main.cpp" line="432"/> + <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="429"/> <source>Please select the game to manage</source> <translation>Veuillez choisir le jeu à gérer</translation> </message> <message> - <location filename="main.cpp" line="458"/> + <location filename="main.cpp" line="456"/> <source>Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="547"/> + <location filename="main.cpp" line="545"/> <source>failed to start application: %1</source> - <translation type="unfinished"></translation> + <translation>impossible de démarrer l'application : %1</translation> </message> <message> <location filename="mainwindow.cpp" line="856"/> @@ -4502,28 +4561,28 @@ p, li { white-space: pre-wrap; } <translation>Veuillez utiliser l'aide dans la barre d'outil pour obtenir des instructions à propos de tous les éléments</translation> </message> <message> - <location filename="mainwindow.cpp" line="1649"/> - <location filename="mainwindow.cpp" line="4314"/> + <location filename="mainwindow.cpp" line="1659"/> + <location filename="mainwindow.cpp" line="4347"/> <source><Manage...></source> <translation><Gérer...></translation> </message> <message> - <location filename="mainwindow.cpp" line="1667"/> + <location filename="mainwindow.cpp" line="1677"/> <source>failed to parse profile %1: %2</source> <translation>impossible d'analyser le profil %1: %2</translation> </message> <message> - <location filename="pluginlist.cpp" line="352"/> + <location filename="pluginlist.cpp" line="353"/> <source>failed to find "%1"</source> <translation>impossible de trouver "%1"</translation> </message> <message> - <location filename="pluginlist.cpp" line="516"/> + <location filename="pluginlist.cpp" line="518"/> <source>failed to access %1</source> <translation>impossible d'accéder à %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="530"/> + <location filename="pluginlist.cpp" line="532"/> <source>failed to set file time %1</source> <translation>impossible de changer la date du fichier %1</translation> </message> @@ -4535,13 +4594,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="96"/> <source>"%1" is missing or inaccessible</source> - <oldsource>"%1" is missing</oldsource> - <translation type="unfinished"></translation> + <translation>"%1" est manquant ou innacessible</translation> </message> <message> <location filename="profilesdialog.cpp" line="80"/> <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> + <translation>Avant de pouvoir utiliser ModOrganizer, vous devez créer au moins un profile. ATTENTION : Lancer le jeu une fois avant de créer un profile!</translation> </message> <message> <location filename="report.cpp" line="33"/> @@ -4550,6 +4608,11 @@ p, li { white-space: pre-wrap; } <translation>Erreur</translation> </message> <message> + <location filename="safewritefile.cpp" line="33"/> + <source>failed to open temporary file</source> + <translation>impossible d'ouvrir le fichier temporaire</translation> + </message> + <message> <location filename="savegamegamebryo.cpp" line="130"/> <location filename="savegamegamebryo.cpp" line="189"/> <location filename="savegamegamebryo.cpp" line="231"/> @@ -4564,7 +4627,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settings.cpp" line="535"/> <source>Script Extender</source> - <translation>Extenseur de script</translation> + <translation>Script Extender</translation> </message> <message> <location filename="settings.cpp" line="542"/> @@ -4572,87 +4635,82 @@ p, li { white-space: pre-wrap; } <translation>DLL par procuration</translation> </message> <message> - <location filename="spawn.cpp" line="133"/> + <location filename="spawn.cpp" line="140"/> <source>failed to spawn "%1"</source> <translation>impossible de lancer "%1"</translation> </message> <message> - <location filename="spawn.cpp" line="140"/> + <location filename="spawn.cpp" line="147"/> <source>Elevation required</source> - <translation type="unfinished"></translation> + <translation>Permissions requises</translation> </message> <message> - <location filename="spawn.cpp" line="141"/> + <location filename="spawn.cpp" line="148"/> <source>This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="spawn.cpp" line="156"/> + <location filename="spawn.cpp" line="163"/> <source>failed to spawn "%1": %2</source> <translation>impossible de lancer "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="165"/> + <location filename="spawn.cpp" line="172"/> <source>"%1" doesn't exist</source> <translation>"%1" inexistant</translation> </message> <message> - <location filename="spawn.cpp" line="172"/> + <location filename="spawn.cpp" line="179"/> <source>failed to inject dll into "%1": %2</source> <translation>impossible d'injecter le DLL dans "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="190"/> + <location filename="spawn.cpp" line="197"/> <source>failed to run "%1"</source> <translation>impossible de lancer "%1"</translation> </message> - <message> - <location filename="safewritefile.cpp" line="33"/> - <source>failed to open temporary file</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> + <translation>Le Mod existe déjà </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> + <translation>Ce Mod semble déjà installé. Voulez-vous ajouter les fichiers provenants de cette archive (écrase les fichiers existants) ou voulez-vous remplacer complètement les fichiers existants (les vieux fichiers seront effacés)? Alternativement vous pouvez installer ce Mod sous un nom différend.</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="63"/> <source>Keep Backup</source> - <translation type="unfinished"></translation> + <translation>Garder une sauvegarde</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="70"/> <source>Merge</source> - <translation type="unfinished"></translation> + <translation>Fusionner</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="77"/> <source>Replace</source> - <translation type="unfinished"></translation> + <translation>Remplacer</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="84"/> <source>Rename</source> - <translation type="unfinished">&Renommer</translation> + <translation>Renommer</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="91"/> <source>Cancel</source> - <translation type="unfinished">Annuler</translation> + <translation>Annuler</translation> </message> </context> <context> @@ -4660,27 +4718,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidget.ui" line="39"/> <source>Save #</source> - <translation type="unfinished"></translation> + <translation>Enregistrer #</translation> </message> <message> <location filename="savegameinfowidget.ui" line="51"/> <source>Character</source> - <translation type="unfinished"></translation> + <translation>Personnage</translation> </message> <message> <location filename="savegameinfowidget.ui" line="63"/> <source>Level</source> - <translation type="unfinished"></translation> + <translation>Niveau</translation> </message> <message> <location filename="savegameinfowidget.ui" line="75"/> <source>Location</source> - <translation type="unfinished"></translation> + <translation>Location</translation> </message> <message> <location filename="savegameinfowidget.ui" line="87"/> <source>Date</source> - <translation type="unfinished">DATA</translation> + <translation>Date</translation> </message> </context> <context> @@ -4688,7 +4746,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidgetgamebryo.cpp" line="41"/> <source>Missing ESPs</source> - <translation type="unfinished">ESP manquant</translation> + <translation>ESPs manquants</translation> </message> </context> <context> @@ -4696,37 +4754,37 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.ui" line="14"/> <source>Dialog</source> - <translation type="unfinished"></translation> + <translation>Dialogue</translation> </message> <message> <location filename="savetextasdialog.ui" line="32"/> <source>Copy To Clipboard</source> - <translation type="unfinished"></translation> + <translation>Copier dans le presse papier</translation> </message> <message> <location filename="savetextasdialog.ui" line="39"/> <source>Save As...</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder en tant que...</translation> </message> <message> <location filename="savetextasdialog.ui" line="59"/> <source>Close</source> - <translation type="unfinished">Fermer</translation> + <translation>Fermer</translation> </message> <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Save CSV</source> - <translation type="unfinished"></translation> + <translation>Sauvegarder le CSV</translation> </message> <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Text Files</source> - <translation type="unfinished">Fichiers texte</translation> + <translation>Fichiers Textes</translation> </message> <message> <location filename="savetextasdialog.cpp" line="40"/> <source>failed to open "%1" for writing</source> - <translation type="unfinished"></translation> + <translation>impossible d'ouvrir "%1" pour écriture</translation> </message> </context> <context> @@ -4734,17 +4792,17 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selectiondialog.ui" line="14"/> <source>Select</source> - <translation type="unfinished"></translation> + <translation>Sélectionner</translation> </message> <message> <location filename="selectiondialog.ui" line="23"/> <source>Placeholder</source> - <translation type="unfinished">Signet</translation> + <translation>*Substitut*</translation> </message> <message> <location filename="selectiondialog.ui" line="77"/> <source>Cancel</source> - <translation type="unfinished">Annuler</translation> + <translation>Annuler</translation> </message> </context> <context> @@ -4790,7 +4848,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="251"/> <source>failed to move outdated files: %1. Please update manually.</source> - <translation type="unfinished"></translation> + <translation>impossible de déplacer les fichiers obsolètes : %1. Veuillez les mettre à jour manuellement.</translation> </message> <message> <location filename="selfupdater.cpp" line="269"/> @@ -4805,22 +4863,22 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="352"/> <source>Failed to parse response. Please report this as a bug and include the file mo_interface.log.</source> - <translation type="unfinished"></translation> + <translation>Échec du traitement de la réponse. Veuillez s'il vous plait reporter ceci comme un bug, en incluant le fichier mo_interface.log.</translation> </message> <message> <location filename="selfupdater.cpp" line="417"/> <source>No incremental update available for this version, the complete package needs to be downloaded (%1 kB)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="426"/> <source>no file for update found. Please update manually.</source> - <translation type="unfinished"></translation> + <translation>aucun fichier de mise à jour trouvé. Veuillez mettre à jour manuellement.</translation> </message> <message> <location filename="selfupdater.cpp" line="441"/> <source>Failed to retrieve update information: %1</source> - <translation type="unfinished"></translation> + <translation>Impossible de récupérer les informations de mise à jour : %1</translation> </message> <message> <location filename="selfupdater.cpp" line="461"/> @@ -4833,28 +4891,28 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="settings.cpp" line="115"/> <source>Failed</source> - <translation type="unfinished"></translation> + <translation>Échec </translation> </message> <message> <location filename="settings.cpp" line="116"/> <source>Sorry, failed to start the helper application</source> - <translation type="unfinished"></translation> + <translation>Désolé, impossible de démarrer l'application d'aide</translation> </message> <message> <location filename="settings.cpp" line="335"/> <location filename="settings.cpp" line="354"/> <source>attempt to store setting for unknown plugin "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="647"/> <source>Confirm</source> - <translation type="unfinished">Confirmer</translation> + <translation>Confimer</translation> </message> <message> <location filename="settings.cpp" line="647"/> <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> + <translation type="unfinished"/> </message> </context> <context> @@ -4862,7 +4920,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="settingsdialog.ui" line="14"/> <source>Settings</source> - <translation>Réglages</translation> + <translation>Paramètres</translation> </message> <message> <location filename="settingsdialog.ui" line="24"/> @@ -4884,7 +4942,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -4895,124 +4953,124 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="57"/> <source>Style</source> - <translation type="unfinished"></translation> + <translation>Style</translation> </message> <message> <location filename="settingsdialog.ui" line="64"/> <source>graphical style</source> - <translation type="unfinished"></translation> + <translation>Style graphique</translation> </message> <message> <location filename="settingsdialog.ui" line="67"/> <source>graphical style of the MO user interface</source> - <translation type="unfinished"></translation> + <translation>Style graphique de l'interface utilise de MO</translation> </message> <message> <location filename="settingsdialog.ui" line="78"/> <source>Log Level</source> - <translation type="unfinished"></translation> + <translation>Niveau de log</translation> </message> <message> <location filename="settingsdialog.ui" line="85"/> <source>Decides the amount of data printed to "ModOrganizer.log"</source> - <translation type="unfinished"></translation> + <translation>Décide de la quantité de donnée écrite dans "ModOrganizer.log"</translation> </message> <message> <location filename="settingsdialog.ui" line="88"/> <source>Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="93"/> <source>Debug</source> - <translation type="unfinished"></translation> + <translation>Débogage </translation> </message> <message> <location filename="settingsdialog.ui" line="98"/> <source>Info</source> - <translation type="unfinished"></translation> + <translation>Information</translation> </message> <message> <location filename="settingsdialog.ui" line="103"/> <source>Error</source> - <translation type="unfinished">Erreur</translation> + <translation>Erreur</translation> </message> <message> <location filename="settingsdialog.ui" line="113"/> <source>Advanced</source> - <translation type="unfinished"></translation> + <translation>Avancé</translation> </message> <message> <location filename="settingsdialog.ui" line="125"/> <location filename="settingsdialog.ui" line="128"/> <source>Directory where downloads are stored.</source> - <translation type="unfinished"></translation> + <translation>Répertoire où les Mods sont stockés</translation> </message> <message> <location filename="settingsdialog.ui" line="148"/> <source>Mod Directory</source> - <translation type="unfinished"></translation> + <translation>Répertoire de Mod</translation> </message> <message> <location filename="settingsdialog.ui" line="155"/> <source>Directory where mods are stored.</source> - <translation type="unfinished"></translation> + <translation>Répertoire où les Mods sont stockés.</translation> </message> <message> <location filename="settingsdialog.ui" line="158"/> <source>Directory where mods are stored. Please note that changing this will break all associations of profiles with mods that don't exist in the new location (with the same name).</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="172"/> <source>Download Directory</source> - <translation type="unfinished"></translation> + <translation>Répertoire de téléchargement</translation> </message> <message> <location filename="settingsdialog.ui" line="179"/> <source>Cache Directory</source> - <translation type="unfinished"></translation> + <translation>Répertoire en cache</translation> </message> <message> <location filename="settingsdialog.ui" line="199"/> <source>User interface</source> - <translation type="unfinished"></translation> + <translation>Interface utiliser</translation> </message> <message> <location filename="settingsdialog.ui" line="205"/> <source>If checked, the download interface will be more compact.</source> - <translation type="unfinished"></translation> + <translation>Si coché, l'interface des téléchargements sera plus compacte.</translation> </message> <message> <location filename="settingsdialog.ui" line="208"/> <source>Compact Download Interface</source> - <translation type="unfinished"></translation> + <translation>Interface de téléchargent compacte</translation> </message> <message> <location filename="settingsdialog.ui" line="215"/> <source>If checked, the download list will display meta information instead of file names.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="218"/> <source>Download Meta Information</source> - <translation type="unfinished"></translation> + <translation>Télécharger les Informations Meta</translation> </message> <message> <location filename="settingsdialog.ui" line="234"/> <source>Reset stored information from dialogs.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="237"/> <source>This will make all dialogs show up again where you checked the "Remember selection"-box.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="240"/> <source>Reset Dialogs</source> - <translation type="unfinished"></translation> + <translation>Réinitialiser les dialogues</translation> </message> <message> <location filename="settingsdialog.ui" line="260"/> @@ -5041,7 +5099,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5052,7 +5110,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="299"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="302"/> @@ -5072,82 +5130,82 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="347"/> <source>Disable automatic internet features</source> - <translation type="unfinished"></translation> + <translation>Désactive les fonctionnalités automatiques nécessitant une connexion internet</translation> </message> <message> <location filename="settingsdialog.ui" line="350"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="353"/> <source>Offline Mode</source> - <translation type="unfinished"></translation> + <translation>Mode hors-connection</translation> </message> <message> <location filename="settingsdialog.ui" line="360"/> <source>Use a proxy for network connections.</source> - <translation type="unfinished"></translation> + <translation>Utiliser un proxy pour les connections sur le réseau.</translation> </message> <message> <location filename="settingsdialog.ui" line="363"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="366"/> <source>Use HTTP Proxy (Uses System Settings)</source> - <translation type="unfinished"></translation> + <translation>Utiliser un Proxy HTTP (Utilise les propriétés du système)</translation> </message> <message> <location filename="settingsdialog.ui" line="375"/> <source>Associate with "Download with manager" links</source> - <translation type="unfinished"></translation> + <translation>Associer avec les liens "Download with manager"</translation> </message> <message> <location filename="settingsdialog.ui" line="404"/> <source>Known Servers (updated on download)</source> - <translation type="unfinished"></translation> + <translation>Serveurs connus (Mà J tout les téléchargements)</translation> </message> <message> <location filename="settingsdialog.ui" line="425"/> <source>Preferred Servers (Drag & Drop)</source> - <translation type="unfinished"></translation> + <translation>Serveurs préférés (Glisser & Déposer)</translation> </message> <message> <location filename="settingsdialog.ui" line="460"/> <source>Plugins</source> - <translation type="unfinished"></translation> + <translation>Plugins</translation> </message> <message> <location filename="settingsdialog.ui" line="482"/> <source>Author:</source> - <translation type="unfinished">Auteur</translation> + <translation>Auteur:</translation> </message> <message> <location filename="settingsdialog.ui" line="496"/> <source>Version:</source> - <translation type="unfinished">Version</translation> + <translation>Version:</translation> </message> <message> <location filename="settingsdialog.ui" line="510"/> <source>Description:</source> - <translation type="unfinished">Description</translation> + <translation>Description:</translation> </message> <message> <location filename="settingsdialog.ui" line="548"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation>Clé</translation> </message> <message> <location filename="settingsdialog.ui" line="553"/> <source>Value</source> - <translation type="unfinished"></translation> + <translation>Valeur</translation> </message> <message> <location filename="settingsdialog.ui" line="565"/> <source>Blacklisted Plugins (use <del> to remove):</source> - <translation type="unfinished"></translation> + <translation>Plugin black-listé (utilisez <del> pour le supprimer) :</translation> </message> <message> <location filename="settingsdialog.ui" line="576"/> @@ -5169,7 +5227,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5207,29 +5265,29 @@ p, li { white-space: pre-wrap; } There are several means to do this: *Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="678"/> <source>NMM Version</source> - <translation type="unfinished"></translation> + <translation>Version de NMM</translation> </message> <message> <location filename="settingsdialog.ui" line="698"/> <source>The Version of Nexus Mod Manager to impersonate.</source> - <translation type="unfinished"></translation> + <translation>La Version de Nexus Mod Manager à impersonnaliser. </translation> </message> <message> <location filename="settingsdialog.ui" line="701"/> <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't need an update. Therefore you can configure the version to identify as here. -Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. +On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here. +Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="723"/> @@ -5238,7 +5296,7 @@ tl;dr-version: If Nexus-features don't work, insert the current version num </message> <message> <location filename="settingsdialog.ui" line="726"/> - <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.</source> <translation>Il semble que les jeux chargent parfois des fichiers ESP ou ESM même s'ils ne sont pas activés. Je n'en connais pas encore les circonstances, mais les rapports des usagers impliquent que dans certains cas, ce comportement est indésirable. Si vous cochez ceci, les ESPs et ESMs qui ne sotn pas cochés seront invisible pour le jeu et ne pourront pas être chargés.</translation> @@ -5251,36 +5309,36 @@ Je n'en connais pas encore les circonstances, mais les rapports des usagers <message> <location filename="settingsdialog.ui" line="737"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="740"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="744"/> <source>Force-enable game files</source> - <translation type="unfinished"></translation> + <translation>Forcer l'activation des fichiers de jeu.</translation> </message> <message> <location filename="settingsdialog.ui" line="754"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="757"/> <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't be resolved correctly. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="763"/> <source>Display mods installed outside MO</source> - <translation type="unfinished"></translation> + <translation>Affichers les Mods qui n'ont pas été installer par MO</translation> </message> <message> <location filename="settingsdialog.ui" line="773"/> @@ -5298,32 +5356,32 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar <message> <location filename="settingsdialog.ui" line="805"/> <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> + <translation>Il s'agit de solutions alternatives pour des problèmes internes à Mod Organizer. Veuillez d'abord vous assurer de lire le texte d'aide avant de modifier quoi que ce soit ici.</translation> </message> <message> <location filename="settingsdialog.cpp" line="95"/> <source>Select download directory</source> - <translation type="unfinished">Sélectionnez un répertoire</translation> + <translation>Sélectionner le répertoire de téléchargement</translation> </message> <message> <location filename="settingsdialog.cpp" line="103"/> <source>Select mod directory</source> - <translation type="unfinished">Sélectionnez un répertoire</translation> + <translation>Sélectionner le répertoire de Mod</translation> </message> <message> <location filename="settingsdialog.cpp" line="111"/> <source>Select cache directory</source> - <translation type="unfinished">Sélectionnez un répertoire</translation> + <translation>Sélectionner le répertoire en cache</translation> </message> <message> <location filename="settingsdialog.cpp" line="119"/> <source>Confirm?</source> - <translation type="unfinished">Confirmer</translation> + <translation>Confirmer ?</translation> </message> <message> <location filename="settingsdialog.cpp" line="120"/> <source>This will make all dialogs show up again where you checked the "Remember selection"-box. Continue?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -5375,7 +5433,7 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar <message> <location filename="singleinstance.cpp" line="88"/> <source>failed to communicate with running instance: %1</source> - <translation type="unfinished"></translation> + <translation>Communication échouée avec l'instance active: %1</translation> </message> <message> <location filename="singleinstance.cpp" line="100"/> @@ -5388,32 +5446,32 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar <message> <location filename="syncoverwritedialog.ui" line="14"/> <source>Sync Overwrite</source> - <translation type="unfinished"></translation> + <translation>Synchroniser Overwrite</translation> </message> <message> <location filename="syncoverwritedialog.ui" line="27"/> <source>Name</source> - <translation type="unfinished">Nom</translation> + <translation>Nom</translation> </message> <message> <location filename="syncoverwritedialog.ui" line="32"/> <source>Sync To</source> - <translation type="unfinished"></translation> + <translation>Synchroniser Vers</translation> </message> <message> <location filename="syncoverwritedialog.cpp" line="95"/> <source><don't sync></source> - <translation type="unfinished"></translation> + <translation><ne pas synchroniser></translation> </message> <message> <location filename="syncoverwritedialog.cpp" line="147"/> <source>failed to remove %1</source> - <translation type="unfinished">Impossible de supprimer %1</translation> + <translation>Impossible de supprimer %1</translation> </message> <message> <location filename="syncoverwritedialog.cpp" line="149"/> <source>failed to move %1 to %2</source> - <translation type="unfinished">impossible de copier %1 vers %2</translation> + <translation>Impossible de déplacer de %1 à %1</translation> </message> </context> <context> @@ -5421,17 +5479,17 @@ Pour les autres jeux, ceci ne suffit pas à remplacer l'invalidation des ar <message> <location filename="transfersavesdialog.ui" line="14"/> <source>Transfer Savegames</source> - <translation type="unfinished"></translation> + <translation>Transférer les sauvegardes de jeux</translation> </message> <message> <location filename="transfersavesdialog.ui" line="22"/> <source>Global Characters</source> - <translation type="unfinished"></translation> + <translation>Personnages Globaux</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> + <translation>Ceci est une liste des personnages globaux.</translation> </message> <message> <location filename="transfersavesdialog.ui" line="32"/> @@ -5443,7 +5501,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="46"/> @@ -5456,47 +5514,47 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="87"/> <source>Move -></source> - <translation type="unfinished"></translation> + <translation>Déplacer -></translation> </message> <message> <location filename="transfersavesdialog.ui" line="97"/> <source>Copy -></source> - <translation type="unfinished"></translation> + <translation>Copier -></translation> </message> <message> <location filename="transfersavesdialog.ui" line="123"/> <source><- Move</source> - <translation type="unfinished"></translation> + <translation><- Déplacer</translation> </message> <message> <location filename="transfersavesdialog.ui" line="133"/> <source><- Copy</source> - <translation type="unfinished"></translation> + <translation><- Copier</translation> </message> <message> <location filename="transfersavesdialog.ui" line="156"/> <source>Done</source> - <translation type="unfinished">Terminé</translation> + <translation>Terminé</translation> </message> <message> <location filename="transfersavesdialog.ui" line="167"/> <source>Profile Characters</source> - <translation type="unfinished"></translation> + <translation>Profil des personnages</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="140"/> <source>Overwrite</source> - <translation type="unfinished"></translation> + <translation>Écraser</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="141"/> <source>Overwrite the file "%1"</source> - <translation type="unfinished"></translation> + <translation>Écraser le fichier "%1"</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="157"/> @@ -5504,23 +5562,23 @@ On Windows XP: <location filename="transfersavesdialog.cpp" line="230"/> <location filename="transfersavesdialog.cpp" line="269"/> <source>Confirm</source> - <translation type="unfinished">Confirmer</translation> + <translation>Confirmer</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="158"/> <location filename="transfersavesdialog.cpp" line="196"/> <source>Copy all save games of character "%1" to the profile?</source> - <translation type="unfinished"></translation> + <translation>Copier toutes les sauvegardes du personnage "%1" vers le profil ?</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="231"/> <source>Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="270"/> <source>Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/src/organizer_ru.ts b/src/organizer_ru.ts index 47978e40..7fc47167 100644 --- a/src/organizer_ru.ts +++ b/src/organizer_ru.ts @@ -1,6 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.0" language="ru"> +<?xml version="1.0" ?><!DOCTYPE TS><TS language="ru" version="2.0"> <context> <name>AboutDialog</name> <message> @@ -62,7 +60,7 @@ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -225,7 +223,7 @@ If there is a component called "00 Core" it is usually required. Optio <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html></source> @@ -989,7 +987,7 @@ Right now the only case I know of where this needs to be overwritten is for the <location filename="editexecutablesdialog.cpp" line="230"/> <location filename="editexecutablesdialog.cpp" line="278"/> <source>Save Changes?</source> - <translation type="unfinished">Сохранить изменениÑ?</translation> + <translation>Сохранить изменениÑ?</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="231"/> @@ -1135,7 +1133,7 @@ Right now the only case I know of where this needs to be overwritten is for the <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1156,7 +1154,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="installdialog.ui" line="148"/> <source>Cancel</source> - <translation type="unfinished">Отмена</translation> + <translation>Отмена</translation> </message> </context> <context> @@ -1179,87 +1177,87 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="164"/> <location filename="installationmanager.cpp" line="248"/> - <location filename="installationmanager.cpp" line="530"/> + <location filename="installationmanager.cpp" line="532"/> <source>Extracting files</source> <translation>Извлечение файлов</translation> </message> <message> - <location filename="installationmanager.cpp" line="439"/> + <location filename="installationmanager.cpp" line="441"/> <source>failed to create backup</source> <translation>не удалоÑÑŒ Ñоздать резервную копию</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Mod Name</source> <translation>Ð˜Ð¼Ñ Ð¼Ð¾Ð´Ð°</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> - <location filename="installationmanager.cpp" line="501"/> + <location filename="installationmanager.cpp" line="503"/> <source>Invalid name</source> <translation>ÐедопуÑтимое имÑ</translation> </message> <message> - <location filename="installationmanager.cpp" line="502"/> + <location filename="installationmanager.cpp" line="504"/> <source>The name you entered is invalid, please enter a different one.</source> <translation>Введенное вами Ð¸Ð¼Ñ Ð½ÐµÐ´Ð¾Ð¿ÑƒÑтимо, пожалуйÑта введите другое.</translation> </message> <message> - <location filename="installationmanager.cpp" line="610"/> + <location filename="installationmanager.cpp" line="612"/> <source>File format "%1" not supported</source> <translation>Формат файла "%1" не поддерживаетÑÑ</translation> </message> <message> - <location filename="installationmanager.cpp" line="743"/> + <location filename="installationmanager.cpp" line="745"/> <source>None of the available installer plugins were able to handle that archive</source> <translation>Ðе один из доÑтупных плагинов-уÑтановщиков не Ñмог проÑмотреть Ñтот архив</translation> </message> <message> - <location filename="installationmanager.cpp" line="753"/> + <location filename="installationmanager.cpp" line="755"/> <source>no error</source> <translation>ошибки отÑутÑтвуют</translation> </message> <message> - <location filename="installationmanager.cpp" line="756"/> + <location filename="installationmanager.cpp" line="758"/> <source>7z.dll not found</source> <translation>7z.dll не найден</translation> </message> <message> - <location filename="installationmanager.cpp" line="759"/> + <location filename="installationmanager.cpp" line="761"/> <source>7z.dll isn't valid</source> <translation>7z.dll поврежден</translation> </message> <message> - <location filename="installationmanager.cpp" line="762"/> + <location filename="installationmanager.cpp" line="764"/> <source>archive not found</source> <translation>архив не найден</translation> </message> <message> - <location filename="installationmanager.cpp" line="765"/> + <location filename="installationmanager.cpp" line="767"/> <source>failed to open archive</source> <translation>не удалоÑÑŒ открыть архив</translation> </message> <message> - <location filename="installationmanager.cpp" line="768"/> + <location filename="installationmanager.cpp" line="770"/> <source>unsupported archive type</source> <translation>не поддерживаемый тип архива</translation> </message> <message> - <location filename="installationmanager.cpp" line="771"/> + <location filename="installationmanager.cpp" line="773"/> <source>internal library error</source> <translation>внутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° библиотеки</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> + <location filename="installationmanager.cpp" line="776"/> <source>archive invalid</source> <translation>архив поврежден</translation> </message> <message> - <location filename="installationmanager.cpp" line="778"/> + <location filename="installationmanager.cpp" line="780"/> <source>unknown archive error</source> <translation>неизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° архива</translation> </message> @@ -1314,7 +1312,7 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="43"/> <location filename="mainwindow.ui" line="482"/> <source>Categories</source> - <translation type="unfinished">Категории</translation> + <translation>Категории</translation> </message> <message> <location filename="mainwindow.ui" line="97"/> @@ -1356,7 +1354,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1367,6 +1365,11 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Обратите внимание, что порÑдок загрузки esp одинаков Ð´Ð»Ñ Ð²Ñех профилей.</span></p></body></html></translation> </message> <message> + <location filename="mainwindow.ui" line="215"/> + <source>Open list options...</source> + <translation>Открыть ÑпиÑок вариантов...</translation> + </message> + <message> <location filename="mainwindow.ui" line="218"/> <source>Refresh list. This is usually not necessary unless you modified data outside the program.</source> <translation>Обновить ÑпиÑок. Обычно в Ñтом нет необходимоÑти, пока вы не измените данные вне программы.</translation> @@ -1425,7 +1428,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1445,7 +1448,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1468,7 +1471,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1487,6 +1490,11 @@ p, li { white-space: pre-wrap; } <translation>Плагины</translation> </message> <message> + <location filename="mainwindow.ui" line="715"/> + <source>Sort</source> + <translation>Сортировать</translation> + </message> + <message> <location filename="mainwindow.ui" line="821"/> <source>List of available esp/esm files</source> <translation>СпиÑок доÑтупных esp/esm файлов</translation> @@ -1496,7 +1504,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1505,16 +1513,6 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Ðтот ÑпиÑок Ñодержит esp и esm файлы активных модов. Ð”Ð»Ñ Ð½Ð¸Ñ… требуетÑÑ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ñ‹Ð¹ порÑдок загрузки. ИÑпользуйте перетаÑкивание Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñ€Ñдка загрузки. Обратите внимание, что MO Ñохранит порÑдок загрузки только Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ‹Ð¼Ð¸/проверенных модов.<br />СущеÑтвует Ð·Ð°Ð¼ÐµÑ‡Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÑƒÑ‚Ð¸Ð»Ð¸Ñ‚Ð°, называющаÑÑÑ &quot;BOSS&quot; , ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки Ñортирует Ñти файлы.</span></p></body></html></translation> </message> <message> - <location filename="mainwindow.ui" line="715"/> - <source>Sort</source> - <translation>Сортировать</translation> - </message> - <message> - <location filename="mainwindow.ui" line="215"/> - <source>Open list options...</source> - <translation>Открыть ÑпиÑок вариантов...</translation> - </message> - <message> <location filename="mainwindow.ui" line="886"/> <source>Archives</source> <translation>Ðрхивы</translation> @@ -1549,7 +1547,7 @@ BSA, отмеченные здеÑÑŒ, загружаютÑÑ Ñ‚Ð°Ðº, чтобы <location filename="mainwindow.ui" line="983"/> <location filename="mainwindow.ui" line="1042"/> <source>File</source> - <translation type="unfinished">Файл</translation> + <translation>Файл</translation> </message> <message> <location filename="mainwindow.ui" line="992"/> @@ -1568,8 +1566,8 @@ BSA, отмеченные здеÑÑŒ, загружаютÑÑ Ñ‚Ð°Ðº, чтобы </message> <message> <location filename="mainwindow.ui" line="1016"/> - <location filename="mainwindow.cpp" line="3833"/> - <location filename="mainwindow.cpp" line="4705"/> + <location filename="mainwindow.cpp" line="3858"/> + <location filename="mainwindow.cpp" line="4738"/> <source>Refresh</source> <translation>Обновить</translation> </message> @@ -1581,7 +1579,7 @@ BSA, отмеченные здеÑÑŒ, загружаютÑÑ Ñ‚Ð°Ðº, чтобы <message> <location filename="mainwindow.ui" line="1047"/> <source>Mod</source> - <translation type="unfinished">Мод</translation> + <translation>Мод</translation> </message> <message> <location filename="mainwindow.ui" line="1057"/> @@ -1604,8 +1602,8 @@ BSA, отмеченные здеÑÑŒ, загружаютÑÑ Ñ‚Ð°Ðº, чтобы <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -1749,7 +1747,7 @@ p, li { white-space: pre-wrap; } </message> <message> <location filename="mainwindow.ui" line="1412"/> - <location filename="mainwindow.cpp" line="4646"/> + <location filename="mainwindow.cpp" line="4679"/> <source>Update</source> <translation>Обновление</translation> </message> @@ -1793,7 +1791,7 @@ Right now this has very limited functionality</source> </message> <message> <location filename="mainwindow.ui" line="1460"/> - <location filename="mainwindow.cpp" line="4728"/> + <location filename="mainwindow.cpp" line="4761"/> <source>Endorse Mod Organizer</source> <translation>Одобрить Mod Organizer</translation> </message> @@ -1875,7 +1873,7 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="793"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> <location filename="mainwindow.cpp" line="794"/> @@ -1923,6 +1921,25 @@ Right now this has very limited functionality</source> <translation>Плагин "%1" не удалоÑÑŒ</translation> </message> <message> + <location filename="mainwindow.cpp" line="1098"/> + <source>Download?</source> + <translation>Загрузить?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1099"/> + <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>Загрузка началаÑÑŒ, но не была уÑтановлена Ñтраница плагина. +ЕÑли вы вÑе равно загрузите, то никакой информации (Ñ‚.е. верÑиÑ) не будет аÑÑоциировано Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¾Ð¹. +Продолжить?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1140"/> + <source>Browse Mod Page</source> + <translation>Смотреть Ñтраницу мода</translation> + </message> + <message> <location filename="mainwindow.cpp" line="1225"/> <source>failed to init plugin %1: %2</source> <translation>не удалоÑÑŒ инициализировать плагин %1: %2</translation> @@ -1955,6 +1972,11 @@ Right now this has very limited functionality</source> <translation>Ðажмите OK как только вы войдете в Steam.</translation> </message> <message> + <location filename="mainwindow.cpp" line="1337"/> + <source>Executable "%1" not found</source> + <translation>ИÑполнÑемый файл "%1" не найден</translation> + </message> + <message> <location filename="mainwindow.cpp" line="1351"/> <source>Start Steam?</source> <translation>ЗапуÑтить Steam?</translation> @@ -1965,926 +1987,887 @@ Right now this has very limited functionality</source> <translation>ТребуетÑÑ Ð·Ð°Ð¿ÑƒÑ‰ÐµÐ½Ð½Ñ‹Ð¹ Steam, Ð´Ð»Ñ ÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð¾Ð³Ð¾ запуÑка игры. Должен ли MO попытатьÑÑ Ð·Ð°Ð¿ÑƒÑтить Steam ÑейчаÑ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="1562"/> + <location filename="mainwindow.cpp" line="1572"/> <source>Also in: <br></source> <translation>Также в: <br></translation> </message> <message> - <location filename="mainwindow.cpp" line="1573"/> + <location filename="mainwindow.cpp" line="1583"/> <source>No conflict</source> <translation>Конфликтов нет</translation> </message> <message> - <location filename="mainwindow.cpp" line="1742"/> + <location filename="mainwindow.cpp" line="1752"/> <source><Edit...></source> <translation><Правка...></translation> </message> <message> - <location filename="mainwindow.cpp" line="2008"/> + <location filename="mainwindow.cpp" line="1849"/> + <source>Failed to refresh list of esps: %1</source> + <translation>Ðе удалоÑÑŒ обновить ÑпиÑок esp: %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2025"/> <source>This bsa is enabled in the ini file so it may be required!</source> <translation>Ðтот bsa подключен через ini, так что он может быть необходим!</translation> </message> <message> - <location filename="mainwindow.cpp" line="2070"/> + <location filename="mainwindow.cpp" line="2087"/> <source>Activating Network Proxy</source> <translation>Подключение Ñетевого прокÑи</translation> </message> <message> - <location filename="mainwindow.cpp" line="2310"/> - <location filename="mainwindow.cpp" line="4349"/> - <source>Installation successful</source> - <translation>УÑтановка завершена</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2321"/> - <location filename="mainwindow.cpp" line="4361"/> - <source>Configure Mod</source> - <translation>ÐаÑтройка мода</translation> + <location filename="mainwindow.cpp" line="2201"/> + <location filename="mainwindow.cpp" line="2208"/> + <source>Failed to write settings</source> + <translation>Ðе удалоÑÑŒ запиÑать наÑтройки</translation> </message> <message> - <location filename="mainwindow.cpp" line="2322"/> - <location filename="mainwindow.cpp" line="4362"/> - <source>This mod contains ini tweaks. Do you want to configure them now?</source> - <translation>Ðтот мод включает наÑтройки ini. Ð’Ñ‹ хотите наÑтроить их ÑейчаÑ?</translation> + <location filename="mainwindow.cpp" line="2202"/> + <location filename="mainwindow.cpp" line="2209"/> + <source>An error occured trying to write back MO settings: %1</source> + <translation>Ошибка при попытке запиÑать обратно наÑтройки MO: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2329"/> - <location filename="mainwindow.cpp" line="4369"/> - <source>mod "%1" not found</source> - <translation>мод "%1" не найден</translation> + <location filename="mainwindow.cpp" line="2205"/> + <source>File is write protected</source> + <translation>Файл защищён от запиÑи</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>Installation cancelled</source> - <translation>УÑтановка отменена</translation> + <location filename="mainwindow.cpp" line="2206"/> + <source>Invalid file format (probably a bug)</source> + <translation>Ðеверный формат файла (возможно баг)</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>The mod was not installed completely.</source> - <translation>Мод не был уÑтановлен полноÑтью.</translation> + <location filename="mainwindow.cpp" line="2207"/> + <source>Unknown error %1</source> + <translation>ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2237"/> + <location filename="mainwindow.cpp" line="2254"/> <source>Some plugins could not be loaded</source> <translation>Ðекоторые плагины не могут быть загружены</translation> </message> <message> - <location filename="mainwindow.cpp" line="2240"/> + <location filename="mainwindow.cpp" line="2257"/> <source>Too many esps and esms enabled</source> <translation>Подключено Ñлишком много esp и esm</translation> </message> <message> - <location filename="mainwindow.cpp" line="2243"/> - <location filename="mainwindow.cpp" line="2264"/> + <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2281"/> <source>Description missing</source> <translation>ОпиÑание отÑутÑтвует</translation> </message> <message> - <location filename="mainwindow.cpp" line="2252"/> + <location filename="mainwindow.cpp" line="2269"/> <source>The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:</source> <translation>Следующие плагины не могут быть загружены. Причина возможно в отÑутÑтвующих завиÑимоÑÑ‚ÑÑ… (таких как python) или в уÑтаревшей верÑии:</translation> </message> <message> - <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2277"/> <source>The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></source> <translation>Игра не позволÑет загрузить больше 255 активных плагинов (Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ð¾Ñ„Ð¸Ñ†Ð¸Ð°Ð»ÑŒÐ½Ñ‹Ðµ). Вам нужно отключить некоторые ненужные плагины или объединить неÑколько небольших плагинов в один. ИнÑÑ‚Ñ€ÑƒÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть найдена здеÑÑŒ: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></translation> </message> <message> - <location filename="mainwindow.cpp" line="2286"/> + <location filename="mainwindow.cpp" line="2303"/> <source>Choose Mod</source> <translation>Выберете мод</translation> </message> <message> - <location filename="mainwindow.cpp" line="2287"/> + <location filename="mainwindow.cpp" line="2304"/> <source>Mod Archive</source> <translation>Ðрхив мода</translation> </message> <message> - <location filename="mainwindow.cpp" line="2541"/> + <location filename="mainwindow.cpp" line="2327"/> + <location filename="mainwindow.cpp" line="4382"/> + <source>Installation successful</source> + <translation>УÑтановка завершена</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2338"/> + <location filename="mainwindow.cpp" line="4394"/> + <source>Configure Mod</source> + <translation>ÐаÑтройка мода</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2339"/> + <location filename="mainwindow.cpp" line="4395"/> + <source>This mod contains ini tweaks. Do you want to configure them now?</source> + <translation>Ðтот мод включает наÑтройки ini. Ð’Ñ‹ хотите наÑтроить их ÑейчаÑ?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2346"/> + <location filename="mainwindow.cpp" line="4402"/> + <source>mod "%1" not found</source> + <translation>мод "%1" не найден</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>Installation cancelled</source> + <translation>УÑтановка отменена</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>The mod was not installed completely.</source> + <translation>Мод не был уÑтановлен полноÑтью.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2558"/> <source>Start Tutorial?</source> <translation>Ðачать урок?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2542"/> + <location filename="mainwindow.cpp" line="2559"/> <source>You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue?</source> <translation>Ð’Ñ‹ ÑобираетеÑÑŒ открыть урок. По техничеÑким причинам будет невозможно закончить его доÑрочно. Продолжить?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2686"/> - <location filename="mainwindow.cpp" line="4274"/> + <location filename="mainwindow.cpp" line="2703"/> + <location filename="mainwindow.cpp" line="4307"/> <source>Download started</source> <translation>Загрузка начата</translation> </message> <message> - <location filename="mainwindow.cpp" line="2747"/> + <location filename="mainwindow.cpp" line="2764"/> <source>failed to update mod list: %1</source> <translation>не удалоÑÑŒ обновить ÑпиÑок модов: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2791"/> + <location filename="mainwindow.cpp" line="2808"/> <source>failed to spawn notepad.exe: %1</source> <translation>не удалоÑÑŒ вызвать notepad.exe: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2828"/> + <location filename="mainwindow.cpp" line="2845"/> <source>failed to open %1</source> <translation>не удалоÑÑŒ открыть %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2903"/> + <location filename="mainwindow.cpp" line="2920"/> <source>failed to change origin name: %1</source> <translation>не удалоÑÑŒ изменить оригинальное имÑ: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="1337"/> - <source>Executable "%1" not found</source> - <translation>ИÑполнÑемый файл "%1" не найден</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1839"/> - <source>Failed to refresh list of esps: %1</source> - <translation>Ðе удалоÑÑŒ обновить ÑпиÑок esp: %1</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2933"/> + <location filename="mainwindow.cpp" line="2950"/> <source>failed to move "%1" from mod "%2" to "%3": %4</source> <translation>не удалоÑÑŒ перемеÑтить "%1" из мода "%2" в "%3": %4</translation> </message> <message> - <location filename="mainwindow.cpp" line="2983"/> + <location filename="mainwindow.cpp" line="2973"/> + <source><Contains %1></source> + <translation><Содержит %1></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3006"/> <source><Checked></source> <translation><Подключен></translation> </message> <message> - <location filename="mainwindow.cpp" line="2984"/> + <location filename="mainwindow.cpp" line="3007"/> <source><Unchecked></source> <translation><Отключен></translation> </message> <message> - <location filename="mainwindow.cpp" line="2985"/> + <location filename="mainwindow.cpp" line="3008"/> <source><Update></source> <translation><Обновлен></translation> </message> <message> - <location filename="mainwindow.cpp" line="2988"/> + <location filename="mainwindow.cpp" line="3009"/> + <source><Managed by MO></source> + <translation><УправлÑетÑÑ Ð² MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3010"/> + <source><Managed outside MO></source> + <translation><УправлÑетÑÑ Ð²Ð½Ðµ MO></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3011"/> <source><No category></source> <translation><Без категории></translation> </message> <message> - <location filename="mainwindow.cpp" line="2989"/> + <location filename="mainwindow.cpp" line="3012"/> <source><Conflicted></source> <translation><Конфликтует></translation> </message> <message> - <location filename="mainwindow.cpp" line="2990"/> + <location filename="mainwindow.cpp" line="3013"/> <source><Not Endorsed></source> <translation><Ðе одобрено></translation> </message> <message> - <location filename="mainwindow.cpp" line="3026"/> + <location filename="mainwindow.cpp" line="3051"/> <source>failed to rename mod: %1</source> <translation>не удалоÑÑŒ переименовать мод: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3039"/> + <location filename="mainwindow.cpp" line="3064"/> <source>Overwrite?</source> <translation>ПерезапиÑать?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3040"/> + <location filename="mainwindow.cpp" line="3065"/> <source>This will replace the existing mod "%1". Continue?</source> <translation>Ðто заменит ÑущеÑтвующий мод "%1". Продолжить?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3043"/> + <location filename="mainwindow.cpp" line="3068"/> <source>failed to remove mod "%1"</source> <translation>не удалоÑÑŒ удалить мод "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3047"/> - <location filename="mainwindow.cpp" line="4547"/> - <location filename="mainwindow.cpp" line="4571"/> + <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="4580"/> + <location filename="mainwindow.cpp" line="4604"/> <source>failed to rename "%1" to "%2"</source> <translation>не удалоÑÑŒ переименовать "%1" в "%2"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="3097"/> <source>Multiple esps activated, please check that they don't conflict.</source> <translation>Подключено неÑколько esp, выберете из них не конфликтующие.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3121"/> - <location filename="mainwindow.cpp" line="3746"/> - <location filename="mainwindow.cpp" line="3754"/> - <location filename="mainwindow.cpp" line="3981"/> + <location filename="mainwindow.cpp" line="3146"/> + <location filename="mainwindow.cpp" line="3771"/> + <location filename="mainwindow.cpp" line="3779"/> + <location filename="mainwindow.cpp" line="4014"/> <source>Confirm</source> <translation>Подтверждение</translation> </message> <message> - <location filename="mainwindow.cpp" line="3122"/> + <location filename="mainwindow.cpp" line="3147"/> <source>Remove the following mods?<br><ul>%1</ul></source> <translation>Удалить Ñледующие моды?<br><ul>%1</ul></translation> </message> <message> - <location filename="mainwindow.cpp" line="3133"/> + <location filename="mainwindow.cpp" line="3158"/> <source>failed to remove mod: %1</source> <translation>не удалоÑÑŒ удалить мод: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> - <location filename="mainwindow.cpp" line="3171"/> + <location filename="mainwindow.cpp" line="3193"/> + <location filename="mainwindow.cpp" line="3196"/> <source>Failed</source> <translation>Ðеудача</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> + <location filename="mainwindow.cpp" line="3193"/> <source>Installation file no longer exists</source> <translation>УÑтановочный файл больше не ÑущеÑтвует</translation> </message> <message> - <location filename="mainwindow.cpp" line="3172"/> + <location filename="mainwindow.cpp" line="3197"/> <source>Mods installed with old versions of MO can't be reinstalled in this way.</source> <translation>Моды, уÑтановленные Ñ Ð¸Ñпользованием Ñтарых верÑий MO не могут быть переуÑтановленны таким образом.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3203"/> - <location filename="mainwindow.cpp" line="3230"/> - <source>You need to be logged in with Nexus to endorse</source> - <translation>Ð’Ñ‹ должны быть авторизированы на Nexus, чтобы одобрÑть.</translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="3981"/> - <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="4095"/> - <source>Delete %n save(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - <numerusform></numerusform> - <numerusform></numerusform> - </translation> - </message> - <message> - <location filename="mainwindow.cpp" line="4974"/> - <source>Extract BSA</source> - <translation>РаÑпаковать BSA</translation> + <location filename="mainwindow.cpp" line="3212"/> + <source>You need to be logged in with Nexus to resume a download</source> + <translation>Ð’Ñ‹ должны быть авторизированы на Nexus, чтобы продолжить загрузку</translation> </message> <message> - <location filename="mainwindow.cpp" line="4931"/> - <location filename="mainwindow.cpp" line="4982"/> - <source>failed to read %1: %2</source> - <translation>не удалоÑÑŒ прочеÑть %1: %2</translation> + <location filename="mainwindow.cpp" line="3228"/> + <location filename="mainwindow.cpp" line="3255"/> + <source>You need to be logged in with Nexus to endorse</source> + <translation>Ð’Ñ‹ должны быть авторизированы на Nexus, чтобы одобрÑть.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4993"/> - <source>This archive contains invalid hashes. Some files may be broken.</source> - <translation>Ðрхив Ñодержит неверные хеш-Ñуммы. Ðекоторые файлы могут быть иÑпорчены.</translation> + <location filename="mainwindow.cpp" line="3289"/> + <source>Failed to display overwrite dialog: %1</source> + <translation>Ошибка при отображении диалогового окна перезапиÑи: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3382"/> + <location filename="mainwindow.cpp" line="3407"/> <source>Nexus ID for this Mod is unknown</source> <translation>Nexus ID Ð´Ð»Ñ Ñтого мода неизвеÑтен</translation> </message> <message> - <location filename="mainwindow.cpp" line="1098"/> - <source>Download?</source> - <translation>Загрузить?</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1099"/> - <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>Загрузка началаÑÑŒ, но не была уÑтановлена Ñтраница плагина. -ЕÑли вы вÑе равно загрузите, то никакой информации (Ñ‚.е. верÑиÑ) не будет аÑÑоциировано Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¾Ð¹. -Продолжить?</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1140"/> - <source>Browse Mod Page</source> - <translation>Смотреть Ñтраницу мода</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2184"/> - <location filename="mainwindow.cpp" line="2191"/> - <source>Failed to write settings</source> - <translation>Ðе удалоÑÑŒ запиÑать наÑтройки</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2185"/> - <location filename="mainwindow.cpp" line="2192"/> - <source>An error occured trying to write back MO settings: %1</source> - <translation>Ошибка при попытке запиÑать обратно наÑтройки MO: %1</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2188"/> - <source>File is write protected</source> - <translation>Файл защищён от запиÑи</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2189"/> - <source>Invalid file format (probably a bug)</source> - <translation>Ðеверный формат файла (возможно баг)</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2190"/> - <source>Unknown error %1</source> - <translation>ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ° %1</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2986"/> - <source><Managed by MO></source> - <translation><УправлÑетÑÑ Ð² MO></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2987"/> - <source><Managed outside MO></source> - <translation><УправлÑетÑÑ Ð²Ð½Ðµ MO></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3187"/> - <source>You need to be logged in with Nexus to resume a download</source> - <translation>Ð’Ñ‹ должны быть авторизированы на Nexus, чтобы продолжить загрузку</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3264"/> - <source>Failed to display overwrite dialog: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3421"/> - <location filename="mainwindow.cpp" line="3861"/> + <location filename="mainwindow.cpp" line="3446"/> + <location filename="mainwindow.cpp" line="3886"/> <source>Create Mod...</source> <translation>Создать мод...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3422"/> + <location filename="mainwindow.cpp" line="3447"/> <source>This will move all files from overwrite into a new, regular mod. Please enter a name:</source> <translation>Ðто перемеÑтит вÑе файлы из перезапиÑи в новый, Ñтандартный мод. ПожалуйÑта введите имÑ:</translation> </message> <message> - <location filename="mainwindow.cpp" line="3431"/> + <location filename="mainwindow.cpp" line="3456"/> <source>A mod with this name already exists</source> <translation>Мод Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует</translation> </message> <message> - <location filename="mainwindow.cpp" line="3672"/> + <location filename="mainwindow.cpp" line="3697"/> <source>Continue?</source> <translation>Продолжить?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3673"/> + <location filename="mainwindow.cpp" line="3698"/> <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>Схема ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми принимает решение, ÐºÐ°ÐºÐ°Ñ Ð²ÐµÑ€ÑÐ¸Ñ ÑчитаетÑÑ Ð½Ð¾Ð²ÐµÐµ другой. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ попробовать угадать Ñхему ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми, при уÑловии, что уÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ ÑвлÑетÑÑ ÑƒÑтаревшей.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3693"/> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="3718"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry</source> <translation>Извините</translation> </message> <message> - <location filename="mainwindow.cpp" line="3694"/> + <location filename="mainwindow.cpp" line="3719"/> <source>I don't know a versioning scheme where %1 is newer than %2.</source> <translation>Мне неизвеÑтна Ñхема ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми, где %1 новее %2.</translation> </message> <message> - <location filename="mainwindow.cpp" line="3746"/> + <location filename="mainwindow.cpp" line="3771"/> <source>Really enable all visible mods?</source> <translation>ДейÑтвительно подключить вÑе видимые моды?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3754"/> + <location filename="mainwindow.cpp" line="3779"/> <source>Really disable all visible mods?</source> <translation>ДейÑтвительно отключить вÑе видимые моды?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3762"/> + <location filename="mainwindow.cpp" line="3787"/> <source>Choose what to export</source> <translation>Выберете, что ÑкÑпортировать</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>Everything</source> <translation>Ð’ÑÑ‘</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>All installed mods are included in the list</source> <translation>Ð’Ñе уÑтановленные моды, включенные в ÑпиÑок</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Active Mods</source> <translation>Ðктивные моды</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Only active (checked) mods from your current profile are included</source> <translation>Включены вÑе активные (подключенные) моды вашего текущего профилÑ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>Visible</source> <translation>Видимые</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>All mods visible in the mod list are included</source> <translation>Включены вÑе моды, видимые в ÑпиÑке модов</translation> </message> <message> - <location filename="mainwindow.cpp" line="3809"/> + <location filename="mainwindow.cpp" line="3834"/> <source>export failed: %1</source> <translation>ÑкÑпорт не удалÑÑ: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3826"/> + <location filename="mainwindow.cpp" line="3851"/> <source>Install Mod...</source> <translation>УÑтановить мод...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3828"/> + <location filename="mainwindow.cpp" line="3853"/> <source>Enable all visible</source> <translation>Включить вÑе видимые</translation> </message> <message> - <location filename="mainwindow.cpp" line="3829"/> + <location filename="mainwindow.cpp" line="3854"/> <source>Disable all visible</source> <translation>Отключить вÑе видимые</translation> </message> <message> - <location filename="mainwindow.cpp" line="3831"/> + <location filename="mainwindow.cpp" line="3856"/> <source>Check all for update</source> <translation>Проверить вÑе на обновлениÑ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3835"/> + <location filename="mainwindow.cpp" line="3860"/> <source>Export to csv...</source> <translation>ÐкÑпорт в csv...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3854"/> + <location filename="mainwindow.cpp" line="3879"/> <source>All Mods</source> <translation>Ð’Ñе моды</translation> </message> <message> - <location filename="mainwindow.cpp" line="3860"/> + <location filename="mainwindow.cpp" line="3885"/> <source>Sync to Mods...</source> <translation>Синхронизировать Ñ Ð¼Ð¾Ð´Ð°Ð¼Ð¸...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3864"/> + <location filename="mainwindow.cpp" line="3889"/> <source>Restore Backup</source> <translation>ВоÑÑтановить из резервной копии</translation> </message> <message> - <location filename="mainwindow.cpp" line="3865"/> + <location filename="mainwindow.cpp" line="3890"/> <source>Remove Backup...</source> <translation>Удалить резервную копию...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3869"/> + <location filename="mainwindow.cpp" line="3894"/> <source>Add/Remove Categories</source> <translation>Добавить/Удалить категории</translation> </message> <message> - <location filename="mainwindow.cpp" line="3874"/> + <location filename="mainwindow.cpp" line="3899"/> <source>Replace Categories</source> <translation>Заменить категории</translation> </message> <message> - <location filename="mainwindow.cpp" line="3879"/> + <location filename="mainwindow.cpp" line="3904"/> <source>Primary Category</source> <translation>ОÑÐ½Ð¾Ð²Ð½Ð°Ñ ÐºÐ°Ñ‚ÐµÐ³Ð¾Ñ€Ð¸Ñ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3886"/> + <location filename="mainwindow.cpp" line="3911"/> <source>Change versioning scheme</source> <translation>Изменить Ñхему ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€ÑиÑми</translation> </message> <message> - <location filename="mainwindow.cpp" line="3890"/> + <location filename="mainwindow.cpp" line="3915"/> <source>Un-ignore update</source> <translation>СнÑть игнорирование обновлениÑ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3892"/> + <location filename="mainwindow.cpp" line="3917"/> <source>Ignore update</source> <translation>Игнорировать обновление</translation> </message> <message> - <location filename="mainwindow.cpp" line="3897"/> + <location filename="mainwindow.cpp" line="3922"/> <source>Rename Mod...</source> <translation>Переименовать мод...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3898"/> + <location filename="mainwindow.cpp" line="3923"/> <source>Remove Mod...</source> <translation>Удалить мод...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3899"/> + <location filename="mainwindow.cpp" line="3924"/> <source>Reinstall Mod</source> <translation>ПереуÑтановить мод</translation> </message> <message> - <location filename="mainwindow.cpp" line="3902"/> + <location filename="mainwindow.cpp" line="3927"/> <source>Un-Endorse</source> <translation>Отменить одобрение</translation> </message> <message> - <location filename="mainwindow.cpp" line="3905"/> - <location filename="mainwindow.cpp" line="3909"/> + <location filename="mainwindow.cpp" line="3930"/> + <location filename="mainwindow.cpp" line="3934"/> <source>Endorse</source> <translation>Одобрить</translation> </message> <message> - <location filename="mainwindow.cpp" line="3906"/> + <location filename="mainwindow.cpp" line="3931"/> <source>Won't endorse</source> <translation>Ðе одобрÑть</translation> </message> <message> - <location filename="mainwindow.cpp" line="3912"/> + <location filename="mainwindow.cpp" line="3937"/> <source>Endorsement state unknown</source> <translation>Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¾Ð´Ð¾Ð±Ñ€ÐµÐ½Ð¸Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑтен</translation> </message> <message> - <location filename="mainwindow.cpp" line="3919"/> + <location filename="mainwindow.cpp" line="3944"/> <source>Ignore missing data</source> <translation>Игнорировать отÑутÑтвующие данные</translation> </message> <message> - <location filename="mainwindow.cpp" line="3922"/> + <location filename="mainwindow.cpp" line="3947"/> <source>Visit on Nexus</source> <translation>Перейти на Nexus</translation> </message> <message> - <location filename="mainwindow.cpp" line="3923"/> + <location filename="mainwindow.cpp" line="3948"/> <source>Open in explorer</source> <translation>Открыть в проводнике</translation> </message> <message> - <location filename="mainwindow.cpp" line="3927"/> + <location filename="mainwindow.cpp" line="3952"/> <source>Information...</source> <translation>ИнформациÑ...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3934"/> - <location filename="mainwindow.cpp" line="5192"/> + <location filename="mainwindow.cpp" line="3959"/> + <location filename="mainwindow.cpp" line="5225"/> <source>Exception: </source> <translation>ИÑключение: </translation> </message> <message> - <location filename="mainwindow.cpp" line="3936"/> - <location filename="mainwindow.cpp" line="5194"/> + <location filename="mainwindow.cpp" line="3961"/> + <location filename="mainwindow.cpp" line="5227"/> <source>Unknown exception</source> <translation>ÐеизвеÑтное иÑключение</translation> </message> <message> - <location filename="mainwindow.cpp" line="3955"/> + <location filename="mainwindow.cpp" line="3988"/> <source><All></source> <translation><Ð’Ñе></translation> </message> <message> - <location filename="mainwindow.cpp" line="3957"/> + <location filename="mainwindow.cpp" line="3990"/> <source><Multiple></source> <translation><ÐеÑколько></translation> </message> - <message> - <location filename="mainwindow.cpp" line="5450"/> - <source>Please wait while LOOT is running</source> - <translation type="unfinished"></translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4014"/> + <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> + <translation><numerusform>Ð’Ñ‹ уверены, что хотите удалить Ñледующие %n ÑохранениÑ?<br><ul>%1</ul><br>Удаленные ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ помещены в Корзину.</numerusform><numerusform>Ð’Ñ‹ уверены, что хотите удалить Ñледующие %n ÑохранениÑ?<br><ul>%1</ul><br>Удаленные ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ помещены в Корзину.</numerusform><numerusform>Ð’Ñ‹ уверены, что хотите удалить Ñледующие %n ÑохранениÑ?<br><ul>%1</ul><br>Удаленные ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ помещены в Корзину.</numerusform></translation> </message> <message> - <source>Really delete "%1"?</source> - <translation type="obsolete">ДейÑтвительно удалить "%1"?</translation> + <location filename="mainwindow.cpp" line="5483"/> + <source>Please wait while LOOT is running</source> + <translation>ПожалуйÑта, подождите, пока LOOT работает</translation> </message> <message> - <location filename="mainwindow.cpp" line="4093"/> + <location filename="mainwindow.cpp" line="4126"/> <source>Fix Mods...</source> <translation>ИÑправить моды...</translation> </message> - <message> - <source>Delete</source> - <translation type="obsolete">Удалить</translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4128"/> + <source>Delete %n save(s)</source> + <translation><numerusform>Удалить Ñохранение(Ñ)</numerusform><numerusform>Удалить Ñохранение(Ñ)</numerusform><numerusform>Удалить Ñохранение(Ñ)</numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="4122"/> <location filename="mainwindow.cpp" line="4155"/> + <location filename="mainwindow.cpp" line="4188"/> <source>failed to remove %1</source> <translation>не удалоÑÑŒ удалить %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4139"/> - <location filename="mainwindow.cpp" line="4171"/> + <location filename="mainwindow.cpp" line="4172"/> + <location filename="mainwindow.cpp" line="4204"/> <source>failed to create %1</source> <translation>не удалоÑÑŒ Ñоздать %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4195"/> + <location filename="mainwindow.cpp" line="4228"/> <source>Can't change download directory while downloads are in progress!</source> <translation>ÐÐµÐ»ÑŒÐ·Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸Ñ‚ÑŒ каталог Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¾Ðº, когда загрузки ещё не завершены!</translation> </message> <message> - <location filename="mainwindow.cpp" line="4277"/> + <location filename="mainwindow.cpp" line="4310"/> <source>Download failed</source> <translation>Загрузка не удалаÑÑŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4424"/> + <location filename="mainwindow.cpp" line="4457"/> <source>failed to write to file %1</source> <translation>ошибка запиÑи в файл %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4430"/> + <location filename="mainwindow.cpp" line="4463"/> <source>%1 written</source> <translation>%1 запиÑан</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Select binary</source> <translation>Выберете иÑполнÑемый файл</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Binary</source> <translation>ИÑполнÑемый файл</translation> </message> <message> - <location filename="mainwindow.cpp" line="4495"/> + <location filename="mainwindow.cpp" line="4528"/> <source>Enter Name</source> <translation>Введите имÑ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4496"/> + <location filename="mainwindow.cpp" line="4529"/> <source>Please enter a name for the executable</source> <translation>Введите название Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>Not an executable</source> <translation>Ðе ÑвлÑетÑÑ Ð¸ÑполнÑемым</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>This is not a recognized executable.</source> <translation>Ðто неверный иÑполнÑемый файл.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4565"/> + <location filename="mainwindow.cpp" line="4590"/> <source>Replace file?</source> <translation>Заменить файл?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> + <location filename="mainwindow.cpp" line="4565"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>Уже ÑущеÑтвует ÑÐºÑ€Ñ‹Ñ‚Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñтого файла. Заменить?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>File operation failed</source> <translation>ÐžÐ¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ не удалаÑÑŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>Ðе удалоÑÑŒ удалить "%1". Может быть, вам не хватает необходимых прав доÑтупа к файлу?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4590"/> <source>There already is a visible version of this file. Replace it?</source> <translation>Ð’Ð¸Ð´Ð¸Ð¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñтого файла уже ÑущеÑтвует. Заменить?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4590"/> + <location filename="mainwindow.cpp" line="4623"/> <source>file not found: %1</source> <translation>файл не найден: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4603"/> + <location filename="mainwindow.cpp" line="4636"/> <source>failed to generate preview for %1</source> <translation>не удалоÑÑŒ получить предоÑмотр Ð´Ð»Ñ %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry, can't preview anything. This function currently does not support extracting from bsas.</source> <translation>Ðевозможно получить предоÑмотр чего-либо. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð½Ð° данный момент не поддерживает извлечение из bsa.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4648"/> + <location filename="mainwindow.cpp" line="4681"/> <source>Update available</source> <translation>ДоÑтупно обновление</translation> </message> <message> - <location filename="mainwindow.cpp" line="4685"/> + <location filename="mainwindow.cpp" line="4718"/> <source>Open/Execute</source> <translation>Открыть/Выполнить</translation> </message> <message> - <location filename="mainwindow.cpp" line="4686"/> + <location filename="mainwindow.cpp" line="4719"/> <source>Add as Executable</source> <translation>Добавить как иÑполнÑемый</translation> </message> <message> - <location filename="mainwindow.cpp" line="4690"/> + <location filename="mainwindow.cpp" line="4723"/> <source>Preview</source> <translation>ПредоÑмотр</translation> </message> <message> - <location filename="mainwindow.cpp" line="4696"/> + <location filename="mainwindow.cpp" line="4729"/> <source>Un-Hide</source> <translation>Показать</translation> </message> <message> - <location filename="mainwindow.cpp" line="4698"/> + <location filename="mainwindow.cpp" line="4731"/> <source>Hide</source> <translation>Скрыть</translation> </message> <message> - <location filename="mainwindow.cpp" line="4704"/> + <location filename="mainwindow.cpp" line="4737"/> <source>Write To File...</source> <translation>ЗапиÑать в файл...</translation> </message> <message> - <location filename="mainwindow.cpp" line="4729"/> + <location filename="mainwindow.cpp" line="4762"/> <source>Do you want to endorse Mod Organizer on %1 now?</source> <translation>Ð’Ñ‹ хотите одобрить Mod Organizer на %1 ÑейчаÑ?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you!</source> <translation>СпаÑибо Вам!</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you for your endorsement!</source> <translation>СпаÑибо Вам за одобрение!</translation> </message> <message> - <location filename="mainwindow.cpp" line="4860"/> + <location filename="mainwindow.cpp" line="4893"/> <source>Request to Nexus failed: %1</source> <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° Nexus не удалÑÑ: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4867"/> - <location filename="mainwindow.cpp" line="4885"/> + <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4918"/> <source>login successful</source> <translation>уÑпешный вход</translation> </message> <message> - <location filename="mainwindow.cpp" line="4894"/> + <location filename="mainwindow.cpp" line="4927"/> <source>login failed: %1. Trying to download anyway</source> <translation>вход не удалÑÑ: %1. ПытаюÑÑŒ загрузить вÑÑ‘ равно</translation> </message> <message> - <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4933"/> <source>login failed: %1</source> <translation>войти не удалоÑÑŒ: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4910"/> + <location filename="mainwindow.cpp" line="4943"/> <source>login failed: %1. You need to log-in with Nexus to update MO.</source> <translation>войти не удалоÑÑŒ: %1. Вам нужно войти на Nexus, чтобы обновить MO.</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4964"/> + <location filename="mainwindow.cpp" line="5015"/> + <source>failed to read %1: %2</source> + <translation>не удалоÑÑŒ прочеÑть %1: %2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="4976"/> <source>Error</source> <translation>Ошибка</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4976"/> <source>failed to extract %1 (errorcode %2)</source> <translation>не удалоÑÑŒ раÑпаковать %1 (код ошибки %2)</translation> </message> <message> - <location filename="mainwindow.cpp" line="5038"/> + <location filename="mainwindow.cpp" line="5007"/> + <source>Extract BSA</source> + <translation>РаÑпаковать BSA</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5026"/> + <source>This archive contains invalid hashes. Some files may be broken.</source> + <translation>Ðрхив Ñодержит неверные хеш-Ñуммы. Ðекоторые файлы могут быть иÑпорчены.</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5071"/> <source>Extract...</source> <translation>РаÑпаковать...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5100"/> + <location filename="mainwindow.cpp" line="5133"/> <source>Edit Categories...</source> <translation>Изменить категории...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5101"/> + <location filename="mainwindow.cpp" line="5134"/> <source>Deselect filter</source> <translation>СнÑть выбор Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°</translation> </message> <message> - <location filename="mainwindow.cpp" line="5152"/> + <location filename="mainwindow.cpp" line="5185"/> <source>Remove</source> <translation>Удалить</translation> </message> <message> - <location filename="mainwindow.cpp" line="5163"/> + <location filename="mainwindow.cpp" line="5196"/> <source>Enable all</source> <translation>Включить вÑе</translation> </message> <message> - <location filename="mainwindow.cpp" line="5164"/> + <location filename="mainwindow.cpp" line="5197"/> <source>Disable all</source> <translation>Отключить вÑе</translation> </message> <message> - <location filename="mainwindow.cpp" line="5183"/> + <location filename="mainwindow.cpp" line="5216"/> <source>Unlock load order</source> <translation>СнÑть фикÑацию порÑдка загрузки</translation> </message> <message> - <location filename="mainwindow.cpp" line="5186"/> + <location filename="mainwindow.cpp" line="5219"/> <source>Lock load order</source> <translation>ЗафикÑировать порÑдок загрузки</translation> </message> <message> - <location filename="mainwindow.cpp" line="5319"/> + <location filename="mainwindow.cpp" line="5352"/> <source>depends on missing "%1"</source> <translation>завиÑит от отÑутÑтвующего "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="5323"/> + <location filename="mainwindow.cpp" line="5356"/> <source>incompatible with "%1"</source> - <translation type="unfinished"></translation> + <translation>неÑовмеÑтимый Ñ "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="5343"/> + <location filename="mainwindow.cpp" line="5376"/> <source>No profile set</source> <translation>Ðет уÑтановленного профилÑ</translation> </message> <message> - <source>LOOT working</source> - <translation type="obsolete">LOOT работает</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="5540"/> + <location filename="mainwindow.cpp" line="5573"/> <source>loot failed. Exit code was: %1</source> <translation>ЗапуÑк LOOT не удалÑÑ. Код завершениÑ: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5546"/> + <location filename="mainwindow.cpp" line="5579"/> <source>failed to start loot</source> - <translation type="unfinished"></translation> + <translation>Ðе удалоÑÑŒ запуÑтить LOOT</translation> </message> <message> - <location filename="mainwindow.cpp" line="5549"/> + <location filename="mainwindow.cpp" line="5582"/> <source>failed to run loot: %1</source> <translation>не удалоÑÑŒ запуÑтить LOOT: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5552"/> + <location filename="mainwindow.cpp" line="5585"/> <source>Errors occured</source> <translation>Возникли ошибки</translation> </message> <message> - <location filename="mainwindow.cpp" line="5601"/> + <location filename="mainwindow.cpp" line="5636"/> <source>Backup of load order created</source> <translation>Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð¿Ð¾Ñ€Ñдка загрузки Ñоздана</translation> </message> <message> - <location filename="mainwindow.cpp" line="5611"/> + <location filename="mainwindow.cpp" line="5646"/> <source>Choose backup to restore</source> <translation>Выберите резервную копию Ð´Ð»Ñ Ð²Ð¾ÑÑтановлениÑ</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>No Backups</source> <translation>Резервных копий нет</translation> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>There are no backups to restore</source> <translation>Резервные копии Ð´Ð»Ñ Ð²Ð¾ÑÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ‚ÑутÑтвуют</translation> </message> <message> - <location filename="mainwindow.cpp" line="5645"/> - <location filename="mainwindow.cpp" line="5666"/> + <location filename="mainwindow.cpp" line="5680"/> + <location filename="mainwindow.cpp" line="5701"/> <source>Restore failed</source> <translation>ВоÑÑтановление не удалоÑÑŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="5646"/> - <location filename="mainwindow.cpp" line="5667"/> + <location filename="mainwindow.cpp" line="5681"/> + <location filename="mainwindow.cpp" line="5702"/> <source>Failed to restore the backup. Errorcode: %1</source> <translation>Ðе удалоÑÑŒ воÑÑтановить резервную копию. Код ошибки: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="5657"/> + <location filename="mainwindow.cpp" line="5692"/> <source>Backup of modlist created</source> <translation>Ð ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ ÑпиÑка модов Ñоздана</translation> </message> @@ -2901,8 +2884,63 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfo</name> <message> - <location filename="modinfo.cpp" line="106"/> - <location filename="modinfo.cpp" line="135"/> + <location filename="modinfo.cpp" line="87"/> + <source>Plugins</source> + <translation>Плагины</translation> + </message> + <message> + <location filename="modinfo.cpp" line="88"/> + <source>Textures</source> + <translation>ТекÑтуры</translation> + </message> + <message> + <location filename="modinfo.cpp" line="89"/> + <source>Meshes</source> + <translation>Полигональные Ñетки</translation> + </message> + <message> + <location filename="modinfo.cpp" line="90"/> + <source>UI Changes</source> + <translation>Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа</translation> + </message> + <message> + <location filename="modinfo.cpp" line="91"/> + <source>Music</source> + <translation>Музыка</translation> + </message> + <message> + <location filename="modinfo.cpp" line="92"/> + <source>Sound Effects</source> + <translation>Звуковые Ñффекты</translation> + </message> + <message> + <location filename="modinfo.cpp" line="93"/> + <source>Scripts</source> + <translation>Скрипты </translation> + </message> + <message> + <location filename="modinfo.cpp" line="94"/> + <source>SKSE Plugins</source> + <translation>Плагины SKSE</translation> + </message> + <message> + <location filename="modinfo.cpp" line="95"/> + <source>SkyProc Tools</source> + <translation>ИнÑтрументы SkyProc</translation> + </message> + <message> + <location filename="modinfo.cpp" line="96"/> + <source>Strings</source> + <translation>Строки</translation> + </message> + <message> + <location filename="modinfo.cpp" line="97"/> + <source>invalid content type %1</source> + <translation>Ðекорректный тип ÑÐ¾Ð´ÐµÑ€Ð¶Ð°Ð½Ð¸Ñ %1</translation> + </message> + <message> + <location filename="modinfo.cpp" line="120"/> + <location filename="modinfo.cpp" line="149"/> <source>invalid index %1</source> <translation>неверный Ð¸Ð½Ð´ÐµÐºÑ %1</translation> </message> @@ -2910,7 +2948,7 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfoBackup</name> <message> - <location filename="modinfo.cpp" line="930"/> + <location filename="modinfo.cpp" line="949"/> <source>This is the backup of a mod</source> <translation>Ðто Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ Ð¼Ð¾Ð´Ð°</translation> </message> @@ -3126,7 +3164,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3139,7 +3177,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3172,7 +3210,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3205,7 +3243,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3228,230 +3266,230 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="814"/> <source>Close</source> - <translation type="unfinished">Закрыть</translation> + <translation>Закрыть</translation> </message> <message> - <location filename="modinfodialog.cpp" line="169"/> + <location filename="modinfodialog.cpp" line="170"/> <source>&Delete</source> <translation>&Удалить</translation> </message> <message> - <location filename="modinfodialog.cpp" line="170"/> + <location filename="modinfodialog.cpp" line="171"/> <source>&Rename</source> <translation>&Переименовать</translation> </message> <message> - <location filename="modinfodialog.cpp" line="171"/> + <location filename="modinfodialog.cpp" line="172"/> <source>&Hide</source> <translation>&Скрыть</translation> </message> <message> - <location filename="modinfodialog.cpp" line="172"/> + <location filename="modinfodialog.cpp" line="173"/> <source>&Unhide</source> <translation>&Показать</translation> </message> <message> - <location filename="modinfodialog.cpp" line="173"/> + <location filename="modinfodialog.cpp" line="174"/> <source>&Open</source> - <translation type="unfinished">&Открыть</translation> + <translation>&Открыть</translation> </message> <message> - <location filename="modinfodialog.cpp" line="174"/> + <location filename="modinfodialog.cpp" line="175"/> <source>&New Folder</source> <translation>&ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes?</source> <translation>Сохранить изменениÑ?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes to "%1"?</source> <translation>Сохранить Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² "%1"?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>File Exists</source> <translation>Файл уже ÑущеÑтвует</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>A file with that name exists, please enter a new one</source> <translation>Файл Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует, укажите другое</translation> </message> <message> - <location filename="modinfodialog.cpp" line="642"/> + <location filename="modinfodialog.cpp" line="643"/> <source>failed to move file</source> <translation>не удалоÑÑŒ перемеÑтить файл</translation> </message> <message> - <location filename="modinfodialog.cpp" line="667"/> + <location filename="modinfodialog.cpp" line="668"/> <source>failed to create directory "optional"</source> <translation>не удалоÑÑŒ Ñоздать папку "optional"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="705"/> - <location filename="modinfodialog.cpp" line="1210"/> + <location filename="modinfodialog.cpp" line="706"/> + <location filename="modinfodialog.cpp" line="1211"/> <source>Info requested, please wait</source> <translation>Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð°, пожалуйÑта, подождите</translation> </message> <message> - <location filename="modinfodialog.cpp" line="759"/> + <location filename="modinfodialog.cpp" line="760"/> <source>Main</source> <translation>Главное</translation> </message> <message> - <location filename="modinfodialog.cpp" line="760"/> + <location filename="modinfodialog.cpp" line="761"/> <source>Update</source> <translation>Обновление</translation> </message> <message> - <location filename="modinfodialog.cpp" line="761"/> + <location filename="modinfodialog.cpp" line="762"/> <source>Optional</source> <translation>Опционально</translation> </message> <message> - <location filename="modinfodialog.cpp" line="762"/> + <location filename="modinfodialog.cpp" line="763"/> <source>Old</source> <translation>Старые</translation> </message> <message> - <location filename="modinfodialog.cpp" line="763"/> + <location filename="modinfodialog.cpp" line="764"/> <source>Misc</source> <translation>Разное</translation> </message> <message> - <location filename="modinfodialog.cpp" line="764"/> + <location filename="modinfodialog.cpp" line="765"/> <source>Unknown</source> <translation>ÐеизвеÑтно</translation> </message> <message> - <location filename="modinfodialog.cpp" line="775"/> + <location filename="modinfodialog.cpp" line="776"/> <source>Current Version: %1</source> <translation>Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑиÑ: %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="779"/> + <location filename="modinfodialog.cpp" line="780"/> <source>No update available</source> <translation>Ðет доÑтупных обновлений</translation> </message> <message> - <location filename="modinfodialog.cpp" line="820"/> + <location filename="modinfodialog.cpp" line="821"/> <source>(description incomplete, please visit nexus)</source> <translation>(опиÑание не завершено, Ñмотрите на nexus)</translation> </message> <message> - <location filename="modinfodialog.cpp" line="835"/> + <location filename="modinfodialog.cpp" line="836"/> <source><a href="%1">Visit on Nexus</a></source> <translation><a href="%1">Перейти на Nexus</a></translation> </message> <message> - <location filename="modinfodialog.cpp" line="914"/> + <location filename="modinfodialog.cpp" line="915"/> <source>Failed to delete %1</source> - <translation type="unfinished">Ðе удалоÑÑŒ удалить %1</translation> + <translation>Ðе удалоÑÑŒ удалить %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="926"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Confirm</source> <translation>Подтверждение</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> + <location filename="modinfodialog.cpp" line="926"/> <source>Are sure you want to delete "%1"?</source> <translation>Ð’Ñ‹ уверены, что хотите удалить "%1"?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Are sure you want to delete the selected files?</source> <translation>Ð’Ñ‹ уверены, что хотите удалить выбранные файлы?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1004"/> - <location filename="modinfodialog.cpp" line="1010"/> + <location filename="modinfodialog.cpp" line="1005"/> + <location filename="modinfodialog.cpp" line="1011"/> <source>New Folder</source> <translation>ÐÐ¾Ð²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1016"/> + <location filename="modinfodialog.cpp" line="1017"/> <source>Failed to create "%1"</source> <translation>Ðе удалоÑÑŒ Ñоздать "%1"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1121"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>Replace file?</source> <translation>Заменить файл?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> + <location filename="modinfodialog.cpp" line="1121"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>Ð¡ÐºÑ€Ñ‹Ñ‚Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñтого файла уже ÑущеÑтвует. Заменить?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>File operation failed</source> <translation>Ðе удалаÑÑŒ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ð¸Ñ Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð¼</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>Ðе удалоÑÑŒ удалить "%1". Может быть, вам не хватает необходимых прав доÑтупа к файлу?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1134"/> - <location filename="modinfodialog.cpp" line="1157"/> + <location filename="modinfodialog.cpp" line="1135"/> + <location filename="modinfodialog.cpp" line="1158"/> <source>failed to rename %1 to %2</source> <translation>не удалоÑÑŒ переименовать %1 в %2</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>There already is a visible version of this file. Replace it?</source> <translation>Ð’Ð¸Ð´Ð¸Ð¼Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ñтого файла уже ÑущеÑтвует. Заменить?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1190"/> + <location filename="modinfodialog.cpp" line="1191"/> <source>Un-Hide</source> <translation>Показать</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1192"/> + <location filename="modinfodialog.cpp" line="1193"/> <source>Hide</source> <translation>Скрыть</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Name</source> <translation>ИмÑ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Please enter a name</source> <translation>ПожалуйÑта, введите имÑ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1238"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>Error</source> <translation>Ошибка</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> + <location filename="modinfodialog.cpp" line="1238"/> <source>Invalid name. Must be a valid file name</source> <translation>Ðеверное имÑ. Ðеобходимо допуÑтимое Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°.</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>A tweak by that name exists</source> <translation>ÐаÑтройка Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем ÑущеÑтвует</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1254"/> + <location filename="modinfodialog.cpp" line="1255"/> <source>Create Tweak</source> <translation>Создать наÑтройку</translation> </message> @@ -3459,7 +3497,7 @@ p, li { white-space: pre-wrap; } <context> <name>ModInfoForeign</name> <message> - <location filename="modinfo.cpp" line="1021"/> + <location filename="modinfo.cpp" line="1040"/> <source>This pseudo mod represents content managed outside MO. It isn't modified by MO.</source> <translation>Ðтот пÑевдо-мод отображает Ñодержимое, управлÑемое из вне MO. Оно не модифицировано в MO.</translation> </message> @@ -3467,7 +3505,7 @@ p, li { white-space: pre-wrap; } <context> <name>ModInfoOverwrite</name> <message> - <location filename="modinfo.cpp" line="975"/> + <location filename="modinfo.cpp" line="994"/> <source>This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)</source> <translation>Ðтот пÑевдо-мод Ñодержит файлы из виртуального древа данных, которые были изменены (в Construction Kit и других программах)</translation> </message> @@ -3475,18 +3513,18 @@ p, li { white-space: pre-wrap; } <context> <name>ModInfoRegular</name> <message> - <location filename="modinfo.cpp" line="567"/> - <location filename="modinfo.cpp" line="570"/> + <location filename="modinfo.cpp" line="586"/> + <location filename="modinfo.cpp" line="589"/> <source>failed to write %1/meta.ini: error %2</source> <translation>не удалоÑÑŒ запиÑать %1/meta.ini: ошибка %2</translation> </message> <message> - <location filename="modinfo.cpp" line="843"/> + <location filename="modinfo.cpp" line="862"/> <source>%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory</source> <translation>%1 не Ñодержит ни esp/esm, ни папок реÑурÑов (textures, meshes, interface, ...)</translation> </message> <message> - <location filename="modinfo.cpp" line="847"/> + <location filename="modinfo.cpp" line="866"/> <source>Categories: <br></source> <translation>Категории: <br></translation> </message> @@ -3496,52 +3534,52 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="55"/> <source>Game plugins (esp/esm)</source> - <translation type="unfinished"></translation> + <translation>Игровые плагины (esp/esm)</translation> </message> <message> <location filename="modlist.cpp" line="56"/> <source>Interface</source> - <translation type="unfinished"></translation> + <translation>ИнтерфейÑ</translation> </message> <message> <location filename="modlist.cpp" line="57"/> <source>Meshes</source> - <translation type="unfinished"></translation> + <translation>Полигональные Ñетки</translation> </message> <message> <location filename="modlist.cpp" line="58"/> <source>Music</source> - <translation type="unfinished"></translation> + <translation>Музыка</translation> </message> <message> <location filename="modlist.cpp" line="59"/> <source>Scripts (Papyrus)</source> - <translation type="unfinished"></translation> + <translation>Скрипты (Papyrus)</translation> </message> <message> <location filename="modlist.cpp" line="60"/> <source>Script Extender Plugin</source> - <translation type="unfinished"></translation> + <translation>Script Extender плагин</translation> </message> <message> <location filename="modlist.cpp" line="61"/> <source>SkyProc Patcher</source> - <translation type="unfinished"></translation> + <translation>Патч SkyProc</translation> </message> <message> <location filename="modlist.cpp" line="62"/> <source>Sound</source> - <translation type="unfinished"></translation> + <translation>Звук</translation> </message> <message> <location filename="modlist.cpp" line="63"/> <source>Strings</source> - <translation type="unfinished"></translation> + <translation>Строки</translation> </message> <message> <location filename="modlist.cpp" line="64"/> <source>Textures</source> - <translation type="unfinished"></translation> + <translation>ТекÑтуры</translation> </message> <message> <location filename="modlist.cpp" line="117"/> @@ -3596,7 +3634,6 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="364"/> <source>installed version: "%1", newest version: "%2"</source> - <oldsource>installed version: %1, newest version: %2</oldsource> <translation>уÑтановлена верÑиÑ: %1, Ð½Ð¾Ð²ÐµÐ¹ÑˆÐ°Ñ Ð²ÐµÑ€ÑиÑ: %2</translation> </message> <message> @@ -3637,7 +3674,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="935"/> <source>Content</source> - <translation type="unfinished">Содержание</translation> + <translation>Содержание</translation> </message> <message> <location filename="modlist.cpp" line="936"/> @@ -3647,7 +3684,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="937"/> <source>Version</source> - <translation type="unfinished">ВерÑиÑ</translation> + <translation>ВерÑиÑ</translation> </message> <message> <location filename="modlist.cpp" line="938"/> @@ -3708,7 +3745,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="957"/> <source>Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></source> - <translation type="unfinished"></translation> + <translation>Показывает Ñодержимое мода:<br><img src=":/MO/gui/content/plugin" width=32/>Плагины (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>интерфейÑ<br><img src=":/MO/gui/content/mesh" width=32/>Полигональные Ñетки<br><img src=":/MO/gui/content/texture" width=32/>ТекÑтуры<br><img src=":/MO/gui/content/sound" width=32/>Звуки<br><img src=":/MO/gui/content/music" width=32/>Музыка<br><img src=":/MO/gui/content/string" width=32/>Строки<br><img src=":/MO/gui/content/script" width=32/>Скрипты (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Плагины Script Extender<br><img src=":/MO/gui/content/skyproc" width=32/>Патч SkyProc<br></translation> </message> <message> <location filename="modlist.cpp" line="969"/> @@ -3745,22 +3782,22 @@ p, li { white-space: pre-wrap; } <context> <name>NXMAccessManager</name> <message> - <location filename="nxmaccessmanager.cpp" line="144"/> + <location filename="nxmaccessmanager.cpp" line="152"/> <source>Logging into Nexus</source> <translation>ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð½Ð° Nexus</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="159"/> + <location filename="nxmaccessmanager.cpp" line="167"/> <source>timeout</source> <translation>задержка</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="178"/> + <location filename="nxmaccessmanager.cpp" line="186"/> <source>Unknown error</source> <translation>ÐеизвеÑÑ‚Ð½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="204"/> + <location filename="nxmaccessmanager.cpp" line="212"/> <source>Please check your password</source> <translation>Проверьте ваш пароль</translation> </message> @@ -3808,7 +3845,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="90"/> <source>&Open</source> - <translation type="unfinished">&Открыть</translation> + <translation>&Открыть</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="91"/> @@ -3818,7 +3855,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="109"/> <source>%1 not found</source> - <translation type="unfinished">%1 не найден</translation> + <translation>%1 не найден</translation> </message> <message> <location filename="overwriteinfodialog.cpp" line="144"/> @@ -3856,114 +3893,114 @@ p, li { white-space: pre-wrap; } <context> <name>PluginList</name> <message> - <location filename="pluginlist.cpp" line="103"/> + <location filename="pluginlist.cpp" line="104"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> - <location filename="pluginlist.cpp" line="104"/> + <location filename="pluginlist.cpp" line="105"/> <source>Priority</source> <translation>Приоритет</translation> </message> <message> - <location filename="pluginlist.cpp" line="105"/> + <location filename="pluginlist.cpp" line="106"/> <source>Mod Index</source> <translation>ИндекÑ</translation> </message> <message> - <location filename="pluginlist.cpp" line="106"/> + <location filename="pluginlist.cpp" line="107"/> <source>Flags</source> <translation>Флаги</translation> </message> <message> - <location filename="pluginlist.cpp" line="107"/> - <location filename="pluginlist.cpp" line="119"/> + <location filename="pluginlist.cpp" line="108"/> + <location filename="pluginlist.cpp" line="120"/> <source>unknown</source> <translation>неизвеÑтно</translation> </message> <message> - <location filename="pluginlist.cpp" line="115"/> + <location filename="pluginlist.cpp" line="116"/> <source>Name of your mods</source> <translation>Имена ваших модов</translation> </message> <message> - <location filename="pluginlist.cpp" line="116"/> + <location filename="pluginlist.cpp" line="117"/> <source>Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority.</source> <translation>Приоритет загрузки ваших модов. Моды Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð¼ приоритетом перезапишут данные модов Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ приоритетом.</translation> </message> <message> - <location filename="pluginlist.cpp" line="118"/> + <location filename="pluginlist.cpp" line="119"/> <source>The modindex determins the formids of objects originating from this mods.</source> <translation>Ð˜Ð½Ð´ÐµÐºÑ Ð¼Ð¾Ð´Ð¾Ð², определÑющий formid объектов, проиÑходÑщих из Ñтих модов.</translation> </message> <message> - <location filename="pluginlist.cpp" line="159"/> + <location filename="pluginlist.cpp" line="160"/> <source>failed to update esp info for file %1 (source id: %2), error: %3</source> <translation>не удалоÑÑŒ обновить информацию о esp Ð´Ð»Ñ Ñ„Ð°Ð¹Ð»Ð° %1 (id иÑточника: %2), ошибка: %3</translation> </message> <message> - <location filename="pluginlist.cpp" line="227"/> + <location filename="pluginlist.cpp" line="228"/> <source>esp not found: %1</source> <translation>esp не найден: %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="235"/> + <location filename="pluginlist.cpp" line="247"/> <source>Confirm</source> <translation>Подтвердить</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> + <location filename="pluginlist.cpp" line="235"/> <source>Really enable all plugins?</source> <translation>ДейÑтвительно подключить вÑе плагины?</translation> </message> <message> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="247"/> <source>Really disable all plugins?</source> <translation>ДейÑтвительно отключить вÑе плагины?</translation> </message> <message> - <location filename="pluginlist.cpp" line="397"/> + <location filename="pluginlist.cpp" line="398"/> <source>The file containing locked plugin indices is broken</source> <translation>Файл, Ñодержащий индекÑÑ‹ заблокированного плагина, не работает.</translation> </message> <message> - <location filename="pluginlist.cpp" line="438"/> + <location filename="pluginlist.cpp" line="439"/> <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source> <translation>Ðекоторые из ваших плагинов имеют неверные имена. Ðти плагины не могут быть загружены игрой. Смотрите mo_interface.log Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ ÑпиÑка таких плагинов и переименуйте их.</translation> </message> <message> <location filename="pluginlist.cpp" line="806"/> + <source>This plugin can't be disabled (enforced by the game)</source> + <translation>Ðтот плагин не может быть отключен (грузитÑÑ Ð¸Ð³Ñ€Ð¾Ð¹ принудительно)</translation> + </message> + <message> + <location filename="pluginlist.cpp" line="808"/> <source><b>Origin</b>: %1</source> <translation><b>ИÑточник</b>: %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="808"/> + <location filename="pluginlist.cpp" line="810"/> <source>Author</source> <translation>Ðвтор</translation> </message> <message> - <location filename="pluginlist.cpp" line="811"/> + <location filename="pluginlist.cpp" line="813"/> <source>Description</source> <translation>ОпиÑание</translation> </message> <message> - <location filename="pluginlist.cpp" line="804"/> - <source>This plugin can't be disabled (enforced by the game)</source> - <translation>Ðтот плагин не может быть отключен (грузитÑÑ Ð¸Ð³Ñ€Ð¾Ð¹ принудительно)</translation> - </message> - <message> - <location filename="pluginlist.cpp" line="814"/> + <location filename="pluginlist.cpp" line="816"/> <source>Missing Masters</source> <translation>ОтÑутÑтвующие маÑтерфайлы</translation> </message> <message> - <location filename="pluginlist.cpp" line="821"/> + <location filename="pluginlist.cpp" line="823"/> <source>Enabled Masters</source> <translation>Подключенные маÑтерфайлы</translation> </message> <message> - <location filename="pluginlist.cpp" line="972"/> + <location filename="pluginlist.cpp" line="974"/> <source>failed to restore load order for %1</source> <translation>не удалоÑÑŒ воÑÑтановить порÑдок загрузки Ð´Ð»Ñ %1</translation> </message> @@ -3993,7 +4030,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -4141,7 +4178,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html></source> @@ -4174,7 +4211,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4249,7 +4286,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.ui" line="162"/> <source>Close</source> - <translation type="unfinished">Закрыть</translation> + <translation>Закрыть</translation> </message> <message> <location filename="profilesdialog.cpp" line="61"/> @@ -4265,7 +4302,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="152"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> <location filename="profilesdialog.cpp" line="152"/> @@ -4424,7 +4461,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="loadmechanism.cpp" line="138"/> <source>Failed to delete %1</source> - <translation type="unfinished">Ðе удалоÑÑŒ удалить %1</translation> + <translation>Ðе удалоÑÑŒ удалить %1</translation> </message> <message> <location filename="loadmechanism.cpp" line="144"/> @@ -4475,60 +4512,60 @@ p, li { white-space: pre-wrap; } <translation>Ðе удалоÑÑŒ уÑтановить загрузку proxy-dll</translation> </message> <message> - <location filename="main.cpp" line="121"/> + <location filename="main.cpp" line="122"/> <source>Permissions required</source> <translation>ТребуютÑÑ Ð¿Ñ€Ð°Ð²Ð° доÑтупа</translation> </message> <message> - <location filename="main.cpp" line="122"/> + <location filename="main.cpp" line="123"/> <source>The current user account doesn't have the required access rights to run Mod Organizer. The neccessary changes can be made automatically (the MO directory will be made writable for the current user account). You will be asked to run "helper.exe" with administrative rights.</source> <translation>Текущий аккаунт Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ имеет требуемых прав доÑтупа Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка Mod Organizer. Ðеобходимые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ быть Ñделаны автоматичеÑки (папка MO будет Ñделана запиÑываемой Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ аккаунта пользователÑ). Ð’Ñ‹ получите Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¾ запуÑке "helper.exe" Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ админиÑтратора.</translation> </message> <message> - <location filename="main.cpp" line="218"/> - <location filename="main.cpp" line="256"/> + <location filename="main.cpp" line="202"/> + <location filename="main.cpp" line="241"/> <source>Woops</source> <translation>УпÑ</translation> </message> <message> - <location filename="main.cpp" line="219"/> + <location filename="main.cpp" line="203"/> <source>ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened</source> <translation>Mod Organizer вышел из ÑтроÑ! Ðужно ли Ñоздать диагноÑтичеÑкий файл? ЕÑли вы вышлите файл (%1) по адреÑу sherb@gmx.net, ошибка Ñ Ð½Ð°Ð¼Ð½Ð¾Ð³Ð¾ большей вероÑтноÑтью будет иÑправлена. ПожалуйÑта, добавьте краткое опиÑание Ñвоих дейÑтвий, перед тем, как произошла ошибка</translation> </message> <message> - <location filename="main.cpp" line="257"/> + <location filename="main.cpp" line="242"/> <source>ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1</source> <translation>ModOrganizer вышел из ÑтроÑ! К Ñожалению не удалоÑÑŒ запиÑать диагноÑтичеÑкий файл: %1</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <location filename="settings.cpp" line="528"/> <source>Mod Organizer</source> <translation>Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <source>An instance of Mod Organizer is already running</source> <translation>Другой ÑкземплÑÑ€ Mod Organizer уже запущен</translation> </message> <message> - <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="397"/> <source>No game identified in "%1". The directory is required to contain the game binary and its launcher.</source> <translation>Игра не обнаружена в "%1". ТребуетÑÑ, чтобы папка Ñодержала иÑполнÑемые файлы игры.</translation> </message> <message> - <location filename="main.cpp" line="403"/> - <location filename="main.cpp" line="432"/> + <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="429"/> <source>Please select the game to manage</source> <translation>Выберете игру Ð´Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ</translation> </message> <message> - <location filename="main.cpp" line="458"/> + <location filename="main.cpp" line="456"/> <source>Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)</source> <translation>ПожалуйÑта, выберете редакцию игры, которую вы имеете (MO не Ñможет правильно запуÑтить игру, еÑли Ñто будет уÑтановлено неверно!)</translation> </message> <message> - <location filename="main.cpp" line="547"/> + <location filename="main.cpp" line="545"/> <source>failed to start application: %1</source> <translation>не удалоÑÑŒ запуÑтить приложение: %1</translation> </message> @@ -4538,28 +4575,28 @@ p, li { white-space: pre-wrap; } <translation>ИÑпользуйте пункт "Справка" на панели инÑтрументов, чтобы получить инÑтрукции по иÑпользованию вÑех Ñлементов.</translation> </message> <message> - <location filename="mainwindow.cpp" line="1649"/> - <location filename="mainwindow.cpp" line="4314"/> + <location filename="mainwindow.cpp" line="1659"/> + <location filename="mainwindow.cpp" line="4347"/> <source><Manage...></source> <translation><УправлÑть...></translation> </message> <message> - <location filename="mainwindow.cpp" line="1667"/> + <location filename="mainwindow.cpp" line="1677"/> <source>failed to parse profile %1: %2</source> <translation>не удалоÑÑŒ обработать профиль %1: %2</translation> </message> <message> - <location filename="pluginlist.cpp" line="352"/> + <location filename="pluginlist.cpp" line="353"/> <source>failed to find "%1"</source> <translation>не удалоÑÑŒ найти "%1"</translation> </message> <message> - <location filename="pluginlist.cpp" line="516"/> + <location filename="pluginlist.cpp" line="518"/> <source>failed to access %1</source> <translation>не удалоÑÑŒ получить доÑтуп к %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="530"/> + <location filename="pluginlist.cpp" line="532"/> <source>failed to set file time %1</source> <translation>не удалоÑÑŒ изменить дату модификации Ð´Ð»Ñ %1</translation> </message> @@ -4571,7 +4608,6 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="96"/> <source>"%1" is missing or inaccessible</source> - <oldsource>"%1" is missing</oldsource> <translation>"%1" отÑутÑтвует или недоÑтупен</translation> </message> <message> @@ -4586,6 +4622,11 @@ p, li { white-space: pre-wrap; } <translation>Ошибка</translation> </message> <message> + <location filename="safewritefile.cpp" line="33"/> + <source>failed to open temporary file</source> + <translation>не удалоÑÑŒ открыть временный файл</translation> + </message> + <message> <location filename="savegamegamebryo.cpp" line="130"/> <location filename="savegamegamebryo.cpp" line="189"/> <location filename="savegamegamebryo.cpp" line="231"/> @@ -4608,17 +4649,17 @@ p, li { white-space: pre-wrap; } <translation>Proxy DLL</translation> </message> <message> - <location filename="spawn.cpp" line="133"/> + <location filename="spawn.cpp" line="140"/> <source>failed to spawn "%1"</source> <translation>не удалоÑÑŒ вызвать "%1"</translation> </message> <message> - <location filename="spawn.cpp" line="140"/> + <location filename="spawn.cpp" line="147"/> <source>Elevation required</source> <translation>ТребуетÑÑ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð¸Ðµ прав</translation> </message> <message> - <location filename="spawn.cpp" line="141"/> + <location filename="spawn.cpp" line="148"/> <source>This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" @@ -4633,30 +4674,25 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe ЗапуÑтить Ñ Ð¿Ð¾Ð²Ñ‹ÑˆÐµÐ½Ð½Ñ‹Ð¼Ð¸ правами в любом Ñлучае? (будет выведен Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð¾ разрешении ModOrganizer.exe Ñделать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² ÑиÑтеме)</translation> </message> <message> - <location filename="spawn.cpp" line="156"/> + <location filename="spawn.cpp" line="163"/> <source>failed to spawn "%1": %2</source> <translation>не удалоÑÑŒ вызвать "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="165"/> + <location filename="spawn.cpp" line="172"/> <source>"%1" doesn't exist</source> <translation>"%1" не ÑущеÑтвует</translation> </message> <message> - <location filename="spawn.cpp" line="172"/> + <location filename="spawn.cpp" line="179"/> <source>failed to inject dll into "%1": %2</source> <translation>не удалоÑÑŒ подключить dll к "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="190"/> + <location filename="spawn.cpp" line="197"/> <source>failed to run "%1"</source> <translation>не удалоÑÑŒ запуÑтить "%1"</translation> </message> - <message> - <location filename="safewritefile.cpp" line="33"/> - <source>failed to open temporary file</source> - <translation>не удалоÑÑŒ открыть временный файл</translation> - </message> </context> <context> <name>QueryOverwriteDialog</name> @@ -4683,7 +4719,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="queryoverwritedialog.ui" line="77"/> <source>Replace</source> - <translation type="unfinished">Заменить</translation> + <translation>Заменить</translation> </message> <message> <location filename="queryoverwritedialog.ui" line="84"/> @@ -4693,7 +4729,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="queryoverwritedialog.ui" line="91"/> <source>Cancel</source> - <translation type="unfinished">Отмена</translation> + <translation>Отмена</translation> </message> </context> <context> @@ -4752,7 +4788,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.ui" line="59"/> <source>Close</source> - <translation type="unfinished">Закрыть</translation> + <translation>Закрыть</translation> </message> <message> <location filename="savetextasdialog.cpp" line="36"/> @@ -4762,7 +4798,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Text Files</source> - <translation type="unfinished">ТекÑтовые файлы</translation> + <translation>ТекÑтовые файлы</translation> </message> <message> <location filename="savetextasdialog.cpp" line="40"/> @@ -4780,12 +4816,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selectiondialog.ui" line="23"/> <source>Placeholder</source> - <translation type="unfinished">Заполнитель</translation> + <translation>Метка-заполнитель</translation> </message> <message> <location filename="selectiondialog.ui" line="77"/> <source>Cancel</source> - <translation type="unfinished">Отмена</translation> + <translation>Отмена</translation> </message> </context> <context> @@ -4874,12 +4910,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="settings.cpp" line="115"/> <source>Failed</source> - <translation type="unfinished">Ðеудача</translation> + <translation>Ðеудача</translation> </message> <message> <location filename="settings.cpp" line="116"/> <source>Sorry, failed to start the helper application</source> - <translation type="unfinished"></translation> + <translation>Ðе удалоÑÑŒ запуÑтить программу-помощник </translation> </message> <message> <location filename="settings.cpp" line="335"/> @@ -4925,7 +4961,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5083,7 +5119,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5104,12 +5140,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="311"/> <source>Username</source> - <translation type="unfinished">Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ</translation> + <translation>Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ</translation> </message> <message> <location filename="settingsdialog.ui" line="325"/> <source>Password</source> - <translation type="unfinished">Пароль</translation> + <translation>Пароль</translation> </message> <message> <location filename="settingsdialog.ui" line="347"/> @@ -5211,7 +5247,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5249,7 +5285,7 @@ p, li { white-space: pre-wrap; } There are several means to do this: *Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam.</source> <translation>Mod Organizer необходимо подключить dll к игре, чтобы вÑе моды были видны в ней. @@ -5273,8 +5309,8 @@ If you use the Steam version of Oblivion the default will NOT work. In this case <message> <location filename="settingsdialog.ui" line="701"/> <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't need an update. Therefore you can configure the version to identify as here. -Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. +On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here. +Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</source> <translation>Mod Organizer иÑпользует API Nexus , Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð°ÐºÐ¸Ñ… возможноÑтей, как проверка обновлений и загрузка файлов. К Ñожалению Ñтот API не был Ñделан официально доÑтупным прочим утилитам, вроде MO, так что нужно предÑтавлÑтьÑÑ ÐºÐ°Ðº Nexus Mod Manager, чтобы получить доÑтуп. @@ -5290,7 +5326,7 @@ tl;dr-верÑиÑ: ЕÑли возможноÑти Nexus не работают, </message> <message> <location filename="settingsdialog.ui" line="726"/> - <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.</source> <translation>КажетÑÑ, что иногда игры загружают ESP и ESM файлы, даже еÑли они не были не подключены как плагины ОбÑтоÑтельÑтва Ñтого пока не извеÑтны, но отчеты пользователей подразумевают, что Ñто в Ñ€Ñде Ñлучаев нежелательно. ЕÑли Ñтот флажок отмечен, не отмеченные в ÑпиÑке ESP и ESM не будут видимы в ÑпиÑке и не будут загружены.</translation> @@ -5325,7 +5361,7 @@ Uncheck this if you want to use Mod Organizer with total conversions (like Nehri <message> <location filename="settingsdialog.ui" line="757"/> <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't be resolved correctly. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</source> <translation>По умолчанию Mod Organizer отобразит пакеты esp+bsa, уÑтановленные из других инÑтрументов, как моды (Ð»ÐµÐ²Ð°Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ). Ðто позволÑет вам контроллировать их приоритет по отношению к другим модам. Ðто оÑобенно полезно, еÑли вы иÑпользуете Steam Workshop, Ð´Ð»Ñ ÑƒÑтановки модов. @@ -5392,7 +5428,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="simpleinstalldialog.ui" line="22"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> <location filename="simpleinstalldialog.ui" line="49"/> @@ -5413,7 +5449,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="simpleinstalldialog.ui" line="72"/> <source>Cancel</source> - <translation type="unfinished">Отмена</translation> + <translation>Отмена</translation> </message> </context> <context> @@ -5431,7 +5467,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="singleinstance.cpp" line="88"/> <source>failed to communicate with running instance: %1</source> - <translation type="unfinished">не удалоÑÑŒ подключитьÑÑ Ðº запущенному ÑкземплÑру: %1</translation> + <translation>Ðе удалоÑÑŒ подключитьÑÑ Ðº запущенному ÑкземплÑру: %1</translation> </message> <message> <location filename="singleinstance.cpp" line="100"/> @@ -5449,7 +5485,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="syncoverwritedialog.ui" line="27"/> <source>Name</source> - <translation type="unfinished">ИмÑ</translation> + <translation>ИмÑ</translation> </message> <message> <location filename="syncoverwritedialog.ui" line="32"/> @@ -5477,7 +5513,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="transfersavesdialog.ui" line="14"/> <source>Transfer Savegames</source> - <translation type="unfinished">Передать ÑохранениÑ</translation> + <translation>ПеренеÑти ÑохранениÑ</translation> </message> <message> <location filename="transfersavesdialog.ui" line="22"/> @@ -5552,7 +5588,7 @@ On Windows XP: <message> <location filename="transfersavesdialog.ui" line="156"/> <source>Done</source> - <translation type="unfinished">Готово</translation> + <translation>Готово</translation> </message> <message> <location filename="transfersavesdialog.ui" line="167"/> @@ -5594,4 +5630,4 @@ On Windows XP: <translation>Скопировать вÑе ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ Ð¿ÐµÑ€Ñонажем "%1" в общее меÑтораÑположение? Имейте ввиду, что Ñто запутает текущую нумерацию Ñохранений.</translation> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/src/organizer_zh_CN.ts b/src/organizer_zh_CN.ts index 9b8754bb..ae964233 100644 --- a/src/organizer_zh_CN.ts +++ b/src/organizer_zh_CN.ts @@ -1,38 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.0" language="zh_CN"> +<?xml version="1.0" ?><!DOCTYPE TS><TS language="zh_CN" version="2.0"> <context> <name>AboutDialog</name> <message> <location filename="aboutdialog.ui" line="14"/> <location filename="aboutdialog.ui" line="53"/> <source>About</source> - <translation type="unfinished"></translation> + <translation>关于</translation> </message> <message> <location filename="aboutdialog.ui" line="66"/> <source>Revision:</source> - <translation type="unfinished"></translation> + <translation>版本</translation> </message> <message> <location filename="aboutdialog.ui" line="104"/> <source>Used Software</source> - <translation type="unfinished"></translation> + <translation>用到的软件</translation> </message> <message> <location filename="aboutdialog.ui" line="117"/> <source>Credits</source> - <translation type="unfinished"></translation> + <translation>制作组</translation> </message> <message> <location filename="aboutdialog.ui" line="123"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation>翻译机</translation> </message> <message> <location filename="aboutdialog.ui" line="189"/> <source>Others</source> - <translation type="unfinished"></translation> + <translation>其它</translation> </message> <message> <location filename="aboutdialog.ui" line="266"/> @@ -42,7 +40,7 @@ <message> <location filename="aboutdialog.cpp" line="80"/> <source>No license</source> - <translation type="unfinished"></translation> + <translation>æ— æŽˆæƒ</translation> </message> </context> <context> @@ -62,7 +60,7 @@ <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -160,22 +158,22 @@ If there is a component called "00 Core" it is usually required. Optio <message> <location filename="browserdialog.ui" line="14"/> <source>Some Page</source> - <translation type="unfinished"></translation> + <translation>æŸäº›é¡µé¢</translation> </message> <message> <location filename="browserdialog.ui" line="281"/> <source>Search</source> - <translation type="unfinished"></translation> + <translation>æœç´¢</translation> </message> <message> <location filename="browserdialog.cpp" line="95"/> <source>new</source> - <translation type="unfinished"></translation> + <translation>新建</translation> </message> <message> <location filename="browserdialog.cpp" line="209"/> <source>failed to start download</source> - <translation type="unfinished"></translation> + <translation>å¯åŠ¨ä¸‹è½½å¤±è´¥</translation> </message> </context> <context> @@ -226,7 +224,7 @@ If there is a component called "00 Core" it is usually required. Optio <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html></source> @@ -289,7 +287,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="credentialsdialog.ui" line="75"/> <source>Never ask again</source> - <translation type="unfinished">æ— æ³•è¯»å–bsa</translation> + <translation>ä¸å†è¿‡é—®</translation> </message> </context> <context> @@ -325,7 +323,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlist.cpp" line="89"/> <source>pending download</source> - <translation type="unfinished"></translation> + <translation>挂起下载</translation> </message> </context> <context> @@ -381,12 +379,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="92"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation>< mod %1 file %2 ></translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="97"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>挂起</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="120"/> @@ -401,12 +399,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="125"/> <source>Fetching Info 2</source> - <translation type="unfinished">抓å–ä¿¡æ¯ 2</translation> + <translation>抓å–ä¿¡æ¯ 2</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="130"/> <source>Installed</source> - <translation type="unfinished">抓å–ä¿¡æ¯ 2</translation> + <translation>已安装</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="133"/> @@ -459,7 +457,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="306"/> <source>Delete</source> - <translation type="unfinished">&åˆ é™¤</translation> + <translation>åˆ é™¤</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="308"/> @@ -517,22 +515,22 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="93"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation>< mod %1 file %2 ></translation> </message> <message> <location filename="downloadlistwidget.cpp" line="96"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>挂起</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="123"/> <source>Fetching Info 1</source> - <translation type="unfinished">抓å–ä¿¡æ¯ 1</translation> + <translation>抓å–ä¿¡æ¯ 1</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="126"/> <source>Fetching Info 2</source> - <translation type="unfinished">抓å–ä¿¡æ¯ 2</translation> + <translation>抓å–ä¿¡æ¯ 2</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="258"/> @@ -638,7 +636,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="321"/> <source>Memory allocation error (in refreshing directory).</source> - <translation type="unfinished"></translation> + <translation>地å€åˆ†é…错误(刷新目录时).</translation> </message> <message> <location filename="downloadmanager.cpp" line="369"/> @@ -658,12 +656,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="454"/> <source>Wrong Game</source> - <translation type="unfinished"></translation> + <translation>错误的游æˆ</translation> </message> <message> <location filename="downloadmanager.cpp" line="454"/> <source>The download link is for a mod for "%1" but this instance of MO has been set up for "%2".</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadmanager.cpp" line="471"/> @@ -708,7 +706,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="640"/> <source>No known download urls. Sorry, this download can't be resumed.</source> - <translation type="unfinished"></translation> + <translation>未知的下载地å€ã€‚很抱æ‰ï¼Œä¸‹è½½æ— 法继ç»ã€‚</translation> </message> <message> <location filename="downloadmanager.cpp" line="695"/> @@ -728,7 +726,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="745"/> <source>Update</source> - <translation type="unfinished">æ›´æ–°</translation> + <translation>æ›´æ–°</translation> </message> <message> <location filename="downloadmanager.cpp" line="746"/> @@ -753,12 +751,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="999"/> <source>Memory allocation error (in processing progress event).</source> - <translation type="unfinished"></translation> + <translation>地å€åˆ†é…错误(处ç†ç¨‹åºäº‹ä»¶æ—¶).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1012"/> <source>Memory allocation error (in processing downloaded data).</source> - <translation type="unfinished"></translation> + <translation>地å€åˆ†é…错误(处ç†ä¸‹è½½æ•°æ®æ—¶).</translation> </message> <message> <location filename="downloadmanager.cpp" line="1141"/> @@ -789,7 +787,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="1356"/> <source>Download failed. Server reported: %1</source> - <translation type="unfinished"></translation> + <translation>下载失败。æœåŠ¡å™¨æŠ¥å‘Š: %1 </translation> </message> <message> <location filename="downloadmanager.cpp" line="1358"/> @@ -964,7 +962,7 @@ Right now the only case I know of where this needs to be overwritten is for the <message> <location filename="editexecutablesdialog.cpp" line="150"/> <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> + <translation>MO需è¦32ä½javaæ¥è¿è¡Œè¯¥åº”用程åºã€‚å¦‚æžœä½ å·²ç»å®‰è£…,在安装目录下选择javaw.exe。</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="166"/> @@ -990,13 +988,13 @@ Right now the only case I know of where this needs to be overwritten is for the <location filename="editexecutablesdialog.cpp" line="230"/> <location filename="editexecutablesdialog.cpp" line="278"/> <source>Save Changes?</source> - <translation type="unfinished">ä¿å˜æ›´æ”¹å—?</translation> + <translation>ä¿å˜ä¿®æ”¹?</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="231"/> <location filename="editexecutablesdialog.cpp" line="279"/> <source>You made changes to the current executable, do you want to save them?</source> - <translation type="unfinished"></translation> + <translation>当å‰å¯æ‰§è¡Œæ–‡ä»¶è¢«ä¿®æ”¹ï¼Œæ˜¯å¦éœ€è¦ä¿å˜?</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="255"/> @@ -1136,7 +1134,7 @@ Right now the only case I know of where this needs to be overwritten is for the <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1180,87 +1178,87 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="164"/> <location filename="installationmanager.cpp" line="248"/> - <location filename="installationmanager.cpp" line="530"/> + <location filename="installationmanager.cpp" line="532"/> <source>Extracting files</source> <translation>æ£åœ¨è§£åŽ‹æ–‡ä»¶</translation> </message> <message> - <location filename="installationmanager.cpp" line="439"/> + <location filename="installationmanager.cpp" line="441"/> <source>failed to create backup</source> <translation>创建备份失败。</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Mod Name</source> <translation>模组åç§°</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Name</source> <translation>åç§°</translation> </message> <message> - <location filename="installationmanager.cpp" line="501"/> + <location filename="installationmanager.cpp" line="503"/> <source>Invalid name</source> <translation>æ— æ•ˆåç§°</translation> </message> <message> - <location filename="installationmanager.cpp" line="502"/> + <location filename="installationmanager.cpp" line="504"/> <source>The name you entered is invalid, please enter a different one.</source> <translation>ä½ è¾“å…¥çš„åç§°æ— æ•ˆï¼Œè¯·é‡æ–°è¾“入。</translation> </message> <message> - <location filename="installationmanager.cpp" line="610"/> + <location filename="installationmanager.cpp" line="612"/> <source>File format "%1" not supported</source> <translation>æš‚ä¸æ”¯æŒæ–‡ä»¶æ ¼å¼: "%1"</translation> </message> <message> - <location filename="installationmanager.cpp" line="743"/> + <location filename="installationmanager.cpp" line="745"/> <source>None of the available installer plugins were able to handle that archive</source> <translation>没有å¯ç”¨çš„安装æ’ä»¶èƒ½å¤Ÿå¤„ç†æ¤åŽ‹ç¼©åŒ…</translation> </message> <message> - <location filename="installationmanager.cpp" line="753"/> + <location filename="installationmanager.cpp" line="755"/> <source>no error</source> <translation>没有错误</translation> </message> <message> - <location filename="installationmanager.cpp" line="756"/> + <location filename="installationmanager.cpp" line="758"/> <source>7z.dll not found</source> <translation>未找到 7z.dll</translation> </message> <message> - <location filename="installationmanager.cpp" line="759"/> + <location filename="installationmanager.cpp" line="761"/> <source>7z.dll isn't valid</source> <translation>æ— æ•ˆçš„ 7z.dll</translation> </message> <message> - <location filename="installationmanager.cpp" line="762"/> + <location filename="installationmanager.cpp" line="764"/> <source>archive not found</source> <translation>未找到压缩包</translation> </message> <message> - <location filename="installationmanager.cpp" line="765"/> + <location filename="installationmanager.cpp" line="767"/> <source>failed to open archive</source> <translation>æ— æ³•æ‰“å¼€åŽ‹ç¼©åŒ…</translation> </message> <message> - <location filename="installationmanager.cpp" line="768"/> + <location filename="installationmanager.cpp" line="770"/> <source>unsupported archive type</source> <translation>䏿”¯æŒçš„压缩包类型</translation> </message> <message> - <location filename="installationmanager.cpp" line="771"/> + <location filename="installationmanager.cpp" line="773"/> <source>internal library error</source> <translation>内部库错误</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> + <location filename="installationmanager.cpp" line="776"/> <source>archive invalid</source> <translation>æ— æ•ˆçš„åŽ‹ç¼©åŒ…</translation> </message> <message> - <location filename="installationmanager.cpp" line="778"/> + <location filename="installationmanager.cpp" line="780"/> <source>unknown archive error</source> <translation>未知压缩包错误</translation> </message> @@ -1301,7 +1299,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="moapplication.cpp" line="115"/> <source>an error occured: %1</source> - <translation type="unfinished">å‘生错误: %1</translation> + <translation>å‘生错误: %1</translation> </message> <message> <location filename="moapplication.cpp" line="120"/> @@ -1320,27 +1318,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="97"/> <source>Click blank area to deselect</source> - <translation type="unfinished"></translation> + <translation>ç‚¹å‡»ç©ºç™½å¤„å–æ¶ˆé€‰æ‹©</translation> </message> <message> <location filename="mainwindow.ui" line="116"/> <source>If checked, only mods that match all selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>如果选ä¸ï¼Œä»…åŒ¹é…æ‰€æœ‰é€‰å®šç±»åˆ«çš„ Mod 会被显示。</translation> </message> <message> <location filename="mainwindow.ui" line="119"/> <source>And</source> - <translation type="unfinished"></translation> + <translation>å’Œ</translation> </message> <message> <location filename="mainwindow.ui" line="129"/> <source>If checked, all mods that match at least one of the selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>如果选ä¸ï¼ŒåŒ¹é…ä»»æ„一个选定类别的 Mod 会被显示。</translation> </message> <message> <location filename="mainwindow.ui" line="132"/> <source>Or</source> - <translation type="unfinished"></translation> + <translation>或</translation> </message> <message> <location filename="mainwindow.ui" line="171"/> @@ -1350,22 +1348,22 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="181"/> <source>Pick a module collection</source> - <translation type="unfinished">选择一个é…置文件</translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="184"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在这里创建é…置文件,æ¯ä¸ªé…置文件都包å«äº†å®ƒä»¬è‡ªå·±çš„ Mod å’Œ esp çš„æ¿€æ´»æ–¹æ¡ˆã€‚è¿™æ ·æ‚¨å°±å¯ä»¥é€šè¿‡å¿«é€Ÿåˆ‡æ¢è®¾ç½®æ¥ä½“验ä¸åŒçš„æ¸¸æˆåŽ†ç¨‹äº†ã€‚</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">请注æ„: 当剿‚¨çš„é…置文件的 esp åŠ è½½é¡ºåºå¹¶ä¸æ˜¯åˆ†å¼€ä¿å˜çš„。</span></p></body></html></translation> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.ui" line="215"/> + <source>Open list options...</source> + <translation>打开选项列表...</translation> </message> <message> <location filename="mainwindow.ui" line="218"/> @@ -1376,13 +1374,13 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="238"/> <location filename="mainwindow.ui" line="739"/> <source>Restore Backup...</source> - <translation type="unfinished">还原备份</translation> + <translation>还原备份</translation> </message> <message> <location filename="mainwindow.ui" line="252"/> <location filename="mainwindow.ui" line="759"/> <source>Create Backup</source> - <translation type="unfinished"></translation> + <translation>创建备份</translation> </message> <message> <location filename="mainwindow.ui" line="368"/> @@ -1397,7 +1395,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="456"/> <source>Filter</source> - <translation type="unfinished">过滤器</translation> + <translation>过滤器</translation> </message> <message> <location filename="mainwindow.ui" line="477"/> @@ -1426,15 +1424,10 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">选择è¦è¿è¡Œçš„程åºã€‚一旦您开始使用 Mod Organizerï¼Œæ‚¨åº”è¯¥å§‹ç»ˆä»Žè¿™é‡Œæˆ–é€šè¿‡åœ¨è¿™é‡Œåˆ›å»ºçš„å¿«æ·æ–¹å¼æ¥è¿è¡Œæ‚¨çš„æ¸¸æˆå’Œå·¥å…·ï¼Œå¦åˆ™ä»»ä½•ç»ç”± MO 安装的 Mod 都会å˜å¾—ä¸å¯è§ã€‚</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您å¯ä»¥æ·»åŠ æ–°çš„å·¥å…·åˆ°æ¤åˆ—表ä¸ï¼Œä½†æˆ‘ä¸èƒ½ä¿è¯ä¸€äº›æˆ‘没有测试过的工具能够æ£å¸¸å·¥ä½œã€‚</span></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="581"/> @@ -1446,13 +1439,9 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer å¯ç”¨çš„状æ€ä¸‹è¿è¡ŒæŒ‡å®šçš„程åºã€‚</span></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="594"/> @@ -1469,13 +1458,9 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">创建一个开始èœå•å¿«æ·æ–¹å¼ï¼Œä½¿æ‚¨å¯ä»¥ç›´æŽ¥åœ¨ MO 激活状æ€ä¸‹è¿è¡ŒæŒ‡å®šçš„程åºã€‚</span></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="645"/> @@ -1488,6 +1473,11 @@ p, li { white-space: pre-wrap; } <translation>æ’ä»¶</translation> </message> <message> + <location filename="mainwindow.ui" line="715"/> + <source>Sort</source> + <translation>排åº</translation> + </message> + <message> <location filename="mainwindow.ui" line="821"/> <source>List of available esp/esm files</source> <translation>å¯ç”¨ esp 或 esm 文件的列表</translation> @@ -1497,43 +1487,29 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">这个列表ä¸åŒ…å«äº†ä½äºŽå·²æ¿€æ´» Mod 里的 esp å’Œ esm 文件。这些文件都需è¦å®ƒä»¬è‡ªå·±çš„åŠ è½½é¡ºåºï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ‹–放æ¥ä¿®æ”¹åŠ è½½é¡ºåºã€‚请注æ„: MO å°†åªä¿å˜å·²æ¿€æ´»æˆ–已勾选状æ€çš„ Mod çš„åŠ è½½é¡ºåºã€‚<br />有个éžå¸¸æ£’的工具å«ä½œ &quot;BOSS&quot;,它å¯ä»¥è‡ªåŠ¨å¯¹è¿™äº›æ–‡ä»¶è¿›è¡ŒæŽ’åºã€‚</span></p></body></html></translation> - </message> - <message> - <location filename="mainwindow.ui" line="715"/> - <source>Sort</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.ui" line="215"/> - <source>Open list options...</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="886"/> <source>Archives</source> - <translation type="unfinished"></translation> + <translation>压缩包</translation> </message> <message> <location filename="mainwindow.ui" line="916"/> <source><html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="919"/> <source><html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html></source> - <translation type="unfinished"></translation> + <translation><html><head/><body><p>使用 MO 管ç†åŽ‹ç¼©åŒ… (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">查看更多</span></a>)</p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="934"/> <source>List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order.</source> - <translation>å¯ç”¨ BSA 文件的列表。未勾选的项目ä¸ä¼šè¢« MO 管ç†å¹¶ä¸”会忽略安装顺åºã€‚</translation> + <translation>å¯ç”¨ BSA 压缩包的列表。未勾选的项目ä¸ä¼šè¢« MO 管ç†å¹¶ä¸”会忽略安装顺åºã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="937"/> @@ -1541,10 +1517,7 @@ p, li { white-space: pre-wrap; } By default, BSAs that share their base name with an enabled ESP (i.e. plugin.esp and plugin.bsa) are automatically loaded and will have precedence over all loose files, the installation order you set up to the left is then ignored! BSAs checked here are loaded in such a way that your installation order is obeyed properly.</source> - <translation type="unfinished">BSA 文件是 Bethesda 专用的压缩包文件 (区别于 .zip 文件),里é¢åŒ…å«äº†æ¸¸æˆæ‰€ç”¨çš„ Data 内的文件 (meshes, textures ç‰)。这与 Data 目录里分散的文件是ä¸åŒçš„。 -默认情况下,BSA 文件的åç§°å–决于 ESP æ’ä»¶çš„åç§° (例: plugins.esp 对应 plugins.bsa)。游æˆè¿è¡Œæ—¶ï¼ŒESP 对应的 BSA å°†ä¼šè‡ªåŠ¨åŠ è½½ï¼Œå¹¶ä¸”æ¯”æ‰€æœ‰åˆ†æ•£çš„æ–‡ä»¶ä¼˜å…ˆçº§éƒ½é«˜ï¼Œå·¦è¾¹æ‚¨è®¾ç½®çš„å®‰è£…é¡ºåºæœ€ç»ˆä¼šè¢«å¿½ç•¥æŽ‰ã€‚ - -这里勾选的 BSA 将会ä¾ä»Žæ‚¨çš„安装顺åºï¼Œå¹¶ä¸”ä¼šè‡ªè¡Œè°ƒæ•´åŠ è½½é¡ºåºã€‚</translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="983"/> @@ -1555,7 +1528,7 @@ BSAs checked here are loaded in such a way that your installation order is obeye <message> <location filename="mainwindow.ui" line="992"/> <source>Data</source> - <translation type="unfinished">Data</translation> + <translation>Data</translation> </message> <message> <location filename="mainwindow.ui" line="1010"/> @@ -1569,8 +1542,8 @@ BSAs checked here are loaded in such a way that your installation order is obeye </message> <message> <location filename="mainwindow.ui" line="1016"/> - <location filename="mainwindow.cpp" line="3833"/> - <location filename="mainwindow.cpp" line="4705"/> + <location filename="mainwindow.cpp" line="3858"/> + <location filename="mainwindow.cpp" line="4738"/> <source>Refresh</source> <translation>刷新</translation> </message> @@ -1605,17 +1578,11 @@ BSAs checked here are loaded in such a way that your installation order is obeye <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">è¿™æ˜¯æ¤æ¸¸æˆæ‰€æœ‰å˜æ¡£çš„åˆ—è¡¨ï¼Œå°†é¼ æ ‡æ‚¬åœåœ¨é¡¹ç›®ä¸Šæ¥èŽ·å–è¯¥å˜æ¡£çš„详细信æ¯ï¼Œé‡Œé¢åŒ…å«äº†çŽ°åœ¨æ²¡æœ‰è¢«æ¿€æ´»ä½†æ˜¯å½“å˜æ¡£è¢«åˆ›å»ºæ—¶æ‰€ä½¿ç”¨çš„ esp 或 esm 的清å•。</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在å³é”®èœå•ä¸ç‚¹å‡»â€œä¿®å¤ Modâ€ï¼Œé‚£ä¹ˆ MO 便会å°è¯•激活所有 Mod å’Œ esp æ¥ä¿®å¤é‚£äº›ç¼ºå¤±çš„ esp,它并ä¸ä¼šç¦ç”¨ä»»ä½•东西ï¼</span></p></body></html></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="1115"/> @@ -1630,7 +1597,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1200"/> <source>Show Hidden</source> - <translation type="unfinished"></translation> + <translation>显示éšè—</translation> </message> <message> <location filename="mainwindow.ui" line="1262"/> @@ -1645,7 +1612,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1307"/> <source>Install &Mod</source> - <translation type="unfinished">安装 &Mod</translation> + <translation>安装 &Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1310"/> @@ -1665,12 +1632,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1325"/> <source>&Profiles</source> - <translation type="unfinished">&é…置文件</translation> + <translation>&é…置文件</translation> </message> <message> <location filename="mainwindow.ui" line="1328"/> <source>Configure Profiles</source> - <translation type="unfinished">设置é…置文件</translation> + <translation>设置é…置文件</translation> </message> <message> <location filename="mainwindow.ui" line="1331"/> @@ -1685,7 +1652,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1343"/> <source>&Executables</source> - <translation type="unfinished">&坿‰§è¡Œç¨‹åº</translation> + <translation>&坿‰§è¡Œç¨‹åº</translation> </message> <message> <location filename="mainwindow.ui" line="1346"/> @@ -1706,7 +1673,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1361"/> <source>&Tools</source> - <translation type="unfinished">工具(&T)</translation> + <translation>&工具</translation> </message> <message> <location filename="mainwindow.ui" line="1367"/> @@ -1721,12 +1688,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="1379"/> <source>&Settings</source> - <translation type="unfinished">&设置</translation> + <translation>&设置</translation> </message> <message> <location filename="mainwindow.ui" line="1382"/> <source>Configure settings and workarounds</source> - <translation type="unfinished">é…置设定和解决方案</translation> + <translation>é…置设定和解决方案</translation> </message> <message> <location filename="mainwindow.ui" line="1385"/> @@ -1750,9 +1717,9 @@ p, li { white-space: pre-wrap; } </message> <message> <location filename="mainwindow.ui" line="1412"/> - <location filename="mainwindow.cpp" line="4646"/> + <location filename="mainwindow.cpp" line="4679"/> <source>Update</source> - <translation type="unfinished">æ›´æ–°</translation> + <translation>æ›´æ–°</translation> </message> <message> <location filename="mainwindow.ui" line="1415"/> @@ -1763,7 +1730,7 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="1427"/> <location filename="mainwindow.cpp" line="573"/> <source>No Problems</source> - <translation type="unfinished">没有问题</translation> + <translation>没有问题</translation> </message> <message> <location filename="mainwindow.ui" line="1430"/> @@ -1794,19 +1761,19 @@ Right now this has very limited functionality</source> </message> <message> <location filename="mainwindow.ui" line="1460"/> - <location filename="mainwindow.cpp" line="4728"/> + <location filename="mainwindow.cpp" line="4761"/> <source>Endorse Mod Organizer</source> <translation>称赞 Mod Organizer</translation> </message> <message> <location filename="mainwindow.ui" line="1465"/> <source>Copy Log to Clipboard</source> - <translation type="unfinished">å¤åˆ¶åˆ°å‰ªè´´æ¿</translation> + <translation>å¤åˆ¶åˆ°å‰ªè´´æ¿</translation> </message> <message> <location filename="mainwindow.ui" line="1468"/> <source>Ctrl+C</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+C</translation> </message> <message> <location filename="mainwindow.cpp" line="255"/> @@ -1826,7 +1793,7 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="561"/> <source>Problems</source> - <translation type="unfinished">问题</translation> + <translation>问题</translation> </message> <message> <location filename="mainwindow.cpp" line="562"/> @@ -1836,17 +1803,17 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="574"/> <source>Everything seems to be in order</source> - <translation type="unfinished">一切井然有åº</translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="635"/> <source>Help on UI</source> - <translation type="unfinished">界é¢å¸®åŠ©</translation> + <translation>界é¢å¸®åŠ©</translation> </message> <message> <location filename="mainwindow.cpp" line="639"/> <source>Documentation Wiki</source> - <translation type="unfinished">说明文档 (维基)</translation> + <translation>说明文档 (维基)</translation> </message> <message> <location filename="mainwindow.cpp" line="643"/> @@ -1861,17 +1828,17 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="686"/> <source>About</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="687"/> <source>About Qt</source> - <translation type="unfinished"></translation> + <translation>关于 Qt</translation> </message> <message> <location filename="mainwindow.cpp" line="782"/> <source>failed to save load order: %1</source> - <translation type="unfinished">æ— æ³•ä¿å˜åŠ è½½é¡ºåº: %1</translation> + <translation>æ— æ³•ä¿å˜åŠ è½½é¡ºåº: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="793"/> @@ -1886,7 +1853,7 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="802"/> <source>failed to create profile: %1</source> - <translation type="unfinished">æ— æ³•åˆ›å»ºé…置文件: %1</translation> + <translation>æ— æ³•åˆ›å»ºé…置文件: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="843"/> @@ -1911,43 +1878,60 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="930"/> <source>failed to read savegame: %1</source> - <translation type="unfinished">æ— æ³•è¯»å–å˜æ¡£: %1</translation> + <translation>æ— æ³•è¯»å–å˜æ¡£: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="1053"/> <source>Plugin "%1" failed: %2</source> - <translation type="unfinished">æ’ä»¶ "%1" 失败: %2</translation> + <translation>æ’ä»¶ "%1" 失败: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1055"/> <source>Plugin "%1" failed</source> - <translation type="unfinished">æ’ä»¶ "%1" 失败</translation> + <translation>æ’ä»¶ "%1" 失败</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1098"/> + <source>Download?</source> + <translation>下载?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1099"/> + <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"/> + </message> + <message> + <location filename="mainwindow.cpp" line="1140"/> + <source>Browse Mod Page</source> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="1225"/> <source>failed to init plugin %1: %2</source> - <translation type="unfinished">æ’ä»¶åˆå§‹åŒ–失败 %1: %2</translation> + <translation>æ’ä»¶åˆå§‹åŒ–失败 %1: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1263"/> <source>Plugin error</source> - <translation type="unfinished"></translation> + <translation>æ’件错误</translation> </message> <message> <location filename="mainwindow.cpp" line="1264"/> <source>It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="1323"/> <source>Failed to start "%1"</source> - <translation type="unfinished">æ— æ³•å¯åЍ "%1"</translation> + <translation>æ— æ³•å¯åЍ "%1"</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> <source>Waiting</source> - <translation type="unfinished">ç¨ç‰</translation> + <translation>ç¨ç‰</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> @@ -1955,6 +1939,11 @@ Right now this has very limited functionality</source> <translation>当您登录 Steam 时请点击确定。</translation> </message> <message> + <location filename="mainwindow.cpp" line="1337"/> + <source>Executable "%1" not found</source> + <translation>坿‰§è¡Œç¨‹åº "%1" 未找到</translation> + </message> + <message> <location filename="mainwindow.cpp" line="1351"/> <source>Start Steam?</source> <translation>å¯åЍ Steam?</translation> @@ -1965,912 +1954,888 @@ Right now this has very limited functionality</source> <translation>æƒ³è¦æ£ç¡®åœ°å¯åŠ¨æ¸¸æˆï¼ŒSteam 必须处于è¿è¡Œçжæ€ã€‚需è¦MOå°è¯•å¯åЍ Steam å—?</translation> </message> <message> - <location filename="mainwindow.cpp" line="1562"/> + <location filename="mainwindow.cpp" line="1572"/> <source>Also in: <br></source> - <translation type="unfinished">也在: <br></translation> + <translation>也在: <br></translation> </message> <message> - <location filename="mainwindow.cpp" line="1573"/> + <location filename="mainwindow.cpp" line="1583"/> <source>No conflict</source> <translation>没有冲çª</translation> </message> <message> - <location filename="mainwindow.cpp" line="1742"/> + <location filename="mainwindow.cpp" line="1752"/> <source><Edit...></source> - <translation type="unfinished"><编辑...></translation> + <translation><编辑...></translation> </message> <message> - <location filename="mainwindow.cpp" line="2008"/> + <location filename="mainwindow.cpp" line="1849"/> + <source>Failed to refresh list of esps: %1</source> + <translation>æ— æ³•åˆ·æ–° esp 列表 : %1</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2025"/> <source>This bsa is enabled in the ini file so it may be required!</source> <translation>该 BSA 已在 ini 文件ä¸å¯ç”¨ï¼Œå› æ¤å®ƒå¯èƒ½æ˜¯å¿…需的。</translation> </message> <message> - <location filename="mainwindow.cpp" line="2070"/> + <location filename="mainwindow.cpp" line="2087"/> <source>Activating Network Proxy</source> <translation>激活网络代ç†</translation> </message> <message> - <location filename="mainwindow.cpp" line="2310"/> - <location filename="mainwindow.cpp" line="4349"/> - <source>Installation successful</source> - <translation>安装æˆåŠŸ</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2321"/> - <location filename="mainwindow.cpp" line="4361"/> - <source>Configure Mod</source> - <translation>é…ç½® Mod</translation> + <location filename="mainwindow.cpp" line="2201"/> + <location filename="mainwindow.cpp" line="2208"/> + <source>Failed to write settings</source> + <translation>æ— æ³•å†™å…¥è®¾ç½®</translation> </message> <message> - <location filename="mainwindow.cpp" line="2322"/> - <location filename="mainwindow.cpp" line="4362"/> - <source>This mod contains ini tweaks. Do you want to configure them now?</source> - <translation>æ¤ Mod ä¸åŒ…å« ini 设定文件,您想现在就对它们进行é…ç½®å—?</translation> + <location filename="mainwindow.cpp" line="2202"/> + <location filename="mainwindow.cpp" line="2209"/> + <source>An error occured trying to write back MO settings: %1</source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2329"/> - <location filename="mainwindow.cpp" line="4369"/> - <source>mod "%1" not found</source> - <translation type="unfinished">Mod "%1" 未找到</translation> + <location filename="mainwindow.cpp" line="2205"/> + <source>File is write protected</source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>Installation cancelled</source> - <translation>å®‰è£…å·²å–æ¶ˆ</translation> + <location filename="mainwindow.cpp" line="2206"/> + <source>Invalid file format (probably a bug)</source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>The mod was not installed completely.</source> - <translation>该模组没有完全安装。</translation> + <location filename="mainwindow.cpp" line="2207"/> + <source>Unknown error %1</source> + <translation>未知错误 %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2237"/> + <location filename="mainwindow.cpp" line="2254"/> <source>Some plugins could not be loaded</source> <translation>一些æ’ä»¶æ— æ³•è½½å…¥</translation> </message> <message> - <location filename="mainwindow.cpp" line="2240"/> + <location filename="mainwindow.cpp" line="2257"/> <source>Too many esps and esms enabled</source> - <translation type="unfinished"></translation> + <translation>esp å’Œ esm å¼€å¯å¤ªå¤š</translation> </message> <message> - <location filename="mainwindow.cpp" line="2243"/> - <location filename="mainwindow.cpp" line="2264"/> + <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2281"/> <source>Description missing</source> - <translation type="unfinished"></translation> + <translation>æè¿°ä¸¢å¤±</translation> </message> <message> - <location filename="mainwindow.cpp" line="2252"/> + <location filename="mainwindow.cpp" line="2269"/> <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> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2277"/> <source>The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2286"/> + <location filename="mainwindow.cpp" line="2303"/> <source>Choose Mod</source> <translation>选择模组</translation> </message> <message> - <location filename="mainwindow.cpp" line="2287"/> + <location filename="mainwindow.cpp" line="2304"/> <source>Mod Archive</source> - <translation type="unfinished">Mod 压缩包</translation> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="2327"/> + <location filename="mainwindow.cpp" line="4382"/> + <source>Installation successful</source> + <translation>安装æˆåŠŸ</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2338"/> + <location filename="mainwindow.cpp" line="4394"/> + <source>Configure Mod</source> + <translation>é…ç½® Mod</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2339"/> + <location filename="mainwindow.cpp" line="4395"/> + <source>This mod contains ini tweaks. Do you want to configure them now?</source> + <translation>æ¤ Mod ä¸åŒ…å« ini 设定文件,您想现在就对它们进行é…ç½®å—?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2346"/> + <location filename="mainwindow.cpp" line="4402"/> + <source>mod "%1" not found</source> + <translation>Mod "%1" 未找到</translation> </message> <message> - <location filename="mainwindow.cpp" line="2541"/> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>Installation cancelled</source> + <translation>å®‰è£…å·²å–æ¶ˆ</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>The mod was not installed completely.</source> + <translation>该模组没有完全安装。</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2558"/> <source>Start Tutorial?</source> <translation>开始教程?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2542"/> + <location filename="mainwindow.cpp" line="2559"/> <source>You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue?</source> <translation>å³å°†å¼€å§‹å¸®åŠ©æ•™ç¨‹ã€‚å› ä¸ºæŠ€æœ¯åŽŸå› å¯èƒ½æ— æ³•éšæ—¶ä¸æ–。是å¦ç»§ç»ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="2686"/> - <location filename="mainwindow.cpp" line="4274"/> + <location filename="mainwindow.cpp" line="2703"/> + <location filename="mainwindow.cpp" line="4307"/> <source>Download started</source> <translation>开始下载</translation> </message> <message> - <location filename="mainwindow.cpp" line="2747"/> + <location filename="mainwindow.cpp" line="2764"/> <source>failed to update mod list: %1</source> - <translation type="unfinished">æ— æ³•æ›´æ–° Mod 列表: %1</translation> + <translation>æ— æ³•æ›´æ–° Mod 列表: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2791"/> + <location filename="mainwindow.cpp" line="2808"/> <source>failed to spawn notepad.exe: %1</source> - <translation type="unfinished">æ— æ³•ç”Ÿæˆ notepad.exe: %1</translation> + <translation>æ— æ³•ç”Ÿæˆ notepad.exe: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2828"/> + <location filename="mainwindow.cpp" line="2845"/> <source>failed to open %1</source> - <translation type="unfinished">æ— æ³•æ‰“å¼€ %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2903"/> + <location filename="mainwindow.cpp" line="2920"/> <source>failed to change origin name: %1</source> - <translation type="unfinished">æ— æ³•æ›´æ”¹åŽŸå§‹æ–‡ä»¶å: %1</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1337"/> - <source>Executable "%1" not found</source> - <translation type="unfinished"></translation> + <translation>æ— æ³•æ›´æ”¹åŽŸå§‹æ–‡ä»¶å: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="1839"/> - <source>Failed to refresh list of esps: %1</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2950"/> + <source>failed to move "%1" from mod "%2" to "%3": %4</source> + <translation>æ— æ³•ç§»åŠ¨ "%1" 从 mod "%2" 到 "%3": %4</translation> </message> <message> - <location filename="mainwindow.cpp" line="2933"/> - <source>failed to move "%1" from mod "%2" to "%3": %4</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2973"/> + <source><Contains %1></source> + <translation><Contains %1></translation> </message> <message> - <location filename="mainwindow.cpp" line="2983"/> + <location filename="mainwindow.cpp" line="3006"/> <source><Checked></source> - <translation type="unfinished"><已勾选></translation> + <translation><Checked></translation> </message> <message> - <location filename="mainwindow.cpp" line="2984"/> + <location filename="mainwindow.cpp" line="3007"/> <source><Unchecked></source> - <translation type="unfinished"><未勾选></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2985"/> + <location filename="mainwindow.cpp" line="3008"/> <source><Update></source> - <translation type="unfinished"><有更新></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2988"/> + <location filename="mainwindow.cpp" line="3009"/> + <source><Managed by MO></source> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="3010"/> + <source><Managed outside MO></source> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="3011"/> <source><No category></source> - <translation type="unfinished"><æ— ç±»åˆ«></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2989"/> + <location filename="mainwindow.cpp" line="3012"/> <source><Conflicted></source> - <translation type="unfinished"><有冲çª></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2990"/> + <location filename="mainwindow.cpp" line="3013"/> <source><Not Endorsed></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3026"/> + <location filename="mainwindow.cpp" line="3051"/> <source>failed to rename mod: %1</source> - <translation type="unfinished">æ— æ³•é‡å‘½å Mod: %1</translation> + <translation>æ— æ³•é‡å‘½å Mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3039"/> + <location filename="mainwindow.cpp" line="3064"/> <source>Overwrite?</source> <translation>覆盖</translation> </message> <message> - <location filename="mainwindow.cpp" line="3040"/> + <location filename="mainwindow.cpp" line="3065"/> <source>This will replace the existing mod "%1". Continue?</source> - <translation type="unfinished">这将会覆盖已å˜åœ¨çš„mod "%1"。是å¦ç»§ç»ï¼Ÿ</translation> + <translation>这将会覆盖已å˜åœ¨çš„mod "%1"。是å¦ç»§ç»ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3043"/> + <location filename="mainwindow.cpp" line="3068"/> <source>failed to remove mod "%1"</source> - <translation type="unfinished">æ— æ³•ç§»åŠ¨ Mod: %1</translation> + <translation>æ— æ³•ç§»åŠ¨ mod %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3047"/> - <location filename="mainwindow.cpp" line="4547"/> - <location filename="mainwindow.cpp" line="4571"/> + <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="4580"/> + <location filename="mainwindow.cpp" line="4604"/> <source>failed to rename "%1" to "%2"</source> <translation>é‡å‘½å "%1 "为 "%2" 时出错</translation> </message> <message> - <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="3097"/> <source>Multiple esps activated, please check that they don't conflict.</source> <translation>多个esp已激活,请检查以确ä¿ä¸å†²çªã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="3121"/> - <location filename="mainwindow.cpp" line="3746"/> - <location filename="mainwindow.cpp" line="3754"/> - <location filename="mainwindow.cpp" line="3981"/> + <location filename="mainwindow.cpp" line="3146"/> + <location filename="mainwindow.cpp" line="3771"/> + <location filename="mainwindow.cpp" line="3779"/> + <location filename="mainwindow.cpp" line="4014"/> <source>Confirm</source> <translation>确认</translation> </message> <message> - <location filename="mainwindow.cpp" line="3122"/> + <location filename="mainwindow.cpp" line="3147"/> <source>Remove the following mods?<br><ul>%1</ul></source> - <translation type="unfinished">是å¦åˆ 除下列mod?<br><ul>%1</ul></translation> + <translation>是å¦åˆ 除下列mod?<br><ul>%1</ul></translation> </message> <message> - <location filename="mainwindow.cpp" line="3133"/> + <location filename="mainwindow.cpp" line="3158"/> <source>failed to remove mod: %1</source> - <translation type="unfinished">æ— æ³•ç§»åŠ¨ Mod: %1</translation> + <translation>æ— æ³•ç§»åŠ¨ Mod: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> - <location filename="mainwindow.cpp" line="3171"/> + <location filename="mainwindow.cpp" line="3193"/> + <location filename="mainwindow.cpp" line="3196"/> <source>Failed</source> - <translation type="unfinished">失败</translation> + <translation>失败</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> + <location filename="mainwindow.cpp" line="3193"/> <source>Installation file no longer exists</source> - <translation type="unfinished">安装文件ä¸å¤å˜åœ¨</translation> + <translation>安装文件ä¸å¤å˜åœ¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="3172"/> + <location filename="mainwindow.cpp" line="3197"/> <source>Mods installed with old versions of MO can't be reinstalled in this way.</source> - <translation type="unfinished">旧版 MO 安装的 Mod æ— æ³•ä½¿ç”¨æ¤æ–¹æ³•釿–°å®‰è£…。</translation> + <translation>旧版 MO 安装的 Mod æ— æ³•ä½¿ç”¨æ¤æ–¹æ³•釿–°å®‰è£…。</translation> </message> <message> - <location filename="mainwindow.cpp" line="3203"/> - <location filename="mainwindow.cpp" line="3230"/> - <source>You need to be logged in with Nexus to endorse</source> + <location filename="mainwindow.cpp" line="3212"/> + <source>You need to be logged in with Nexus to resume a download</source> <translation>ä½ å¿…é¡»ç™»å½• Nexus æ‰èƒ½ç‚¹â€œç§°èµžâ€</translation> </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="3981"/> - <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> - <translation type="unfinished"> - <numerusform></numerusform> - </translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="4095"/> - <source>Delete %n save(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - </translation> - </message> - <message> - <location filename="mainwindow.cpp" line="4974"/> - <source>Extract BSA</source> - <translation>解压 BSA</translation> - </message> <message> - <location filename="mainwindow.cpp" line="4931"/> - <location filename="mainwindow.cpp" line="4982"/> - <source>failed to read %1: %2</source> - <translation type="unfinished">æ— æ³•è¯»å– %1: %2</translation> + <location filename="mainwindow.cpp" line="3228"/> + <location filename="mainwindow.cpp" line="3255"/> + <source>You need to be logged in with Nexus to endorse</source> + <translation>ä½ å¿…é¡»ç™»å½• Nexus æ‰èƒ½ç‚¹â€œç§°èµžâ€</translation> </message> <message> - <location filename="mainwindow.cpp" line="4993"/> - <source>This archive contains invalid hashes. Some files may be broken.</source> - <translation type="unfinished">压缩包 Hash 值错误。部分文件å¯èƒ½å·²ç»æŸå。</translation> + <location filename="mainwindow.cpp" line="3289"/> + <source>Failed to display overwrite dialog: %1</source> + <translation>æ— æ³•æ˜¾ç¤º overwrite 对è¯: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3382"/> + <location filename="mainwindow.cpp" line="3407"/> <source>Nexus ID for this Mod is unknown</source> <translation>æ¤æ¨¡ç»„çš„Nexus ID未知</translation> </message> <message> - <location filename="mainwindow.cpp" line="1098"/> - <source>Download?</source> - <translation type="unfinished">下载</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1099"/> - <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="mainwindow.cpp" line="1140"/> - <source>Browse Mod Page</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2184"/> - <location filename="mainwindow.cpp" line="2191"/> - <source>Failed to write settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2185"/> - <location filename="mainwindow.cpp" line="2192"/> - <source>An error occured trying to write back MO settings: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2188"/> - <source>File is write protected</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2189"/> - <source>Invalid file format (probably a bug)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2190"/> - <source>Unknown error %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2986"/> - <source><Managed by MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2987"/> - <source><Managed outside MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3187"/> - <source>You need to be logged in with Nexus to resume a download</source> - <translation type="unfinished">ä½ å¿…é¡»ç™»å½• Nexus æ‰èƒ½ç‚¹â€œç§°èµžâ€</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3264"/> - <source>Failed to display overwrite dialog: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3421"/> - <location filename="mainwindow.cpp" line="3861"/> + <location filename="mainwindow.cpp" line="3446"/> + <location filename="mainwindow.cpp" line="3886"/> <source>Create Mod...</source> <translation>创建Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3422"/> + <location filename="mainwindow.cpp" line="3447"/> <source>This will move all files from overwrite into a new, regular mod. Please enter a name:</source> - <translation type="unfinished"></translation> + <translation>这会移动所有的 overwirite 文件æˆä¸ºä¸€ä¸ªæ–°å»ºçš„ mod。 +请输入åç§°:</translation> </message> <message> - <location filename="mainwindow.cpp" line="3431"/> + <location filename="mainwindow.cpp" line="3456"/> <source>A mod with this name already exists</source> <translation>åŒå模组已å˜åœ¨ã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="3672"/> + <location filename="mainwindow.cpp" line="3697"/> <source>Continue?</source> - <translation type="unfinished"></translation> + <translation>ç»§ç»ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3673"/> + <location filename="mainwindow.cpp" line="3698"/> <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> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3693"/> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="3718"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry</source> - <translation type="unfinished"></translation> + <translation>抱æ‰</translation> </message> <message> - <location filename="mainwindow.cpp" line="3694"/> + <location filename="mainwindow.cpp" line="3719"/> <source>I don't know a versioning scheme where %1 is newer than %2.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3746"/> + <location filename="mainwindow.cpp" line="3771"/> <source>Really enable all visible mods?</source> <translation>确定è¦å¯ç”¨å…¨éƒ¨å¯è§çš„æ¨¡ç»„å—?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3754"/> + <location filename="mainwindow.cpp" line="3779"/> <source>Really disable all visible mods?</source> <translation>确定è¦ç¦ç”¨å…¨éƒ¨å¯è§çš„æ¨¡ç»„å—?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3762"/> + <location filename="mainwindow.cpp" line="3787"/> <source>Choose what to export</source> <translation>选择è¦å¯¼å‡ºçš„内容</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>Everything</source> - <translation type="unfinished">全部</translation> + <translation>全部</translation> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>All installed mods are included in the list</source> - <translation type="unfinished">所有包å«åœ¨åˆ—表的已安装mod</translation> + <translation>所有包å«åœ¨åˆ—表的已安装mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Active Mods</source> <translation>激活模组</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Only active (checked) mods from your current profile are included</source> <translation>仅包å«å½“å‰é…置文件ä¸å·²æ¿€æ´»ï¼ˆæ‰“勾)的mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>Visible</source> - <translation type="unfinished">å¯è§çš„</translation> + <translation>å¯è§çš„</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>All mods visible in the mod list are included</source> - <translation type="unfinished">包å«åˆ—è¡¨ä¸æ‰€æœ‰å¯è§çš„mod</translation> + <translation>包å«åˆ—è¡¨ä¸æ‰€æœ‰å¯è§çš„mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3809"/> + <location filename="mainwindow.cpp" line="3834"/> <source>export failed: %1</source> - <translation type="unfinished">导出失败: %1</translation> + <translation>导出失败: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3826"/> + <location filename="mainwindow.cpp" line="3851"/> <source>Install Mod...</source> <translation>安装模组...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3828"/> + <location filename="mainwindow.cpp" line="3853"/> <source>Enable all visible</source> <translation>å¯ç”¨æ‰€æœ‰å¯è§é¡¹ç›®</translation> </message> <message> - <location filename="mainwindow.cpp" line="3829"/> + <location filename="mainwindow.cpp" line="3854"/> <source>Disable all visible</source> <translation>ç¦ç”¨æ‰€æœ‰å¯è§é¡¹ç›®</translation> </message> <message> - <location filename="mainwindow.cpp" line="3831"/> + <location filename="mainwindow.cpp" line="3856"/> <source>Check all for update</source> <translation>检查所有更新</translation> </message> <message> - <location filename="mainwindow.cpp" line="3835"/> + <location filename="mainwindow.cpp" line="3860"/> <source>Export to csv...</source> <translation>导出为 CSV...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3854"/> + <location filename="mainwindow.cpp" line="3879"/> <source>All Mods</source> - <translation type="unfinished"></translation> + <translation>所有模组</translation> </message> <message> - <location filename="mainwindow.cpp" line="3860"/> + <location filename="mainwindow.cpp" line="3885"/> <source>Sync to Mods...</source> - <translation type="unfinished">åŒæ¥åˆ° Mod...</translation> + <translation>åŒæ¥åˆ°æ¨¡ç»„...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3864"/> + <location filename="mainwindow.cpp" line="3889"/> <source>Restore Backup</source> <translation>还原备份</translation> </message> <message> - <location filename="mainwindow.cpp" line="3865"/> + <location filename="mainwindow.cpp" line="3890"/> <source>Remove Backup...</source> - <translation type="unfinished">还原备份...</translation> + <translation>移除备份</translation> </message> <message> - <location filename="mainwindow.cpp" line="3869"/> + <location filename="mainwindow.cpp" line="3894"/> <source>Add/Remove Categories</source> - <translation type="unfinished"></translation> + <translation>æ·»åŠ /移除 类别</translation> </message> <message> - <location filename="mainwindow.cpp" line="3874"/> + <location filename="mainwindow.cpp" line="3899"/> <source>Replace Categories</source> - <translation type="unfinished"></translation> + <translation>æ›´æ¢ç±»åˆ«</translation> </message> <message> - <location filename="mainwindow.cpp" line="3879"/> + <location filename="mainwindow.cpp" line="3904"/> <source>Primary Category</source> <translation>主分类</translation> </message> <message> - <location filename="mainwindow.cpp" line="3886"/> + <location filename="mainwindow.cpp" line="3911"/> <source>Change versioning scheme</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3890"/> + <location filename="mainwindow.cpp" line="3915"/> <source>Un-ignore update</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3892"/> + <location filename="mainwindow.cpp" line="3917"/> <source>Ignore update</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3897"/> + <location filename="mainwindow.cpp" line="3922"/> <source>Rename Mod...</source> <translation>é‡å‘½å模组...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3898"/> + <location filename="mainwindow.cpp" line="3923"/> <source>Remove Mod...</source> <translation>移除模组...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3899"/> + <location filename="mainwindow.cpp" line="3924"/> <source>Reinstall Mod</source> <translation>釿–°å®‰è£…模组</translation> </message> <message> - <location filename="mainwindow.cpp" line="3902"/> + <location filename="mainwindow.cpp" line="3927"/> <source>Un-Endorse</source> <translation>å–æ¶ˆç§°èµž</translation> </message> <message> - <location filename="mainwindow.cpp" line="3905"/> - <location filename="mainwindow.cpp" line="3909"/> + <location filename="mainwindow.cpp" line="3930"/> + <location filename="mainwindow.cpp" line="3934"/> <source>Endorse</source> <translation>称赞</translation> </message> <message> - <location filename="mainwindow.cpp" line="3906"/> + <location filename="mainwindow.cpp" line="3931"/> <source>Won't endorse</source> <translation>䏿ƒ³ç§°èµž</translation> </message> <message> - <location filename="mainwindow.cpp" line="3912"/> + <location filename="mainwindow.cpp" line="3937"/> <source>Endorsement state unknown</source> <translation>称赞状æ€ä¸æ˜Ž</translation> </message> <message> - <location filename="mainwindow.cpp" line="3919"/> + <location filename="mainwindow.cpp" line="3944"/> <source>Ignore missing data</source> <translation>忽略丢失的数æ®</translation> </message> <message> - <location filename="mainwindow.cpp" line="3922"/> + <location filename="mainwindow.cpp" line="3947"/> <source>Visit on Nexus</source> <translation>在Nexus上æµè§ˆ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3923"/> + <location filename="mainwindow.cpp" line="3948"/> <source>Open in explorer</source> <translation>在资æºç®¡ç†å™¨ä¸æ‰“å¼€</translation> </message> <message> - <location filename="mainwindow.cpp" line="3927"/> + <location filename="mainwindow.cpp" line="3952"/> <source>Information...</source> - <translation type="unfinished">ä¿¡æ¯...</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3934"/> - <location filename="mainwindow.cpp" line="5192"/> + <location filename="mainwindow.cpp" line="3959"/> + <location filename="mainwindow.cpp" line="5225"/> <source>Exception: </source> - <translation type="unfinished">例外: </translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3936"/> - <location filename="mainwindow.cpp" line="5194"/> + <location filename="mainwindow.cpp" line="3961"/> + <location filename="mainwindow.cpp" line="5227"/> <source>Unknown exception</source> - <translation type="unfinished">未知的例外</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3955"/> + <location filename="mainwindow.cpp" line="3988"/> <source><All></source> - <translation type="unfinished"><全部></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3957"/> + <location filename="mainwindow.cpp" line="3990"/> <source><Multiple></source> - <translation type="unfinished">XX</translation> + <translation type="unfinished"/> + </message> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4014"/> + <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> + <translation type="unfinished"><numerusform></numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="5450"/> + <location filename="mainwindow.cpp" line="5483"/> <source>Please wait while LOOT is running</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4093"/> + <location filename="mainwindow.cpp" line="4126"/> <source>Fix Mods...</source> <translation>ä¿®å¤æ¨¡ç»„...</translation> </message> - <message> - <source>Delete</source> - <translation type="obsolete">&åˆ é™¤</translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4128"/> + <source>Delete %n save(s)</source> + <translation type="unfinished"><numerusform></numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="4122"/> <location filename="mainwindow.cpp" line="4155"/> + <location filename="mainwindow.cpp" line="4188"/> <source>failed to remove %1</source> - <translation type="unfinished">æ— æ³•åˆ é™¤ %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4139"/> - <location filename="mainwindow.cpp" line="4171"/> + <location filename="mainwindow.cpp" line="4172"/> + <location filename="mainwindow.cpp" line="4204"/> <source>failed to create %1</source> - <translation type="unfinished">æ— æ³•åˆ›å»º %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4195"/> + <location filename="mainwindow.cpp" line="4228"/> <source>Can't change download directory while downloads are in progress!</source> <translation>下载文件时ä¸èƒ½ä¿®æ”¹ä¸‹è½½ç›®å½•ï¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4277"/> + <location filename="mainwindow.cpp" line="4310"/> <source>Download failed</source> <translation>下载失败</translation> </message> <message> - <location filename="mainwindow.cpp" line="4424"/> + <location filename="mainwindow.cpp" line="4457"/> <source>failed to write to file %1</source> - <translation type="unfinished">æ— æ³•å†™å…¥æ–‡ä»¶ %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4430"/> + <location filename="mainwindow.cpp" line="4463"/> <source>%1 written</source> - <translation type="unfinished">已写入 %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Select binary</source> - <translation type="unfinished">é€‰æ‹©å¯æ‰§è¡Œæ–‡ä»¶</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Binary</source> <translation>程åº</translation> </message> <message> - <location filename="mainwindow.cpp" line="4495"/> + <location filename="mainwindow.cpp" line="4528"/> <source>Enter Name</source> <translation>输入åç§°</translation> </message> <message> - <location filename="mainwindow.cpp" line="4496"/> + <location filename="mainwindow.cpp" line="4529"/> <source>Please enter a name for the executable</source> <translation>è¯·ä¸ºè¯¥å¯æ‰§è¡Œç¨‹åºè¾“入一个åç§°</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>Not an executable</source> - <translation type="unfinished">䏿˜¯å¯æ‰§è¡Œç¨‹åº</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>This is not a recognized executable.</source> - <translation type="unfinished">æ— æ³•è¯†åˆ«çš„å¯æ‰§è¡Œæ–‡ä»¶</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4565"/> + <location filename="mainwindow.cpp" line="4590"/> <source>Replace file?</source> - <translation type="unfinished">æ›¿æ¢æ–‡ä»¶ï¼Ÿ</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> + <location filename="mainwindow.cpp" line="4565"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå文件,但该文件被éšè—了。确定è¦è¦†ç›–å—?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>File operation failed</source> <translation>文件æ“作错误</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>æ— æ³•ç§»é™¤ "%1"。也许您需è¦è¶³å¤Ÿçš„æ–‡ä»¶æƒé™ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4590"/> <source>There already is a visible version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå文件。确定è¦è¦†ç›–å—?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4590"/> + <location filename="mainwindow.cpp" line="4623"/> <source>file not found: %1</source> - <translation type="unfinished">esp未找到:%1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4603"/> + <location filename="mainwindow.cpp" line="4636"/> <source>failed to generate preview for %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry, can't preview anything. This function currently does not support extracting from bsas.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4648"/> + <location filename="mainwindow.cpp" line="4681"/> <source>Update available</source> <translation>æ›´æ–°å¯ç”¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="4685"/> + <location filename="mainwindow.cpp" line="4718"/> <source>Open/Execute</source> <translation>打开/执行</translation> </message> <message> - <location filename="mainwindow.cpp" line="4686"/> + <location filename="mainwindow.cpp" line="4719"/> <source>Add as Executable</source> <translation>æ·»åŠ ä¸ºå¯æ‰§è¡Œæ–‡ä»¶</translation> </message> <message> - <location filename="mainwindow.cpp" line="4690"/> + <location filename="mainwindow.cpp" line="4723"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4696"/> + <location filename="mainwindow.cpp" line="4729"/> <source>Un-Hide</source> <translation>å–æ¶ˆéšè—</translation> </message> <message> - <location filename="mainwindow.cpp" line="4698"/> + <location filename="mainwindow.cpp" line="4731"/> <source>Hide</source> <translation>éšè—</translation> </message> <message> - <location filename="mainwindow.cpp" line="4704"/> + <location filename="mainwindow.cpp" line="4737"/> <source>Write To File...</source> - <translation type="unfinished">写入文件...</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4729"/> + <location filename="mainwindow.cpp" line="4762"/> <source>Do you want to endorse Mod Organizer on %1 now?</source> - <translation type="unfinished">是å¦çŽ°åœ¨å°±åœ¨ %1 ç‚¹èµžæ”¯æŒ Mod Organizer?</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you!</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you for your endorsement!</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4860"/> + <location filename="mainwindow.cpp" line="4893"/> <source>Request to Nexus failed: %1</source> - <translation type="unfinished">å‘å¾€ Nexus 的请求失败: %1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4867"/> - <location filename="mainwindow.cpp" line="4885"/> + <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4918"/> <source>login successful</source> <translation>登录æˆåŠŸ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4894"/> + <location filename="mainwindow.cpp" line="4927"/> <source>login failed: %1. Trying to download anyway</source> - <translation type="unfinished">登录失败: %1,请å°è¯•使用别的方法下载</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4933"/> <source>login failed: %1</source> <translation>æ— æ³•ç™»å½•: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4910"/> + <location filename="mainwindow.cpp" line="4943"/> <source>login failed: %1. You need to log-in with Nexus to update MO.</source> - <translation type="unfinished">登录失败: %1。您需è¦ç™»å½•到N网æ‰èƒ½æ›´æ–° MO</translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4964"/> + <location filename="mainwindow.cpp" line="5015"/> + <source>failed to read %1: %2</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="4976"/> <source>Error</source> <translation>错误</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4976"/> <source>failed to extract %1 (errorcode %2)</source> - <translation type="unfinished">æ— æ³•è§£åŽ‹ %1 (错误代ç %2)</translation> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="5007"/> + <source>Extract BSA</source> + <translation>解压 BSA</translation> </message> <message> - <location filename="mainwindow.cpp" line="5038"/> + <location filename="mainwindow.cpp" line="5026"/> + <source>This archive contains invalid hashes. Some files may be broken.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="mainwindow.cpp" line="5071"/> <source>Extract...</source> <translation>解压...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5100"/> + <location filename="mainwindow.cpp" line="5133"/> <source>Edit Categories...</source> <translation>编辑类别...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5101"/> + <location filename="mainwindow.cpp" line="5134"/> <source>Deselect filter</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5152"/> + <location filename="mainwindow.cpp" line="5185"/> <source>Remove</source> <translation>移除</translation> </message> <message> - <location filename="mainwindow.cpp" line="5163"/> + <location filename="mainwindow.cpp" line="5196"/> <source>Enable all</source> <translation>全部å¯ç”¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="5164"/> + <location filename="mainwindow.cpp" line="5197"/> <source>Disable all</source> <translation>全部ç¦ç”¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="5183"/> + <location filename="mainwindow.cpp" line="5216"/> <source>Unlock load order</source> <translation>è§£é”åŠ è½½é¡ºåº</translation> </message> <message> - <location filename="mainwindow.cpp" line="5186"/> + <location filename="mainwindow.cpp" line="5219"/> <source>Lock load order</source> <translation>é”å®šåŠ è½½é¡ºåº</translation> </message> <message> - <location filename="mainwindow.cpp" line="5319"/> + <location filename="mainwindow.cpp" line="5352"/> <source>depends on missing "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5323"/> + <location filename="mainwindow.cpp" line="5356"/> <source>incompatible with "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5343"/> + <location filename="mainwindow.cpp" line="5376"/> <source>No profile set</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5540"/> + <location filename="mainwindow.cpp" line="5573"/> <source>loot failed. Exit code was: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5546"/> + <location filename="mainwindow.cpp" line="5579"/> <source>failed to start loot</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5549"/> + <location filename="mainwindow.cpp" line="5582"/> <source>failed to run loot: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5552"/> + <location filename="mainwindow.cpp" line="5585"/> <source>Errors occured</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5601"/> + <location filename="mainwindow.cpp" line="5636"/> <source>Backup of load order created</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5611"/> + <location filename="mainwindow.cpp" line="5646"/> <source>Choose backup to restore</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>No Backups</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>There are no backups to restore</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5645"/> - <location filename="mainwindow.cpp" line="5666"/> + <location filename="mainwindow.cpp" line="5680"/> + <location filename="mainwindow.cpp" line="5701"/> <source>Restore failed</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5646"/> - <location filename="mainwindow.cpp" line="5667"/> + <location filename="mainwindow.cpp" line="5681"/> + <location filename="mainwindow.cpp" line="5702"/> <source>Failed to restore the backup. Errorcode: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5657"/> + <location filename="mainwindow.cpp" line="5692"/> <source>Backup of modlist created</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -2885,8 +2850,63 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfo</name> <message> - <location filename="modinfo.cpp" line="106"/> - <location filename="modinfo.cpp" line="135"/> + <location filename="modinfo.cpp" line="87"/> + <source>Plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="88"/> + <source>Textures</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="89"/> + <source>Meshes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="90"/> + <source>UI Changes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="91"/> + <source>Music</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="92"/> + <source>Sound Effects</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="93"/> + <source>Scripts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="94"/> + <source>SKSE Plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="95"/> + <source>SkyProc Tools</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="96"/> + <source>Strings</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="97"/> + <source>invalid content type %1</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="120"/> + <location filename="modinfo.cpp" line="149"/> <source>invalid index %1</source> <translation>æ— æ•ˆçš„ç´¢å¼• %1</translation> </message> @@ -2894,7 +2914,7 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfoBackup</name> <message> - <location filename="modinfo.cpp" line="930"/> + <location filename="modinfo.cpp" line="949"/> <source>This is the backup of a mod</source> <translation>这是模组的备份</translation> </message> @@ -2935,7 +2955,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="91"/> <source>Ini Files</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="104"/> @@ -2950,17 +2970,17 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="114"/> <source>Ini Tweaks</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="130"/> <source>This is a list of ini tweaks (ini modifications that can be toggled).</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="133"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="169"/> @@ -2985,7 +3005,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="243"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="276"/> @@ -3004,7 +3024,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="310"/> @@ -3107,7 +3127,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3120,7 +3140,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3153,19 +3173,19 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="724"/> <source>Endorse</source> - <translation type="unfinished">称赞</translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="738"/> <source>Notes</source> - <translation type="unfinished">笔记</translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="748"/> @@ -3182,7 +3202,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3208,264 +3228,264 @@ p, li { white-space: pre-wrap; } <translation>å…³é—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="169"/> + <location filename="modinfodialog.cpp" line="170"/> <source>&Delete</source> <translation>&åˆ é™¤</translation> </message> <message> - <location filename="modinfodialog.cpp" line="170"/> + <location filename="modinfodialog.cpp" line="171"/> <source>&Rename</source> <translation>&é‡å‘½å</translation> </message> <message> - <location filename="modinfodialog.cpp" line="171"/> + <location filename="modinfodialog.cpp" line="172"/> <source>&Hide</source> <translation>&éšè—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="172"/> + <location filename="modinfodialog.cpp" line="173"/> <source>&Unhide</source> <translation>&å–æ¶ˆéšè—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="173"/> + <location filename="modinfodialog.cpp" line="174"/> <source>&Open</source> <translation>&打开</translation> </message> <message> - <location filename="modinfodialog.cpp" line="174"/> + <location filename="modinfodialog.cpp" line="175"/> <source>&New Folder</source> <translation>&新建文件夹</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes?</source> <translation>ä¿å˜æ›´æ”¹å—?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes to "%1"?</source> - <translation type="unfinished">将更改ä¿å˜åˆ°â€œ%1â€å—?</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>File Exists</source> <translation>文件已å˜åœ¨</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>A file with that name exists, please enter a new one</source> <translation>文件åå·²å˜åœ¨ï¼Œè¯·è¾“入其它åç§°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="642"/> + <location filename="modinfodialog.cpp" line="643"/> <source>failed to move file</source> <translation>æ— æ³•ç§»åŠ¨æ–‡ä»¶</translation> </message> <message> - <location filename="modinfodialog.cpp" line="667"/> + <location filename="modinfodialog.cpp" line="668"/> <source>failed to create directory "optional"</source> <translation>æ— æ³•åˆ›å»º "optional" 目录</translation> </message> <message> - <location filename="modinfodialog.cpp" line="705"/> - <location filename="modinfodialog.cpp" line="1210"/> + <location filename="modinfodialog.cpp" line="706"/> + <location filename="modinfodialog.cpp" line="1211"/> <source>Info requested, please wait</source> <translation>请求信æ¯å·²å‘出,请ç¨åŽ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="759"/> + <location filename="modinfodialog.cpp" line="760"/> <source>Main</source> <translation>ä¸»è¦æ–‡ä»¶</translation> </message> <message> - <location filename="modinfodialog.cpp" line="760"/> + <location filename="modinfodialog.cpp" line="761"/> <source>Update</source> <translation>æ›´æ–°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="761"/> + <location filename="modinfodialog.cpp" line="762"/> <source>Optional</source> <translation>å¯é€‰æ–‡ä»¶</translation> </message> <message> - <location filename="modinfodialog.cpp" line="762"/> + <location filename="modinfodialog.cpp" line="763"/> <source>Old</source> <translation>æ—§æ¡£</translation> </message> <message> - <location filename="modinfodialog.cpp" line="763"/> + <location filename="modinfodialog.cpp" line="764"/> <source>Misc</source> <translation>æ‚项</translation> </message> <message> - <location filename="modinfodialog.cpp" line="764"/> + <location filename="modinfodialog.cpp" line="765"/> <source>Unknown</source> <translation>未知</translation> </message> <message> - <location filename="modinfodialog.cpp" line="775"/> + <location filename="modinfodialog.cpp" line="776"/> <source>Current Version: %1</source> <translation>当å‰ç‰ˆæœ¬: %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="779"/> + <location filename="modinfodialog.cpp" line="780"/> <source>No update available</source> <translation>没有å¯ç”¨çš„æ›´æ–°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="820"/> + <location filename="modinfodialog.cpp" line="821"/> <source>(description incomplete, please visit nexus)</source> <translation>(æè¿°ä¿¡æ¯ä¸å®Œæ•´ï¼Œè¯·è®¿é—®N网)</translation> </message> <message> - <location filename="modinfodialog.cpp" line="835"/> + <location filename="modinfodialog.cpp" line="836"/> <source><a href="%1">Visit on Nexus</a></source> <translation><a href="%1">访问N网</a></translation> </message> <message> - <location filename="modinfodialog.cpp" line="914"/> + <location filename="modinfodialog.cpp" line="915"/> <source>Failed to delete %1</source> <translation>æ— æ³•åˆ é™¤ %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="926"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Confirm</source> <translation>确认</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> + <location filename="modinfodialog.cpp" line="926"/> <source>Are sure you want to delete "%1"?</source> <translation>确定è¦åˆ 除 "%1" å—?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Are sure you want to delete the selected files?</source> <translation>确定è¦åˆ 除所选的文件å—?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1004"/> - <location filename="modinfodialog.cpp" line="1010"/> + <location filename="modinfodialog.cpp" line="1005"/> + <location filename="modinfodialog.cpp" line="1011"/> <source>New Folder</source> <translation>新建文件夹</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1016"/> + <location filename="modinfodialog.cpp" line="1017"/> <source>Failed to create "%1"</source> <translation>æ— æ³•åˆ›å»º "%1"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1121"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>Replace file?</source> <translation>æ›¿æ¢æ–‡ä»¶ï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> + <location filename="modinfodialog.cpp" line="1121"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå文件,但该文件被éšè—了。确定è¦è¦†ç›–å—?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>File operation failed</source> <translation>文件æ“作错误</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>æ— æ³•ç§»é™¤ "%1"。也许您需è¦è¶³å¤Ÿçš„æ–‡ä»¶æƒé™ï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1134"/> - <location filename="modinfodialog.cpp" line="1157"/> + <location filename="modinfodialog.cpp" line="1135"/> + <location filename="modinfodialog.cpp" line="1158"/> <source>failed to rename %1 to %2</source> <translation>æ— æ³•é‡å‘½å %1 为 %2</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>There already is a visible version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå文件。确定è¦è¦†ç›–å—?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1190"/> + <location filename="modinfodialog.cpp" line="1191"/> <source>Un-Hide</source> <translation>å–æ¶ˆéšè—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1192"/> + <location filename="modinfodialog.cpp" line="1193"/> <source>Hide</source> <translation>éšè—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Name</source> <translation>åç§°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Please enter a name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1238"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>Error</source> <translation>错误</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> + <location filename="modinfodialog.cpp" line="1238"/> <source>Invalid name. Must be a valid file name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>A tweak by that name exists</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1254"/> + <location filename="modinfodialog.cpp" line="1255"/> <source>Create Tweak</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoForeign</name> <message> - <location filename="modinfo.cpp" line="1021"/> + <location filename="modinfo.cpp" line="1040"/> <source>This pseudo mod represents content managed outside MO. It isn't modified by MO.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoOverwrite</name> <message> - <location filename="modinfo.cpp" line="975"/> + <location filename="modinfo.cpp" line="994"/> <source>This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)</source> - <translation type="unfinished">æ¤è™šæ‹Ÿå®‰è£…åŒ…å†…åŒ…å«æ¥è‡ªè™šæ‹Ÿ Data æ ‘çš„æ–‡ä»¶ï¼Œä½†æ–‡ä»¶å‘生了å˜åŒ– (例: 被CK修改了)</translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoRegular</name> <message> - <location filename="modinfo.cpp" line="567"/> - <location filename="modinfo.cpp" line="570"/> + <location filename="modinfo.cpp" line="586"/> + <location filename="modinfo.cpp" line="589"/> <source>failed to write %1/meta.ini: error %2</source> - <translation type="unfinished">æ— æ³•å†™å…¥ %1/meta.ini: %2</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfo.cpp" line="843"/> + <location filename="modinfo.cpp" line="862"/> <source>%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory</source> - <translation type="unfinished">%1 䏿œªåŒ…å« esp 或 esm 和有效的目录 (textures, meshes, interface, ...)</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfo.cpp" line="847"/> + <location filename="modinfo.cpp" line="866"/> <source>Categories: <br></source> - <translation type="unfinished">ç§ç±»: <br></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3473,52 +3493,52 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="55"/> <source>Game plugins (esp/esm)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="56"/> <source>Interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="57"/> <source>Meshes</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="58"/> <source>Music</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="59"/> <source>Scripts (Papyrus)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="60"/> <source>Script Extender Plugin</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="61"/> <source>SkyProc Patcher</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="62"/> <source>Sound</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="63"/> <source>Strings</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="64"/> <source>Textures</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="117"/> @@ -3543,12 +3563,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="130"/> <source>Overwrites files</source> - <translation type="unfinished">Overwrites文件</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="131"/> <source>Overwritten files</source> - <translation type="unfinished">覆盖的 Mod</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="132"/> @@ -3558,12 +3578,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="133"/> <source>Redundant</source> - <translation type="unfinished">冗余</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="208"/> <source>Non-MO</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="238"/> @@ -3573,13 +3593,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="364"/> <source>installed version: "%1", newest version: "%2"</source> - <oldsource>installed version: %1, newest version: %2</oldsource> - <translation type="unfinished">当å‰ç‰ˆæœ¬: %1,最新版本: %2</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="366"/> <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 "upgrade".</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="374"/> @@ -3594,7 +3613,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="814"/> <source>drag&drop failed: %1</source> - <translation type="unfinished">拖拽失败: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="877"/> @@ -3609,12 +3628,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="934"/> <source>Flags</source> - <translation type="unfinished">æ ‡å¿—</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="935"/> <source>Content</source> - <translation type="unfinished">内容</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="936"/> @@ -3644,7 +3663,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="941"/> <source>Installation</source> - <translation type="unfinished">安装</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="942"/> @@ -3680,17 +3699,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="956"/> <source>Emblemes to highlight things that might require attention.</source> - <translation type="unfinished">éœ€è¦æ³¨æ„è¢«æ ‡è®°ä¸ºé«˜äº®çš„</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="957"/> <source>Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="969"/> <source>Time this mod was installed</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3722,22 +3741,22 @@ p, li { white-space: pre-wrap; } <context> <name>NXMAccessManager</name> <message> - <location filename="nxmaccessmanager.cpp" line="144"/> + <location filename="nxmaccessmanager.cpp" line="152"/> <source>Logging into Nexus</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="nxmaccessmanager.cpp" line="159"/> + <location filename="nxmaccessmanager.cpp" line="167"/> <source>timeout</source> <translation>è¶…æ—¶</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="178"/> + <location filename="nxmaccessmanager.cpp" line="186"/> <source>Unknown error</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="nxmaccessmanager.cpp" line="204"/> + <location filename="nxmaccessmanager.cpp" line="212"/> <source>Please check your password</source> <translation>请检查您的密ç </translation> </message> @@ -3747,7 +3766,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="nexusinterface.cpp" line="216"/> <source>Failed to guess mod id for "%1", please pick the correct one</source> - <translation type="unfinished"> æå–mod "%1"çš„IDç¼–å·å¤±è´¥ï¼Œè¯·è‡ªè¡Œé€‰æ‹©æ£ç¡®é¡¹ã€‚</translation> + <translation type="unfinished"/> </message> <message> <location filename="nexusinterface.cpp" line="482"/> @@ -3795,7 +3814,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="109"/> <source>%1 not found</source> - <translation type="unfinished">找ä¸åˆ° %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="overwriteinfodialog.cpp" line="144"/> @@ -3833,116 +3852,116 @@ p, li { white-space: pre-wrap; } <context> <name>PluginList</name> <message> - <location filename="pluginlist.cpp" line="103"/> + <location filename="pluginlist.cpp" line="104"/> <source>Name</source> <translation>åç§°</translation> </message> <message> - <location filename="pluginlist.cpp" line="104"/> + <location filename="pluginlist.cpp" line="105"/> <source>Priority</source> <translation>优先级</translation> </message> <message> - <location filename="pluginlist.cpp" line="105"/> + <location filename="pluginlist.cpp" line="106"/> <source>Mod Index</source> <translation>Mod 索引</translation> </message> <message> - <location filename="pluginlist.cpp" line="106"/> + <location filename="pluginlist.cpp" line="107"/> <source>Flags</source> - <translation type="unfinished">æ ‡å¿—</translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="107"/> - <location filename="pluginlist.cpp" line="119"/> + <location filename="pluginlist.cpp" line="108"/> + <location filename="pluginlist.cpp" line="120"/> <source>unknown</source> - <translation type="unfinished">未知</translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="115"/> + <location filename="pluginlist.cpp" line="116"/> <source>Name of your mods</source> <translation>ä½ çš„modåç§°</translation> </message> <message> - <location filename="pluginlist.cpp" line="116"/> + <location filename="pluginlist.cpp" line="117"/> <source>Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="118"/> + <location filename="pluginlist.cpp" line="119"/> <source>The modindex determins the formids of objects originating from this mods.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="159"/> + <location filename="pluginlist.cpp" line="160"/> <source>failed to update esp info for file %1 (source id: %2), error: %3</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="227"/> + <location filename="pluginlist.cpp" line="228"/> <source>esp not found: %1</source> - <translation type="unfinished">esp未找到:%1</translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="234"/> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="235"/> + <location filename="pluginlist.cpp" line="247"/> <source>Confirm</source> <translation>确认</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> + <location filename="pluginlist.cpp" line="235"/> <source>Really enable all plugins?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="247"/> <source>Really disable all plugins?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="397"/> + <location filename="pluginlist.cpp" line="398"/> <source>The file containing locked plugin indices is broken</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="438"/> + <location filename="pluginlist.cpp" line="439"/> <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source> <translation>您的一些æ’ä»¶åç§°æ— æ•ˆï¼è¿™äº›æ’ä»¶æ— æ³•è¢«æ¸¸æˆè½½å…¥ã€‚请查看 mo_interface.log æ¥ç¡®è®¤é‚£äº›å—å½±å“çš„æ’ä»¶å¹¶é‡å‘½å它们。</translation> </message> <message> <location filename="pluginlist.cpp" line="806"/> - <source><b>Origin</b>: %1</source> - <translation type="unfinished"></translation> + <source>This plugin can't be disabled (enforced by the game)</source> + <translation>这个æ’ä»¶ä¸èƒ½è¢«ç¦ç”¨ (ç”±æ¸¸æˆæ‰§è¡Œ)</translation> </message> <message> <location filename="pluginlist.cpp" line="808"/> + <source><b>Origin</b>: %1</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="pluginlist.cpp" line="810"/> <source>Author</source> <translation>作者</translation> </message> <message> - <location filename="pluginlist.cpp" line="811"/> + <location filename="pluginlist.cpp" line="813"/> <source>Description</source> <translation>æè¿°</translation> </message> <message> - <location filename="pluginlist.cpp" line="804"/> - <source>This plugin can't be disabled (enforced by the game)</source> - <translation>这个æ’ä»¶ä¸èƒ½è¢«ç¦ç”¨ (ç”±æ¸¸æˆæ‰§è¡Œ)</translation> - </message> - <message> - <location filename="pluginlist.cpp" line="814"/> + <location filename="pluginlist.cpp" line="816"/> <source>Missing Masters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="821"/> + <location filename="pluginlist.cpp" line="823"/> <source>Enabled Masters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="972"/> + <location filename="pluginlist.cpp" line="974"/> <source>failed to restore load order for %1</source> - <translation type="unfinished">æ¢å¤ %1 åŠ è½½é¡ºåºå¤±è´¥</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3950,7 +3969,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="previewdialog.ui" line="14"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="previewdialog.ui" line="78"/> @@ -3963,16 +3982,16 @@ p, li { white-space: pre-wrap; } <message> <location filename="problemsdialog.ui" line="14"/> <source>Problems</source> - <translation type="unfinished">问题</translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.ui" line="49"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.ui" line="75"/> @@ -3983,12 +4002,12 @@ p, li { white-space: pre-wrap; } <location filename="problemsdialog.cpp" line="44"/> <location filename="problemsdialog.cpp" line="45"/> <source>Fix</source> - <translation type="unfinished">ä¿®å¤</translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.cpp" line="49"/> <source>No guided fix</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3996,32 +4015,32 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="59"/> <source>invalid profile name %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="63"/> <source>failed to create %1</source> - <translation type="unfinished">æ— æ³•åˆ›å»º %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="184"/> <source>failed to write mod list: %1</source> - <translation type="unfinished">æ— æ³•æ›´æ–° Mod 列表: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="195"/> <source>failed to update tweaked ini file, wrong settings may be used: %1</source> - <translation type="unfinished">æ›´æ–°tweaked ini文件失败,å¯èƒ½ä¼šåº”用错误的设置: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="226"/> <source>failed to create tweaked ini: %1</source> - <translation type="unfinished">创建 tweaked ini: %1 失败</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="236"/> <source>"%1" is missing or inaccessible</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="282"/> @@ -4045,7 +4064,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="596"/> <source>failed to parse ini file (%1)</source> - <translation type="unfinished">æ— æ³•è§£æž Ini 文件 (%1)</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="624"/> @@ -4056,7 +4075,7 @@ p, li { white-space: pre-wrap; } <location filename="profile.cpp" line="648"/> <location filename="profile.cpp" line="685"/> <source>failed to modify "%1"</source> - <translation type="unfinished">未能找到 "%1"</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="713"/> @@ -4114,7 +4133,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html></source> @@ -4147,7 +4166,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4206,7 +4225,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.ui" line="123"/> <source>Rename</source> - <translation type="unfinished">&é‡å‘½å</translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="133"/> @@ -4258,7 +4277,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="165"/> <source>Invalid profile name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="172"/> @@ -4268,17 +4287,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="172"/> <source>Are you sure you want to remove this profile (including local savegames if any)?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="182"/> <source>Profile broken</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="183"/> <source>This profile you're about to delete seems to be broken or the path is invalid. I'm about to delete the following folder: "%1". Proceed?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="215"/> @@ -4324,47 +4343,47 @@ p, li { white-space: pre-wrap; } <message> <location filename="csvbuilder.cpp" line="70"/> <source>invalid field name "%1"</source> - <translation type="unfinished">æ— æ•ˆçš„åç§° "%1"</translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="76"/> <source>invalid type for "%1" (should be integer)</source> - <translation type="unfinished">æ— æ•ˆçš„ç±»åž‹ "%1" (应该是整数)</translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="81"/> <source>invalid type for "%1" (should be string)</source> - <translation type="unfinished">æ— æ•ˆçš„ç±»åž‹ "%1" (应该是å—符串)</translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="86"/> <source>invalid type for "%1" (should be float)</source> - <translation type="unfinished">æ— æ•ˆçš„ç±»åž‹ "%1" (应该是浮点数)</translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="103"/> <source>no fields set up yet!</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="140"/> <source>field not set "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="237"/> <source>invalid character in field "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="240"/> <source>empty field name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="gameinfoimpl.cpp" line="41"/> <source>invalid game type %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="helper.cpp" line="53"/> @@ -4448,62 +4467,62 @@ p, li { white-space: pre-wrap; } <translation>æ— æ³•è®¾ç½®ä»£ç†DLLåŠ è½½</translation> </message> <message> - <location filename="main.cpp" line="121"/> + <location filename="main.cpp" line="122"/> <source>Permissions required</source> <translation>éœ€è¦æƒé™</translation> </message> <message> - <location filename="main.cpp" line="122"/> + <location filename="main.cpp" line="123"/> <source>The current user account doesn't have the required access rights to run Mod Organizer. The neccessary changes can be made automatically (the MO directory will be made writable for the current user account). You will be asked to run "helper.exe" with administrative rights.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="218"/> - <location filename="main.cpp" line="256"/> + <location filename="main.cpp" line="202"/> + <location filename="main.cpp" line="241"/> <source>Woops</source> <translation>糟糕</translation> </message> <message> - <location filename="main.cpp" line="219"/> + <location filename="main.cpp" line="203"/> <source>ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened</source> - <translation type="unfinished">ModOrganizerå·²ç»å´©æºƒã€‚è¯Šæ–æ–‡ä»¶æ˜¯å¦å·²ç»äº§ç”Ÿï¼Ÿå¦‚æžœä½ å°†æ–‡ä»¶(%1)å‘é€è‡³ sherb@gmx.net ,这个bug有å¯èƒ½ä¼šè¢«ä¿®å¤ã€‚æœ€å¥½åŠ å…¥å´©æºƒå‘生时情况的简çŸè¯´æ˜Žï¼ˆç”¨è‹±æ–‡å§ï¼‰ã€‚</translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="257"/> + <location filename="main.cpp" line="242"/> <source>ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1</source> <translation>Mod Organizer 崩溃了ï¼é—æ†¾çš„æ˜¯ï¼Œæˆ‘æ— æ³•ç”Ÿæˆè¯Šæ–文件: %1</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <location filename="settings.cpp" line="528"/> <source>Mod Organizer</source> <translation>Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <source>An instance of Mod Organizer is already running</source> <translation>Mod Organizer 的一个实例æ£åœ¨è¿è¡Œ</translation> </message> <message> - <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="397"/> <source>No game identified in "%1". The directory is required to contain the game binary and its launcher.</source> <translation>"%1" 䏿œªæ£€æµ‹åˆ°æ¸¸æˆã€‚请确ä¿è¯¥è·¯å¾„ä¸åŒ…嫿¸¸æˆæ‰§è¡Œç¨‹åºä»¥åŠå¯¹åº”çš„ Launcher 文件。</translation> </message> <message> - <location filename="main.cpp" line="403"/> - <location filename="main.cpp" line="432"/> + <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="429"/> <source>Please select the game to manage</source> <translation>请选择想è¦ç®¡ç†çš„æ¸¸æˆ</translation> </message> <message> - <location filename="main.cpp" line="458"/> + <location filename="main.cpp" line="456"/> <source>Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="547"/> + <location filename="main.cpp" line="545"/> <source>failed to start application: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="856"/> @@ -4511,28 +4530,28 @@ p, li { white-space: pre-wrap; } <translation>请使用工具æ ä¸Šçš„â€œå¸®åŠ©â€æ¥èŽ·å¾—æ‰€æœ‰å…ƒç´ çš„ä½¿ç”¨è¯´æ˜Ž</translation> </message> <message> - <location filename="mainwindow.cpp" line="1649"/> - <location filename="mainwindow.cpp" line="4314"/> + <location filename="mainwindow.cpp" line="1659"/> + <location filename="mainwindow.cpp" line="4347"/> <source><Manage...></source> <translation><管ç†...></translation> </message> <message> - <location filename="mainwindow.cpp" line="1667"/> + <location filename="mainwindow.cpp" line="1677"/> <source>failed to parse profile %1: %2</source> <translation>æ— æ³•è§£æžé…置文件 %1: %2</translation> </message> <message> - <location filename="pluginlist.cpp" line="352"/> + <location filename="pluginlist.cpp" line="353"/> <source>failed to find "%1"</source> <translation>未能找到 "%1"</translation> </message> <message> - <location filename="pluginlist.cpp" line="516"/> + <location filename="pluginlist.cpp" line="518"/> <source>failed to access %1</source> <translation>æ— æ³•è®¿é—® %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="530"/> + <location filename="pluginlist.cpp" line="532"/> <source>failed to set file time %1</source> <translation>æ— æ³•è®¾ç½®æ–‡ä»¶æ—¶é—´ %1</translation> </message> @@ -4544,8 +4563,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="96"/> <source>"%1" is missing or inaccessible</source> - <oldsource>"%1" is missing</oldsource> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="80"/> @@ -4559,6 +4577,11 @@ p, li { white-space: pre-wrap; } <translation>错误</translation> </message> <message> + <location filename="safewritefile.cpp" line="33"/> + <source>failed to open temporary file</source> + <translation type="unfinished"/> + </message> + <message> <location filename="savegamegamebryo.cpp" line="130"/> <location filename="savegamegamebryo.cpp" line="189"/> <location filename="savegamegamebryo.cpp" line="231"/> @@ -4581,62 +4604,57 @@ p, li { white-space: pre-wrap; } <translation>代ç†DLL</translation> </message> <message> - <location filename="spawn.cpp" line="133"/> + <location filename="spawn.cpp" line="140"/> <source>failed to spawn "%1"</source> <translation>æ— æ³•ç”Ÿæˆ "%1"</translation> </message> <message> - <location filename="spawn.cpp" line="140"/> + <location filename="spawn.cpp" line="147"/> <source>Elevation required</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="spawn.cpp" line="141"/> + <location filename="spawn.cpp" line="148"/> <source>This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="spawn.cpp" line="156"/> + <location filename="spawn.cpp" line="163"/> <source>failed to spawn "%1": %2</source> <translation>æ— æ³•ç”Ÿæˆ "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="165"/> + <location filename="spawn.cpp" line="172"/> <source>"%1" doesn't exist</source> <translation>"%1" ä¸å˜åœ¨</translation> </message> <message> - <location filename="spawn.cpp" line="172"/> + <location filename="spawn.cpp" line="179"/> <source>failed to inject dll into "%1": %2</source> <translation>æ— æ³•æ³¨å…¥ dll 到 "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="190"/> + <location filename="spawn.cpp" line="197"/> <source>failed to run "%1"</source> <translation>æ— æ³•è¿è¡Œ "%1"</translation> </message> - <message> - <location filename="safewritefile.cpp" line="33"/> - <source>failed to open temporary file</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">Mod å·²å˜åœ¨</translation> + <translation type="unfinished"/> </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">这个mod看上去已ç»å˜åœ¨ã€‚ä½ æ˜¯å¸Œæœ›å°†æœ¬æ¬¡åŽ‹ç¼©åŒ…æ–‡ä»¶æ·»åŠ ï¼ˆè¦†ç›–å·²å˜åœ¨æ–‡ä»¶ï¼‰æˆ–å®Œå…¨è¦†ç›–ï¼ˆæ—§çš„æ–‡ä»¶å…¨åˆ é™¤ï¼‰ï¼Ÿå¦å¤–ä½ è¿˜å¯ä»¥èµ·åˆ«çš„å称安装本mod。</translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="63"/> @@ -4651,17 +4669,17 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="queryoverwritedialog.ui" line="77"/> <source>Replace</source> - <translation type="unfinished">替æ¢</translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="84"/> <source>Rename</source> - <translation type="unfinished">&é‡å‘½å</translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="91"/> <source>Cancel</source> - <translation type="unfinished">å–æ¶ˆ</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4669,27 +4687,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidget.ui" line="39"/> <source>Save #</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="51"/> <source>Character</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="63"/> <source>Level</source> - <translation type="unfinished">ç‰çº§</translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="75"/> <source>Location</source> - <translation type="unfinished">ä½ç½®</translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="87"/> <source>Date</source> - <translation type="unfinished">æ—¶é—´</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4697,7 +4715,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidgetgamebryo.cpp" line="41"/> <source>Missing ESPs</source> - <translation type="unfinished">缺失的 ESP</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4705,7 +4723,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.ui" line="14"/> <source>Dialog</source> - <translation type="unfinished">å¯¹è¯æ¡†</translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.ui" line="32"/> @@ -4730,12 +4748,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Text Files</source> - <translation type="unfinished">文本文件</translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.cpp" line="40"/> <source>failed to open "%1" for writing</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4761,7 +4779,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="66"/> <source>archive.dll not loaded: "%1"</source> - <translation type="unfinished">archive.dll 没有载入: "%1"</translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="117"/> @@ -4799,7 +4817,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="251"/> <source>failed to move outdated files: %1. Please update manually.</source> - <translation type="unfinished">移除过时文件失败: %1。请手动更新</translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="269"/> @@ -4824,7 +4842,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="426"/> <source>no file for update found. Please update manually.</source> - <translation type="unfinished">没有å‘çŽ°å¯æ›´æ–°ã€‚请手动更新。</translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="441"/> @@ -4842,18 +4860,18 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="settings.cpp" line="115"/> <source>Failed</source> - <translation type="unfinished">失败</translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="116"/> <source>Sorry, failed to start the helper application</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="335"/> <location filename="settings.cpp" line="354"/> <source>attempt to store setting for unknown plugin "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="647"/> @@ -4893,7 +4911,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -4904,12 +4922,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="57"/> <source>Style</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="64"/> <source>graphical style</source> - <translation type="unfinished">ç•Œé¢æ ·å¼</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="67"/> @@ -4919,23 +4937,23 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="78"/> <source>Log Level</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="85"/> <source>Decides the amount of data printed to "ModOrganizer.log"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="88"/> <source>Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="93"/> <source>Debug</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="98"/> @@ -4986,37 +5004,37 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="199"/> <source>User interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="205"/> <source>If checked, the download interface will be more compact.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="208"/> <source>Compact Download Interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="215"/> <source>If checked, the download list will display meta information instead of file names.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="218"/> <source>Download Meta Information</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="234"/> <source>Reset stored information from dialogs.</source> - <translation type="unfinished">é‡è®¾å¯¹è¯æ¡†ä¿¡æ¯ã€‚</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="237"/> <source>This will make all dialogs show up again where you checked the "Remember selection"-box.</source> - <translation type="unfinished">å…¨éƒ¨å¯¹è¯æ¡†å°†å…¨éƒ¨é‡æ–°æ˜¾ç¤ºï¼ŒåŒ…æ‹¬ä½ å·²å‹¾å–过“记ä½é€‰æ‹©â€çš„å¯¹è¯æ¡†ã€‚</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="240"/> @@ -5050,7 +5068,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5061,7 +5079,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="299"/> <source>If checked and if correct credentials are entered below, log-in to Nexus (for browsing and downloading) is automatic.</source> - <translation type="unfinished">勾å–并在下é¢è¾“å…¥æ£ç¡®è´¦æˆ·ï¼Œå°†è‡ªåŠ¨ç™»å½•Nexus (æµè§ˆå’Œä¸‹è½½)。</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="302"/> @@ -5086,7 +5104,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="350"/> <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">å–æ¶ˆè‡ªåЍè”网功能。这并ä¸å½±å“用户调用功能(如检查mod更新,点赞支æŒmod,打开网页æµè§ˆï¼‰ã€‚</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="353"/> @@ -5101,7 +5119,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="363"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="366"/> @@ -5111,12 +5129,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="375"/> <source>Associate with "Download with manager" links</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="404"/> <source>Known Servers (updated on download)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="425"/> @@ -5146,17 +5164,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="548"/> <source>Key</source> - <translation type="unfinished">关键</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="553"/> <source>Value</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="565"/> <source>Blacklisted Plugins (use <del> to remove):</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="576"/> @@ -5178,7 +5196,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5216,10 +5234,10 @@ p, li { white-space: pre-wrap; } There are several means to do this: *Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="678"/> @@ -5234,8 +5252,8 @@ If you use the Steam version of Oblivion the default will NOT work. In this case <message> <location filename="settingsdialog.ui" line="701"/> <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't need an update. Therefore you can configure the version to identify as here. -Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. +On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here. +Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</source> <translation>Mod Organizer 使用了一个N网所æä¾›çš„ API æ¥è¿›è¡Œç±»ä¼¼äºŽæ£€æŸ¥æ›´æ–°å’Œä¸‹è½½æ–‡ä»¶è¿™æ ·çš„æ“ä½œã€‚é—æ†¾çš„æ˜¯è¿™ä¸ª API 并没有给第三方工具 (比如 MO) æ£å¼çš„æŽˆæƒï¼Œæ‰€ä»¥æˆ‘ä»¬éœ€è¦æ¨¡æ‹Ÿ NMM æ¥è¿›è¡Œè¿™äº›æ“作。 @@ -5251,7 +5269,7 @@ tl;dr-version: If Nexus-features don't work, insert the current version num </message> <message> <location filename="settingsdialog.ui" line="726"/> - <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.</source> <translation>看æ¥ï¼Œæ¸¸æˆå¶å°”ä¼šåŠ è½½ä¸€äº›æ²¡æœ‰è¢«æ¿€æ´»æˆæ’ä»¶çš„ ESP 或 ESM 文件。 我还尚ä¸çŸ¥é“å®ƒåœ¨ä»€ä¹ˆæƒ…å†µä¸‹ä¼šè¿™æ ·ï¼Œä½†æ˜¯æœ‰ç”¨æˆ·æŠ¥å‘Šè¯´å®ƒåœ¨æŸäº›æƒ…况下是很ä¸å¿…è¦çš„。如果这个选项被选ä¸ï¼Œé‚£ä¹ˆåœ¨åˆ—è¡¨ä¸æ²¡æœ‰è¢«å‹¾é€‰çš„ ESP å’Œ ESM å°†ä¸ä¼šåœ¨æ¸¸æˆä¸å‡ºçŽ°ï¼Œå¹¶ä¸”ä¹Ÿä¸ä¼šè¢«è½½å…¥ã€‚</translation> @@ -5264,36 +5282,36 @@ I don't yet know what the circumstances are, but user reports imply it is i <message> <location filename="settingsdialog.ui" line="737"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="740"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="744"/> <source>Force-enable game files</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="754"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="757"/> <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't be resolved correctly. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="763"/> <source>Display mods installed outside MO</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="773"/> @@ -5311,7 +5329,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="settingsdialog.ui" line="805"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.cpp" line="95"/> @@ -5388,7 +5406,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="singleinstance.cpp" line="88"/> <source>failed to communicate with running instance: %1</source> - <translation type="unfinished">æ— æ³•è¿žæŽ¥åˆ°æ£åœ¨è¿è¡Œçš„实例: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="singleinstance.cpp" line="100"/> @@ -5434,17 +5452,17 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="transfersavesdialog.ui" line="14"/> <source>Transfer Savegames</source> - <translation type="unfinished">è½¬ç§»å˜æ¡£</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="22"/> <source>Global Characters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="29"/> <source>This is a list of characters in the global location.</source> - <translation type="unfinished">这里是全局ä½ç½®å˜æ¡£è§’色列表。</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="32"/> @@ -5456,7 +5474,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="46"/> @@ -5469,7 +5487,7 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="87"/> @@ -5499,17 +5517,17 @@ On Windows XP: <message> <location filename="transfersavesdialog.ui" line="167"/> <source>Profile Characters</source> - <translation type="unfinished">é…置文件ä¸è§’色</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="140"/> <source>Overwrite</source> - <translation type="unfinished">覆盖</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="141"/> <source>Overwrite the file "%1"</source> - <translation type="unfinished">覆盖文件 "%1"</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="157"/> @@ -5523,17 +5541,17 @@ On Windows XP: <location filename="transfersavesdialog.cpp" line="158"/> <location filename="transfersavesdialog.cpp" line="196"/> <source>Copy all save games of character "%1" to the profile?</source> - <translation type="unfinished">是å¦å¤åˆ¶è§’色 "%1" 的所有游æˆå˜æ¡£åˆ°è¿™ä¸ªé…ç½®ä¸ï¼Ÿ</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="231"/> <source>Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished">是å¦ç§»åŠ¨è§’è‰² "%1" 的所有游æˆå˜æ¡£åˆ°å…¨å±€è·¯å¾„?请注æ„这将使游æˆå˜æ¡£çš„è¿è¡Œç¼–å·å˜å¾—混乱。</translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="270"/> <source>Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished">æ˜¯å¦æ‹·è´è§’色 "%1" 的所有游æˆå˜æ¡£åˆ°å…¨å±€è·¯å¾„?请注æ„这将使游æˆå˜æ¡£çš„è¿è¡Œç¼–å·å˜å¾—混乱。</translation> + <translation type="unfinished"/> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/src/organizer_zh_TW.ts b/src/organizer_zh_TW.ts index 00cb02ae..08c9ed2e 100644 --- a/src/organizer_zh_TW.ts +++ b/src/organizer_zh_TW.ts @@ -1,38 +1,36 @@ -<?xml version="1.0" encoding="utf-8"?> -<!DOCTYPE TS> -<TS version="2.0" language="zh_TW"> +<?xml version="1.0" ?><!DOCTYPE TS><TS language="zh_TW" version="2.0"> <context> <name>AboutDialog</name> <message> <location filename="aboutdialog.ui" line="14"/> <location filename="aboutdialog.ui" line="53"/> <source>About</source> - <translation type="unfinished"></translation> + <translation>關於</translation> </message> <message> <location filename="aboutdialog.ui" line="66"/> <source>Revision:</source> - <translation type="unfinished"></translation> + <translation>版本:</translation> </message> <message> <location filename="aboutdialog.ui" line="104"/> <source>Used Software</source> - <translation type="unfinished"></translation> + <translation>使用的軟體</translation> </message> <message> <location filename="aboutdialog.ui" line="117"/> <source>Credits</source> - <translation type="unfinished"></translation> + <translation>æ¸åŠŸæ–¼</translation> </message> <message> <location filename="aboutdialog.ui" line="123"/> <source>Translators</source> - <translation type="unfinished"></translation> + <translation>ç¿»è¯è€…</translation> </message> <message> <location filename="aboutdialog.ui" line="189"/> <source>Others</source> - <translation type="unfinished"></translation> + <translation>å…¶ä»–</translation> </message> <message> <location filename="aboutdialog.ui" line="266"/> @@ -42,7 +40,7 @@ <message> <location filename="aboutdialog.cpp" line="80"/> <source>No license</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -50,19 +48,19 @@ <message> <location filename="activatemodsdialog.ui" line="14"/> <source>Activate Mods</source> - <translation>激活 Mod</translation> + <translation>啟動 Mod</translation> </message> <message> <location filename="activatemodsdialog.ui" line="20"/> <source>This is a list of esps and esms that were active when the save game was created.</source> - <translation>這是 esp å’Œ esm æª”æ¡ˆçš„åˆ—è¡¨ï¼Œç•¶æ‚¨çš„å˜æª”被建立時將會被激活。</translation> + <translation>這是 esp å’Œ esm æª”æ¡ˆçš„åˆ—è¡¨ï¼Œç•¶æ‚¨çš„å˜æª”被建立時將會被啟動。</translation> </message> <message> <location filename="activatemodsdialog.ui" line="23"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of esps and esms that were active when the save game was created.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">For each esp, the right column contains the mod (or mods) that can be enabled to make the missing esps/esms available.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> @@ -71,11 +69,11 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是 esp å’Œ esm æª”æ¡ˆçš„åˆ—è¡¨ï¼Œç•¶æ‚¨çš„å˜æª”被建立時將會被激活。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是 esp å’Œ esm æª”æ¡ˆçš„åˆ—è¡¨ï¼Œç•¶æ‚¨çš„å˜æª”被建立時將會被啟動。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">å°æ–¼æ¯å€‹ esp,å³åˆ—ä¸åŒ…å«äº†å¯ä»¥é€šéŽå•Ÿç”¨ä¾†ä½¿ç¼ºå¤±çš„ esp 或 esm 變得å¯ç”¨çš„ Mod。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您點擊確定,那麼所有在å³åˆ—ä¸å·²é¸çš„並且å¯ç”¨çš„ Mod 和缺失的 esp 都將會被激活。</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您點擊確定,那麼所有在å³åˆ—ä¸å·²é¸çš„並且å¯ç”¨çš„ Mod 和缺失的 esp 都將會被啟動。</span></p></body></html></translation> </message> <message> <location filename="activatemodsdialog.ui" line="37"/> @@ -160,22 +158,22 @@ If there is a component called "00 Core" it is usually required. Optio <message> <location filename="browserdialog.ui" line="14"/> <source>Some Page</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="browserdialog.ui" line="281"/> <source>Search</source> - <translation type="unfinished"></translation> + <translation>æœå°‹</translation> </message> <message> <location filename="browserdialog.cpp" line="95"/> <source>new</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="browserdialog.cpp" line="209"/> <source>failed to start download</source> - <translation type="unfinished"></translation> + <translation>下載失敗</translation> </message> </context> <context> @@ -226,7 +224,7 @@ If there is a component called "00 Core" it is usually required. Optio <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can match one or multiple nexus categories to a internal ID. Whenever you download a mod from a Nexus Page, Mod Organizer will try to resolve the category defined on the Nexus to one available in MO.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">To find out a category id used by the nexus, visit the categories list of the nexus page and hover over the links there.</span></p></body></html></source> @@ -315,7 +313,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlist.cpp" line="66"/> <source>Done</source> - <translation type="unfinished">完æˆ</translation> + <translation>完æˆ</translation> </message> <message> <location filename="downloadlist.cpp" line="82"/> @@ -325,7 +323,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlist.cpp" line="89"/> <source>pending download</source> - <translation type="unfinished"></translation> + <translation>ç‰å¾…ä¸çš„下載</translation> </message> </context> <context> @@ -334,7 +332,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidget.ui" line="17"/> <location filename="downloadlistwidget.ui" line="61"/> <source>Placeholder</source> - <translation>å ä½ç¬¦</translation> + <translation>é ç•™ä½ç½®</translation> </message> <message> <location filename="downloadlistwidget.ui" line="99"/> @@ -347,7 +345,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidget.cpp" line="116"/> <location filename="downloadlistwidget.cpp" line="118"/> <source>Paused - Double Click to resume</source> - <translation type="unfinished"></translation> + <translation>æš«åœ - 雙擊以回復</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="136"/> @@ -359,7 +357,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidget.cpp" line="143"/> <location filename="downloadlistwidget.cpp" line="145"/> <source>Uninstalled - Double Click to re-install</source> - <translation type="unfinished">å·²å®‰è£ - é›™æ“Šé‡æ–°å®‰è£</translation> + <translation>è§£é™¤å®‰è£ - é›™æ“Šé‡æ–°å®‰è£</translation> </message> </context> <context> @@ -368,7 +366,7 @@ p, li { white-space: pre-wrap; } <location filename="downloadlistwidgetcompact.ui" line="17"/> <location filename="downloadlistwidgetcompact.ui" line="56"/> <source>Placeholder</source> - <translation>å ä½ç¬¦</translation> + <translation>é ç•™ä½ç½®</translation> </message> <message> <location filename="downloadlistwidgetcompact.ui" line="122"/> @@ -381,27 +379,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="92"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="97"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>ç‰å¾…</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="120"/> <source>Paused</source> - <translation type="unfinished">æš«åœ</translation> + <translation>æš«åœ</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="123"/> <source>Fetching Info 1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="125"/> <source>Fetching Info 2</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="130"/> @@ -411,7 +409,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="133"/> <source>Uninstalled</source> - <translation type="unfinished"></translation> + <translation>已解除安è£</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="136"/> @@ -439,12 +437,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="264"/> <source>This will permanently remove all finished downloads from this list (but NOT from disk).</source> - <translation type="unfinished"></translation> + <translation>é€™å°‡æœƒå¾žåˆ—è¡¨ä¸æ°¸ä¹…移除所有已完æˆçš„下載(但䏿œƒå¾žç¡¬ç¢Ÿä¸ç§»é™¤)。</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="273"/> <source>This will permanently remove all installed downloads from this list (but NOT from disk).</source> - <translation type="unfinished"></translation> + <translation>é€™å°‡æœƒå¾žåˆ—è¡¨ä¸æ°¸ä¹…移除所有已安è£çš„下載(但䏿œƒå¾žç¡¬ç¢Ÿä¸ç§»é™¤)。</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="302"/> @@ -459,17 +457,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="306"/> <source>Delete</source> - <translation type="unfinished">&刪除</translation> + <translation>刪除</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="308"/> <source>Un-Hide</source> - <translation type="unfinished">å–æ¶ˆéš±è—</translation> + <translation>å–æ¶ˆéš±è—</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="310"/> <source>Remove from View</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="313"/> @@ -494,12 +492,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidgetcompact.cpp" line="322"/> <source>Delete Installed...</source> - <translation type="unfinished">移除已安è£çš„é …ç›®...</translation> + <translation>刪除已安è£çš„é …ç›®...</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="323"/> <source>Delete All...</source> - <translation type="unfinished"></translation> + <translation>刪除所有...</translation> </message> <message> <location filename="downloadlistwidgetcompact.cpp" line="326"/> @@ -517,22 +515,22 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="93"/> <source>< mod %1 file %2 ></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidget.cpp" line="96"/> <source>Pending</source> - <translation type="unfinished"></translation> + <translation>ç‰å¾…</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="123"/> <source>Fetching Info 1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidget.cpp" line="126"/> <source>Fetching Info 2</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidget.cpp" line="258"/> @@ -555,12 +553,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="277"/> <source>This will remove all finished downloads from this list (but NOT from disk).</source> - <translation type="unfinished">這將會從列表和ç£ç¢Ÿä¸ç§»é™¤æ‰€æœ‰å·²å®Œæˆçš„下載。</translation> + <translation>這將會從列表ä¸ç§»é™¤æ‰€æœ‰å·²å®Œæˆçš„下載(但䏿œƒå¾žç¡¬ç¢Ÿä¸ç§»é™¤)。</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="286"/> <source>This will remove all installed downloads from this list (but NOT from disk).</source> - <translation type="unfinished">這將會從列表和ç£ç¢Ÿä¸ç§»é™¤æ‰€æœ‰å·²å®‰è£çš„ä¸‹è¼‰é …ç›®ã€‚</translation> + <translation>這將會從列表ä¸ç§»é™¤æ‰€æœ‰å·²å®‰è£çš„下載(但䏿œƒå¾žç¡¬ç¢Ÿä¸ç§»é™¤)。</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="314"/> @@ -575,17 +573,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="318"/> <source>Delete</source> - <translation type="unfinished">&刪除</translation> + <translation>刪除</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="320"/> <source>Un-Hide</source> - <translation type="unfinished">å–æ¶ˆéš±è—</translation> + <translation>å–æ¶ˆéš±è—</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="322"/> <source>Remove from View</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadlistwidget.cpp" line="325"/> @@ -610,12 +608,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadlistwidget.cpp" line="334"/> <source>Delete Installed...</source> - <translation type="unfinished">移除已安è£çš„é …ç›®...</translation> + <translation>刪除已安è£çš„é …ç›®...</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="335"/> <source>Delete All...</source> - <translation type="unfinished"></translation> + <translation>刪除所有...</translation> </message> <message> <location filename="downloadlistwidget.cpp" line="338"/> @@ -638,7 +636,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="321"/> <source>Memory allocation error (in refreshing directory).</source> - <translation type="unfinished"></translation> + <translation>記憶體分é…錯誤(æ–¼é‡æ–°æ•´ç†ç›®éŒ„時)。</translation> </message> <message> <location filename="downloadmanager.cpp" line="369"/> @@ -658,12 +656,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="454"/> <source>Wrong Game</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadmanager.cpp" line="454"/> <source>The download link is for a mod for "%1" but this instance of MO has been set up for "%2".</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="downloadmanager.cpp" line="471"/> @@ -708,7 +706,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="640"/> <source>No known download urls. Sorry, this download can't be resumed.</source> - <translation type="unfinished"></translation> + <translation>沒有已知的下載url。抱æ‰ï¼Œç„¡æ³•回復這個下載。</translation> </message> <message> <location filename="downloadmanager.cpp" line="695"/> @@ -728,7 +726,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="745"/> <source>Update</source> - <translation type="unfinished">æ›´æ–°</translation> + <translation>æ›´æ–°</translation> </message> <message> <location filename="downloadmanager.cpp" line="746"/> @@ -753,12 +751,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="999"/> <source>Memory allocation error (in processing progress event).</source> - <translation type="unfinished"></translation> + <translation>記憶體分é…錯誤(於處ç†ç¨‹åºæ™‚)。</translation> </message> <message> <location filename="downloadmanager.cpp" line="1012"/> <source>Memory allocation error (in processing downloaded data).</source> - <translation type="unfinished"></translation> + <translation>記憶體分é…錯誤(於處ç†å·²ä¸‹è¼‰è³‡æ–™æ™‚)。</translation> </message> <message> <location filename="downloadmanager.cpp" line="1141"/> @@ -789,7 +787,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="downloadmanager.cpp" line="1356"/> <source>Download failed. Server reported: %1</source> - <translation type="unfinished"></translation> + <translation>下載失敗。伺æœå™¨å›žå ±: %1</translation> </message> <message> <location filename="downloadmanager.cpp" line="1358"/> @@ -959,12 +957,12 @@ Right now the only case I know of where this needs to be overwritten is for the <message> <location filename="editexecutablesdialog.cpp" line="149"/> <source>Java (32-bit) required</source> - <translation type="unfinished"></translation> + <translation>需è¦Java (32ä½å…ƒ)</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="150"/> <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> + <translation>MO需è¦32ä½å…ƒjava來執行這個程å¼ã€‚å¦‚æžœä½ å·²ç¶“å®‰è£äº†ï¼Œé¸æ“‡é‚£å€‹å®‰è£ä¸‹çš„binaryä¸çš„javaw.exe。</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="166"/> @@ -990,13 +988,13 @@ Right now the only case I know of where this needs to be overwritten is for the <location filename="editexecutablesdialog.cpp" line="230"/> <location filename="editexecutablesdialog.cpp" line="278"/> <source>Save Changes?</source> - <translation type="unfinished">å„²å˜æ›´æ”¹å—Žï¼Ÿ</translation> + <translation>儲å˜ä¿®æ”¹ï¼Ÿ</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="231"/> <location filename="editexecutablesdialog.cpp" line="279"/> <source>You made changes to the current executable, do you want to save them?</source> - <translation type="unfinished"></translation> + <translation>ä½ å°ç¾åœ¨çš„å¯åŸ·è¡Œæª”案åšå‡ºäº†æ”¹è®Šï¼Œä½ 想è¦ä¿å˜å®ƒå€‘嗎?</translation> </message> <message> <location filename="editexecutablesdialog.cpp" line="255"/> @@ -1104,7 +1102,7 @@ Right now the only case I know of where this needs to be overwritten is for the <message> <location filename="installdialog.ui" line="32"/> <source>New Mod</source> - <translation>新增</translation> + <translation>新增 Mod</translation> </message> <message> <location filename="installdialog.ui" line="46"/> @@ -1136,7 +1134,7 @@ Right now the only case I know of where this needs to be overwritten is for the <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This displays the content of the archive. &lt;data&gt; represents the base directory which will map to the game's data directory. You can change the base directory via the right-click context menu and you can move around files via drag&amp;drop</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -1147,17 +1145,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="installdialog.ui" line="121"/> <source>Placeholder</source> - <translation>å ä½ç¬¦</translation> + <translation>é ç•™ä½ç½®</translation> </message> <message> <location filename="installdialog.ui" line="141"/> <source>OK</source> - <translation type="unfinished">確定</translation> + <translation>確定</translation> </message> <message> <location filename="installdialog.ui" line="148"/> <source>Cancel</source> - <translation type="unfinished">å–æ¶ˆ</translation> + <translation>å–æ¶ˆ</translation> </message> </context> <context> @@ -1165,7 +1163,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="76"/> <source>archive.dll not loaded: "%1"</source> - <translation type="unfinished"></translation> + <translation>archive.dll 並未載入: "%1"</translation> </message> <message> <location filename="installationmanager.cpp" line="98"/> @@ -1180,87 +1178,87 @@ p, li { white-space: pre-wrap; } <message> <location filename="installationmanager.cpp" line="164"/> <location filename="installationmanager.cpp" line="248"/> - <location filename="installationmanager.cpp" line="530"/> + <location filename="installationmanager.cpp" line="532"/> <source>Extracting files</source> <translation>æ£åœ¨è§£å£“檔案</translation> </message> <message> - <location filename="installationmanager.cpp" line="439"/> + <location filename="installationmanager.cpp" line="441"/> <source>failed to create backup</source> - <translation type="unfinished"></translation> + <translation>產生備份失敗</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Mod Name</source> - <translation type="unfinished"></translation> + <translation>Mod å稱</translation> </message> <message> - <location filename="installationmanager.cpp" line="448"/> + <location filename="installationmanager.cpp" line="450"/> <source>Name</source> - <translation type="unfinished">å稱</translation> + <translation>å稱</translation> </message> <message> - <location filename="installationmanager.cpp" line="501"/> + <location filename="installationmanager.cpp" line="503"/> <source>Invalid name</source> - <translation type="unfinished"></translation> + <translation>無效的å稱</translation> </message> <message> - <location filename="installationmanager.cpp" line="502"/> + <location filename="installationmanager.cpp" line="504"/> <source>The name you entered is invalid, please enter a different one.</source> - <translation type="unfinished"></translation> + <translation>ä½ è¼¸å…¥çš„å稱是無效的,請輸入ä¸åŒçš„å稱。</translation> </message> <message> - <location filename="installationmanager.cpp" line="610"/> + <location filename="installationmanager.cpp" line="612"/> <source>File format "%1" not supported</source> <translation>æš«ä¸æ”¯æŒæª”æ¡ˆæ ¼å¼: "%1"</translation> </message> <message> - <location filename="installationmanager.cpp" line="743"/> + <location filename="installationmanager.cpp" line="745"/> <source>None of the available installer plugins were able to handle that archive</source> - <translation type="unfinished"></translation> + <translation>沒有任何å¯ç”¨çš„å®‰è£æ’ä»¶èƒ½å¤ è™•ç†é‚£å€‹å£“縮檔</translation> </message> <message> - <location filename="installationmanager.cpp" line="753"/> + <location filename="installationmanager.cpp" line="755"/> <source>no error</source> <translation>沒有錯誤</translation> </message> <message> - <location filename="installationmanager.cpp" line="756"/> + <location filename="installationmanager.cpp" line="758"/> <source>7z.dll not found</source> <translation>未找到 7z.dll</translation> </message> <message> - <location filename="installationmanager.cpp" line="759"/> + <location filename="installationmanager.cpp" line="761"/> <source>7z.dll isn't valid</source> <translation>無效的 7z.dll</translation> </message> <message> - <location filename="installationmanager.cpp" line="762"/> + <location filename="installationmanager.cpp" line="764"/> <source>archive not found</source> <translation>未找到壓縮包</translation> </message> <message> - <location filename="installationmanager.cpp" line="765"/> + <location filename="installationmanager.cpp" line="767"/> <source>failed to open archive</source> <translation>無法開啟壓縮包</translation> </message> <message> - <location filename="installationmanager.cpp" line="768"/> + <location filename="installationmanager.cpp" line="770"/> <source>unsupported archive type</source> <translation>䏿”¯æŒçš„壓縮包類型</translation> </message> <message> - <location filename="installationmanager.cpp" line="771"/> + <location filename="installationmanager.cpp" line="773"/> <source>internal library error</source> <translation>內部庫錯誤</translation> </message> <message> - <location filename="installationmanager.cpp" line="774"/> + <location filename="installationmanager.cpp" line="776"/> <source>archive invalid</source> <translation>無效的壓縮包</translation> </message> <message> - <location filename="installationmanager.cpp" line="778"/> + <location filename="installationmanager.cpp" line="780"/> <source>unknown archive error</source> <translation>未知壓縮包錯誤</translation> </message> @@ -1301,12 +1299,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="moapplication.cpp" line="115"/> <source>an error occured: %1</source> - <translation type="unfinished">發生錯誤: %1</translation> + <translation>發生錯誤: %1</translation> </message> <message> <location filename="moapplication.cpp" line="120"/> <source>an error occured</source> - <translation type="unfinished">發生錯誤</translation> + <translation>發生錯誤</translation> </message> </context> <context> @@ -1320,89 +1318,94 @@ p, li { white-space: pre-wrap; } <message> <location filename="mainwindow.ui" line="97"/> <source>Click blank area to deselect</source> - <translation type="unfinished"></translation> + <translation>點擊空白å€åŸŸä»¥å–æ¶ˆé¸æ“‡</translation> </message> <message> <location filename="mainwindow.ui" line="116"/> <source>If checked, only mods that match all selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>å¦‚æžœæ‰“å‹¾ï¼Œç¬¦åˆæ‰€æœ‰é¸æ“‡çš„類別的mod會被顯示。</translation> </message> <message> <location filename="mainwindow.ui" line="119"/> <source>And</source> - <translation type="unfinished"></translation> + <translation>以åŠ</translation> </message> <message> <location filename="mainwindow.ui" line="129"/> <source>If checked, all mods that match at least one of the selected categories are displayed.</source> - <translation type="unfinished"></translation> + <translation>如果打勾,符åˆè‡³å°‘ä¸€é …é¸æ“‡çš„類別的mod會被顯示。</translation> </message> <message> <location filename="mainwindow.ui" line="132"/> <source>Or</source> - <translation type="unfinished"></translation> + <translation>或者</translation> </message> <message> <location filename="mainwindow.ui" line="171"/> <source>Profile</source> - <translation type="unfinished">é…置檔案</translation> + <translation>é…置檔案</translation> </message> <message> <location filename="mainwindow.ui" line="181"/> <source>Pick a module collection</source> - <translation type="unfinished">鏿“‡ä¸€å€‹é…置檔案</translation> + <translation>鏿“‡ä¸€å€‹é…置檔案</translation> </message> <message> <location filename="mainwindow.ui" line="184"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create profiles here. Each profile contains its own list of active mods and esps. This way you can quickly switch between setups for different play throughs.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Please note that right now your esp load order is not kept seperate for different profiles.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在這裡建立é…置檔案,æ¯å€‹é…置檔案都包å«äº†å®ƒå€‘自己的 Mod å’Œ esp 的激活方案。這樣您就å¯ä»¥é€šéŽå¿«é€Ÿåˆ‡æ›è¨å®šä¾†é«”é©—ä¸åŒçš„éŠæˆ²æ·ç¨‹äº†ã€‚</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">請注æ„: ç•¶å‰æ‚¨çš„é…置檔案的 esp åŠ è¼‰é †åºä¸¦ä¸æ˜¯åˆ†é–‹å„²å˜çš„。</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在這裡建立é…置檔案,æ¯å€‹é…置檔案都包å«äº†å®ƒå€‘自己的 Mod å’Œ esp 的啟動方案。這樣您就å¯ä»¥é€šéŽå¿«é€Ÿåˆ‡æ›è¨å®šä¾†é«”é©—ä¸åŒçš„éŠæˆ²æ·ç¨‹äº†ã€‚</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">請注æ„: ç•¶å‰æ‚¨çš„é…置檔案的 esp è¼‰å…¥é †åºä¸¦ä¸æ˜¯åˆ†é–‹å„²å˜çš„。</span></p></body></html></translation> + </message> + <message> + <location filename="mainwindow.ui" line="215"/> + <source>Open list options...</source> + <translation>打開åå–®é¸é …...</translation> </message> <message> <location filename="mainwindow.ui" line="218"/> <source>Refresh list. This is usually not necessary unless you modified data outside the program.</source> - <translation type="unfinished">釿–°æ•´ç†åˆ—è¡¨ï¼Œé€™é€šå¸¸ä¸æ˜¯å¿…é ˆçš„ï¼Œé™¤éžæ‚¨åœ¨ç¨‹å¼ä¹‹å¤–修改了檔案的數據。</translation> + <translation>釿–°æ•´ç†åˆ—è¡¨ï¼Œé™¤éžæ‚¨åœ¨ç¨‹å¼ä¹‹å¤–修改了檔案的資料,å¦å‰‡é€™é€šå¸¸æ˜¯ä¸å¿…è¦çš„。</translation> </message> <message> <location filename="mainwindow.ui" line="238"/> <location filename="mainwindow.ui" line="739"/> <source>Restore Backup...</source> - <translation type="unfinished"></translation> + <translation>回復備份...</translation> </message> <message> <location filename="mainwindow.ui" line="252"/> <location filename="mainwindow.ui" line="759"/> <source>Create Backup</source> - <translation type="unfinished"></translation> + <translation>產生備份</translation> </message> <message> <location filename="mainwindow.ui" line="368"/> <source>List of available mods.</source> - <translation type="unfinished"></translation> + <translation>å¯ç”¨ Mod åå–®</translation> </message> <message> <location filename="mainwindow.ui" line="371"/> <source>This is a list of installed mods. Use the checkboxes to activate/deactivate mods and drag & drop mods to change their "installation" orders.</source> - <translation type="unfinished"></translation> + <translation>這是已安è£çš„ Mod åå–®ã€‚ä½¿ç”¨è¤‡é¸æ¡†ä¾†å•Ÿå‹•/關閉 Mod 並拖曳 Mod 來改變它們的"安è£"é †åºã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="456"/> <source>Filter</source> - <translation type="unfinished">éŽæ¿¾å™¨</translation> + <translation>篩é¸</translation> </message> <message> <location filename="mainwindow.ui" line="477"/> <source>No groups</source> - <translation type="unfinished"></translation> + <translation>無群組</translation> </message> <message> <location filename="mainwindow.ui" line="487"/> @@ -1414,126 +1417,121 @@ p, li { white-space: pre-wrap; } <location filename="mainwindow.ui" line="876"/> <location filename="mainwindow.ui" line="1220"/> <source>Namefilter</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="530"/> <source>Pick a program to run.</source> - <translation type="unfinished">鏿“‡è¦é‹è¡Œçš„程å¼ã€‚</translation> + <translation>鏿“‡è¦åŸ·è¡Œçš„程å¼ã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="533"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Choose the program to run. Once you start using ModOrganizer, you should always run your game and tools from here or through shortcuts created here, otherwise mods installed through MO will not be visible.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You can add new Tools to this list, but I can't promise tools I haven't tested will work.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">鏿“‡è¦é‹è¡Œçš„程å¼ã€‚一旦您開始使用 Mod Organizer,您應該始終從這裡或通éŽåœ¨é€™è£¡å»ºç«‹çš„æ·å¾‘ä¾†é‹è¡Œæ‚¨çš„éŠæˆ²å’Œå·¥å…·ï¼Œå¦å‰‡ä»»ä½•ç¶“ç”± MO 安è£çš„ Mod 都會變得ä¸å¯è¦‹ã€‚</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您å¯ä»¥æ·»åŠ æ–°çš„å·¥å…·åˆ°æ¤åˆ—表ä¸ï¼Œä½†æˆ‘ä¸èƒ½ä¿è‰ä¸€äº›æˆ‘沒有測試éŽçš„工具能够æ£å¸¸å·¥ä½œã€‚</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">鏿“‡è¦åŸ·è¡Œçš„程å¼ã€‚一旦您開始使用 Mod Organizer,您應該始終從這裡或通éŽåœ¨é€™è£¡å»ºç«‹çš„æ·å¾‘ä¾†é‹è¡Œæ‚¨çš„éŠæˆ²å’Œå·¥å…·ï¼Œå¦å‰‡ä»»ä½•ç¶“ç”± MO 安è£çš„ Mod 都會變得ä¸å¯è¦‹ã€‚</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">您å¯ä»¥æ·»åŠ æ–°çš„å·¥å…·åˆ°æ¤åˆ—表ä¸ï¼Œä½†æˆ‘ä¸èƒ½ä¿è‰ä¸€äº›æˆ‘沒有測試éŽçš„å·¥å…·èƒ½å¤ æ£å¸¸å·¥ä½œã€‚</span></p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="581"/> <source>Run program</source> - <translation type="unfinished">é‹è¡Œç¨‹å¼</translation> + <translation>執行程å¼</translation> </message> <message> <location filename="mainwindow.ui" line="584"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Run the selected program with ModOrganizer enabled.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer 啟用的狀態下é‹è¡ŒæŒ‡å®šçš„程å¼ã€‚</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">在 Mod Organizer 啟用的狀態下執行指定的程å¼ã€‚</span></p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="594"/> <source>Run</source> - <translation type="unfinished">é‹è¡Œ</translation> + <translation>執行</translation> </message> <message> <location filename="mainwindow.ui" line="635"/> <source>Create a shortcut in your start menu or on the desktop to the specified program</source> - <translation type="unfinished"></translation> + <translation>為特定的程å¼åœ¨é–‹å§‹åŠŸèƒ½åˆ—æˆ–æ¡Œé¢ä¸Šç”¢ç”Ÿä¸€å€‹æ·å¾‘</translation> </message> <message> <location filename="mainwindow.ui" line="638"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This creates a start menu shortcut that directly starts the selected program with the MO active.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">建立一個開始èœå–®æ·å¾‘,使您å¯ä»¥ç›´æŽ¥åœ¨ MO 激活狀態下é‹è¡ŒæŒ‡å®šçš„程å¼ã€‚</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">建立一個開始功能列æ·å¾‘,使您å¯ä»¥ç›´æŽ¥åœ¨ MO 啟動狀態下執行指定的程å¼ã€‚</span></p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="645"/> <source>Shortcut</source> - <translation type="unfinished"></translation> + <translation>æ·å¾‘</translation> </message> <message> <location filename="mainwindow.ui" line="695"/> <source>Plugins</source> - <translation type="unfinished"></translation> + <translation>æ’ä»¶</translation> + </message> + <message> + <location filename="mainwindow.ui" line="715"/> + <source>Sort</source> + <translation>排åº</translation> </message> <message> <location filename="mainwindow.ui" line="821"/> <source>List of available esp/esm files</source> - <translation type="unfinished">å¯ç”¨ esp 或 esm 檔案的列表</translation> + <translation>å¯ç”¨ esp/esm 檔案åå–®</translation> </message> <message> <location filename="mainwindow.ui" line="824"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This list contains the esps and esms contained in the active mods. These require their own load order. Use drag&amp;drop to modify this load order. Please note that MO will only save the load order for mods that are active/checked.<br />There is a great tool named &quot;BOSS&quot; to automatically sort these files.</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這個列表ä¸åŒ…å«äº†ä½äºŽå·²æ¿€æ´» Mod 裡的 esp å’Œ esm 檔案。這些檔案都需è¦å®ƒå€‘è‡ªå·±çš„åŠ è¼‰é †åºï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ‹–æ”¾ä¾†ä¿®æ”¹åŠ è¼‰é †åºã€‚請注æ„: MO å°‡åªå„²å˜å·²æ¿€æ´»æˆ–已勾é¸ç‹€æ…‹çš„ Mod çš„åŠ è¼‰é †åºã€‚<br />有個éžå¸¸æ£’的工具å«ä½œ &quot;BOSS&quot;,它å¯ä»¥è‡ªå‹•å°é€™äº›æª”案進行排åºã€‚</span></p></body></html></translation> - </message> - <message> - <location filename="mainwindow.ui" line="715"/> - <source>Sort</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.ui" line="215"/> - <source>Open list options...</source> - <translation type="unfinished"></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這個列表ä¸åŒ…å«äº†ä½æ–¼å·²å•Ÿå‹• Mod 裡的 esp å’Œ esm 檔案。這些檔案都需è¦å®ƒå€‘è‡ªå·±çš„è¼‰å…¥é †åºï¼Œæ‚¨å¯ä»¥æ‹–æ›³ä¾†ä¿®æ”¹è¼‰å…¥é †åºã€‚請注æ„: MO å°‡åªå„²å˜å·²å•Ÿå‹•或已勾é¸ç‹€æ…‹çš„ Mod çš„è¼‰å…¥é †åºã€‚<br />有個éžå¸¸æ£’的工具å«ä½œ "BOSS",它å¯ä»¥è‡ªå‹•å°é€™äº›æª”案進行排åºã€‚</span></p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="886"/> <source>Archives</source> - <translation type="unfinished"></translation> + <translation>壓縮包</translation> </message> <message> <location filename="mainwindow.ui" line="916"/> <source><html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html></source> - <translation type="unfinished"></translation> + <translation><html><head/><body><p>BSA æª”æ¡ˆæ˜¯éŠæˆ²è³‡æºçš„包裹(æè³ªã€è…³æœ¬......)。é è¨æƒ…æ³ä¸‹ï¼ŒéŠæˆ²å¼•擎自分散的檔案ä¸åˆ†åˆ¥è¼‰å…¥é€™äº›åŒ…裹。MO å¯ä»¥é€éŽåˆ†æ•£çš„æª”案來管ç†é€™äº›å£“ç¸®åŒ…ä»¥èª¿æ•´å®ƒå€‘çš„è¼‰å…¥é †åº:</p><p>如果壓縮包<span style=" font-weight:600;">有被管ç†</span>ï¼Œå®ƒå€‘çš„è¼‰å…¥é †åºæ˜¯è¢«å°æ‡‰çš„ Mod(å·¦å´çš„颿¿)決定其優先程度,分散的檔案也是如æ¤ã€‚您å¯ä»¥æ‰‹å‹•å•Ÿç”¨ä»»ä½•æ²’æœ‰å°æ‡‰æ’件於啟動狀態的 BSA 檔案。<br/></p><p>如果壓縮包 <span style=" font-weight:600;">沒有被管ç†</span>ï¼Œå®ƒå€‘çš„è¼‰å…¥é †åºæ˜¯è¢«å°æ‡‰çš„æ’ä»¶(å³å´çš„颿¿ï¼Œæ’ä»¶é¸é …)決定其優先程度。您就ä¸å¯ä»¥æ‰‹å‹•啟用沒有æ’件於啟動狀態的 BSA 檔案。</p><p>在兩種狀æ³ä¸‹æ‚¨éƒ½ä¸å¯ä»¥é—œé–‰æœ‰å°æ‡‰æ’ä»¶çš„å£“ç¸®åŒ…ï¼ŒéŠæˆ²ä»ç„¶æœƒè¼‰å…¥å®ƒå€‘。</p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="919"/> <source><html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.ui" line="934"/> <source>List of available BS Archives. Archives not checked here are not managed by MO and ignore installation order.</source> - <translation type="unfinished">å¯ç”¨ BSA 檔案的列表。未勾é¸çš„é …ç›®ä¸æœƒè¢« MO 管ç†ä¸¦ä¸”會忽略安è£é †åºã€‚</translation> + <translation>å¯ç”¨ BSA 檔案的列表。未勾é¸çš„é …ç›®ä¸æœƒè¢« MO 管ç†ä¸¦ä¸”會忽略安è£é †åºã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="937"/> @@ -1541,229 +1539,229 @@ p, li { white-space: pre-wrap; } By default, BSAs that share their base name with an enabled ESP (i.e. plugin.esp and plugin.bsa) are automatically loaded and will have precedence over all loose files, the installation order you set up to the left is then ignored! BSAs checked here are loaded in such a way that your installation order is obeyed properly.</source> - <translation type="unfinished">BSA 檔案是 Bethesda 專用的壓縮包檔案 (å€åˆ¥æ–¼ .zip 檔案),裡é¢åŒ…å«äº†éŠæˆ²æ‰€ç”¨çš„ Data 內的檔案 (meshes, textures ç‰)。這與 Data 目錄裡分散的檔案是ä¸åŒçš„。 + <translation>BSA 檔案是 Bethesda 專用的壓縮包檔案 (å€åˆ¥æ–¼ .zip 檔案),裡é¢åŒ…å«äº†éŠæˆ²æ‰€ç”¨çš„ Data 內的檔案 (meshes, textures ç‰)。這與 Data 目錄裡分散的檔案是ä¸åŒçš„。 é»˜èªæƒ…æ³ä¸‹ï¼ŒBSA 檔案的åç¨±å–æ±ºæ–¼ ESP æ’ä»¶çš„å稱 (例: plugins.esp å°æ‡‰ plugins.bsa)ã€‚éŠæˆ²é‹è¡Œæ™‚,ESP å°æ‡‰çš„ BSA å°‡æœƒè‡ªå‹•åŠ è¼‰ï¼Œä¸¦ä¸”æ¯”æ‰€æœ‰åˆ†æ•£çš„æª”æ¡ˆå„ªå…ˆç´šéƒ½é«˜ï¼Œå·¦é‚Šæ‚¨è¨å®šçš„安è£é †åºæœ€çµ‚會被忽略掉。 -這裡勾é¸çš„ BSA 將會ä¾å¾žæ‚¨çš„安è£é †åºï¼Œä¸¦ä¸”æœƒè‡ªè¡Œèª¿æ•´åŠ è¼‰é †åºã€‚</translation> +這裡勾é¸çš„ BSA 將會ä¾å¾žæ‚¨çš„安è£é †åºï¼Œä¸¦ä¸”æœƒè‡ªè¡Œèª¿æ•´è¼‰å…¥é †åºã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="983"/> <location filename="mainwindow.ui" line="1042"/> <source>File</source> - <translation type="unfinished">檔案</translation> + <translation>檔案</translation> </message> <message> <location filename="mainwindow.ui" line="992"/> <source>Data</source> - <translation type="unfinished">Data</translation> + <translation>資料</translation> </message> <message> <location filename="mainwindow.ui" line="1010"/> <source>refresh data-directory overview</source> - <translation type="unfinished">釿–°æ•´ç† Data 目錄總覽</translation> + <translation>釿–°æ•´ç† Data 目錄總覽</translation> </message> <message> <location filename="mainwindow.ui" line="1013"/> <source>Refresh the overview. This may take a moment.</source> - <translation type="unfinished">釿–°æ•´ç†ç¸½è¦½ï¼Œé€™å¯èƒ½éœ€è¦ä¸€äº›æ™‚間。</translation> + <translation>釿–°æ•´ç†ç¸½è¦½ï¼Œé€™å¯èƒ½éœ€è¦ä¸€äº›æ™‚間。</translation> </message> <message> <location filename="mainwindow.ui" line="1016"/> - <location filename="mainwindow.cpp" line="3833"/> - <location filename="mainwindow.cpp" line="4705"/> + <location filename="mainwindow.cpp" line="3858"/> + <location filename="mainwindow.cpp" line="4738"/> <source>Refresh</source> - <translation type="unfinished">釿–°æ•´ç†</translation> + <translation>釿–°æ•´ç†</translation> </message> <message> <location filename="mainwindow.ui" line="1032"/> <source>This is an overview of your data directory as visible to the game (and tools). </source> - <translation type="unfinished">é€™æ˜¯åœ¨éŠæˆ²ä¸å¯è¦‹çš„ Data 目錄 (和工具) 的總覽。</translation> + <translation>é€™æ˜¯åœ¨éŠæˆ²ä¸å¯è¦‹çš„ Data 目錄 (和工具) 的總覽。</translation> </message> <message> <location filename="mainwindow.ui" line="1047"/> <source>Mod</source> - <translation type="unfinished">Mod</translation> + <translation>Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1057"/> <location filename="mainwindow.ui" line="1060"/> <source>Filter the above list so that only conflicts are displayed.</source> - <translation type="unfinished">éŽæ¿¾ä¸Šé¢çš„列表,使您åªèƒ½çœ‹åˆ°æœ‰è¡çªçš„æª”案。</translation> + <translation>篩é¸ä¸Šé¢çš„列表,使您åªèƒ½çœ‹åˆ°æœ‰è¡çªçš„æª”案。</translation> </message> <message> <location filename="mainwindow.ui" line="1063"/> <source>Show only conflicts</source> - <translation type="unfinished">åªé¡¯ç¤ºè¡çª</translation> + <translation>åªé¡¯ç¤ºè¡çª</translation> </message> <message> <location filename="mainwindow.ui" line="1071"/> <source>Saves</source> - <translation type="unfinished">å˜æª”</translation> + <translation>å˜æª”</translation> </message> <message> <location filename="mainwindow.ui" line="1095"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a list of all savegames for this game. Hover over a list entry to get detailed information about the save including a list of esps/esms that were used at the time this save was created but aren't active now.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you click &quot;Fix Mods...&quot; in the context menu, MO will try to activate all mods and esps to fix those missing esps. It will not disable anything!</span></p></body></html></source> - <translation type="unfinished"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> + <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是æ¤éŠæˆ²æ‰€æœ‰å˜æª”çš„åˆ—è¡¨ï¼Œå°‡æ»‘é¼ æ‡¸åœåœ¨é …目上來ç²å–è©²å˜æª”的詳細信æ¯ï¼Œè£¡é¢åŒ…å«äº†ç¾åœ¨æ²’æœ‰è¢«æ¿€æ´»ä½†æ˜¯ç•¶å˜æª”被建立時所使用的 esp 或 esm 的清單。</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">這是æ¤éŠæˆ²æ‰€æœ‰å˜æª”çš„åˆ—è¡¨ï¼Œå°‡æ»‘é¼ æ‡¸åœåœ¨é …目上來ç²å–è©²å˜æª”的詳細信æ¯ï¼Œè£¡é¢åŒ…å«äº†ç¾åœ¨æ²’æœ‰è¢«å•Ÿå‹•ä½†æ˜¯ç•¶å˜æª”被建立時所使用的 esp 或 esm 的清單。</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在å³éµèœå–®ä¸é»žæ“Šâ€œä¿®å¾© Modâ€ï¼Œé‚£éº¼ MO 便會嘗試激活所有 Mod å’Œ esp 來修復那些缺失的 espï¼Œå®ƒä¸¦ä¸æœƒç¦ç”¨ä»»ä½•æ±è¥¿ï¼</span></p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您在å³éµé¸é …ä¸é»žæ“Šâ€œä¿®å¾© Modâ€ï¼Œé‚£éº¼ MO 便會嘗試啟動所有 Mod å’Œ esp 來修復那些缺失的 espï¼Œå®ƒä¸¦ä¸æœƒç¦ç”¨ä»»ä½•æ±è¥¿ï¼</span></p></body></html></translation> </message> <message> <location filename="mainwindow.ui" line="1115"/> <source>Downloads</source> - <translation type="unfinished">下載</translation> + <translation>下載</translation> </message> <message> <location filename="mainwindow.ui" line="1147"/> <source>This is a list of mods you downloaded from Nexus. Double click one to install it.</source> - <translation type="unfinished">這是當å‰å·²ä¸‹è¼‰çš„ Mod 的列表,雙擊進行安è£ã€‚</translation> + <translation>這是自N網下載的 Mod 的列表,雙擊進行安è£ã€‚</translation> </message> <message> <location filename="mainwindow.ui" line="1200"/> <source>Show Hidden</source> - <translation type="unfinished"></translation> + <translation>顯示隱è—</translation> </message> <message> <location filename="mainwindow.ui" line="1262"/> <source>Tool Bar</source> - <translation type="unfinished">工具欄</translation> + <translation>工具欄</translation> </message> <message> <location filename="mainwindow.ui" line="1304"/> <source>Install Mod</source> - <translation type="unfinished">å®‰è£ Mod</translation> + <translation>å®‰è£ Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1307"/> <source>Install &Mod</source> - <translation type="unfinished">å®‰è£ &Mod</translation> + <translation>å®‰è£ &Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1310"/> <source>Install a new mod from an archive</source> - <translation type="unfinished">通éŽå£“縮包來安è£ä¸€å€‹æ–° Mod</translation> + <translation>通éŽå£“縮包來安è£ä¸€å€‹æ–° Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1313"/> <source>Ctrl+M</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+M</translation> </message> <message> <location filename="mainwindow.ui" line="1322"/> <source>Profiles</source> - <translation type="unfinished">é…置檔案</translation> + <translation>é…置檔案</translation> </message> <message> <location filename="mainwindow.ui" line="1325"/> <source>&Profiles</source> - <translation type="unfinished">&é…置檔案</translation> + <translation>&é…置檔案</translation> </message> <message> <location filename="mainwindow.ui" line="1328"/> <source>Configure Profiles</source> - <translation type="unfinished">è¨å®šé…置檔案</translation> + <translation>è¨å®šé…置檔案</translation> </message> <message> <location filename="mainwindow.ui" line="1331"/> <source>Ctrl+P</source> - <translation type="unfinished">Ctrl+P</translation> + <translation>Ctrl+P</translation> </message> <message> <location filename="mainwindow.ui" line="1340"/> <source>Executables</source> - <translation type="unfinished">å¯åŸ·è¡Œç¨‹å¼</translation> + <translation>å¯åŸ·è¡Œç¨‹å¼</translation> </message> <message> <location filename="mainwindow.ui" line="1343"/> <source>&Executables</source> - <translation type="unfinished">&å¯åŸ·è¡Œç¨‹å¼</translation> + <translation>&å¯åŸ·è¡Œç¨‹å¼</translation> </message> <message> <location filename="mainwindow.ui" line="1346"/> <source>Configure the executables that can be started through Mod Organizer</source> - <translation type="unfinished">é…ç½®å¯é€šéŽ MO 來啟動的程å¼</translation> + <translation>é…ç½®å¯é€éŽ Mod Organizer 來啟動的程å¼</translation> </message> <message> <location filename="mainwindow.ui" line="1349"/> <source>Ctrl+E</source> - <translation type="unfinished">Ctrl+E</translation> + <translation>Ctrl+E</translation> </message> <message> <location filename="mainwindow.ui" line="1358"/> <location filename="mainwindow.ui" line="1364"/> <source>Tools</source> - <translation type="unfinished"></translation> + <translation>工具</translation> </message> <message> <location filename="mainwindow.ui" line="1361"/> <source>&Tools</source> - <translation type="unfinished"></translation> + <translation>&工具</translation> </message> <message> <location filename="mainwindow.ui" line="1367"/> <source>Ctrl+I</source> - <translation type="unfinished">Ctrl+I</translation> + <translation>Ctrl+I</translation> </message> <message> <location filename="mainwindow.ui" line="1376"/> <source>Settings</source> - <translation type="unfinished">è¨å®š</translation> + <translation>è¨å®š</translation> </message> <message> <location filename="mainwindow.ui" line="1379"/> <source>&Settings</source> - <translation type="unfinished">&è¨å®š</translation> + <translation>&è¨å®š</translation> </message> <message> <location filename="mainwindow.ui" line="1382"/> <source>Configure settings and workarounds</source> - <translation type="unfinished">é…ç½®è¨å®šå’Œè§£æ±ºæ–¹æ¡ˆ</translation> + <translation>é…ç½®è¨å®šå’Œè§£æ±ºæ–¹æ¡ˆ</translation> </message> <message> <location filename="mainwindow.ui" line="1385"/> <source>Ctrl+S</source> - <translation type="unfinished">Ctrl+S</translation> + <translation>Ctrl+S</translation> </message> <message> <location filename="mainwindow.ui" line="1394"/> <source>Nexus</source> - <translation type="unfinished">Nç¶²</translation> + <translation>Nç¶²</translation> </message> <message> <location filename="mainwindow.ui" line="1397"/> <source>Search nexus network for more mods</source> - <translation type="unfinished">æœå°‹N網以ç²å–更多 Mod</translation> + <translation>æœå°‹N網以ç²å–更多 Mod</translation> </message> <message> <location filename="mainwindow.ui" line="1400"/> <source>Ctrl+N</source> - <translation type="unfinished">Ctrl+N</translation> + <translation>Ctrl+N</translation> </message> <message> <location filename="mainwindow.ui" line="1412"/> - <location filename="mainwindow.cpp" line="4646"/> + <location filename="mainwindow.cpp" line="4679"/> <source>Update</source> - <translation type="unfinished">æ›´æ–°</translation> + <translation>æ›´æ–°</translation> </message> <message> <location filename="mainwindow.ui" line="1415"/> <source>Mod Organizer is up-to-date</source> - <translation type="unfinished">Mod Organizer ç¾åœ¨æ˜¯æœ€æ–°ç‰ˆæœ¬</translation> + <translation>Mod Organizer ç¾åœ¨æ˜¯æœ€æ–°ç‰ˆæœ¬</translation> </message> <message> <location filename="mainwindow.ui" line="1427"/> <location filename="mainwindow.cpp" line="573"/> <source>No Problems</source> - <translation type="unfinished">沒有å•題</translation> + <translation>沒有å•題</translation> </message> <message> <location filename="mainwindow.ui" line="1430"/> @@ -1771,7 +1769,7 @@ p, li { white-space: pre-wrap; } !Work in progress! Right now this has very limited functionality</source> - <translation type="unfinished">如果 MO 檢測到您的安è£ä¸å˜åœ¨æ½›åœ¨çš„å•é¡Œï¼Œé‚£éº¼æ¤æŒ‰éˆ•å°‡æœƒé«˜äº®é¡¯ç¤ºï¼ŒåŒæ™‚ MO 也會給您相應的修復æç¤ºã€‚ + <translation>如果 MO 檢測到您的安è£ä¸å˜åœ¨æ½›åœ¨çš„å•é¡Œï¼Œé‚£éº¼æ¤æŒ‰éˆ•å°‡æœƒé«˜äº®é¡¯ç¤ºï¼ŒåŒæ™‚ MO 也會給您相應的修復æç¤ºã€‚ ï¼æ¤åŠŸèƒ½å°šæœªå®Œå–„ï¼ ç•¶å‰æ¤åŠŸèƒ½æ‰€èƒ½æä¾›çš„é …ç›®éžå¸¸æœ‰é™</translation> @@ -1780,103 +1778,103 @@ Right now this has very limited functionality</source> <location filename="mainwindow.ui" line="1442"/> <location filename="mainwindow.ui" line="1445"/> <source>Help</source> - <translation type="unfinished">幫助</translation> + <translation>幫助</translation> </message> <message> <location filename="mainwindow.ui" line="1448"/> <source>Ctrl+H</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+M</translation> </message> <message> <location filename="mainwindow.ui" line="1457"/> <source>Endorse MO</source> - <translation type="unfinished"></translation> + <translation>è´ŠåŒ MO</translation> </message> <message> <location filename="mainwindow.ui" line="1460"/> - <location filename="mainwindow.cpp" line="4728"/> + <location filename="mainwindow.cpp" line="4761"/> <source>Endorse Mod Organizer</source> - <translation type="unfinished"></translation> + <translation>è´ŠåŒ Mod Organizer</translation> </message> <message> <location filename="mainwindow.ui" line="1465"/> <source>Copy Log to Clipboard</source> - <translation type="unfinished"></translation> + <translation>複製紀錄到剪貼簿上</translation> </message> <message> <location filename="mainwindow.ui" line="1468"/> <source>Ctrl+C</source> - <translation type="unfinished">Ctrl+M</translation> + <translation>Ctrl+C</translation> </message> <message> <location filename="mainwindow.cpp" line="255"/> <source>Toolbar</source> - <translation type="unfinished">工具欄</translation> + <translation>工具欄</translation> </message> <message> <location filename="mainwindow.cpp" line="256"/> <source>Desktop</source> - <translation type="unfinished"></translation> + <translation>桌é¢</translation> </message> <message> <location filename="mainwindow.cpp" line="257"/> <source>Start Menu</source> - <translation type="unfinished"></translation> + <translation>開始功能列</translation> </message> <message> <location filename="mainwindow.cpp" line="561"/> <source>Problems</source> - <translation type="unfinished">å•題</translation> + <translation>å•題</translation> </message> <message> <location filename="mainwindow.cpp" line="562"/> <source>There are potential problems with your setup</source> - <translation type="unfinished">您的安è£ä¸å˜åœ¨æ½›åœ¨çš„å•題</translation> + <translation>您的安è£ä¸å˜åœ¨æ½›åœ¨çš„å•題</translation> </message> <message> <location filename="mainwindow.cpp" line="574"/> <source>Everything seems to be in order</source> - <translation type="unfinished">一切井然有åº</translation> + <translation>一切看來井然有åº</translation> </message> <message> <location filename="mainwindow.cpp" line="635"/> <source>Help on UI</source> - <translation type="unfinished">介é¢å¹«åŠ©</translation> + <translation>使用者介é¢å¹«åŠ©</translation> </message> <message> <location filename="mainwindow.cpp" line="639"/> <source>Documentation Wiki</source> - <translation type="unfinished">說明文檔 (ç¶åŸº)</translation> + <translation>說明文檔 (Wiki)</translation> </message> <message> <location filename="mainwindow.cpp" line="643"/> <source>Report Issue</source> - <translation type="unfinished">å ±å‘Šå•題</translation> + <translation>å›žå ±å•題</translation> </message> <message> <location filename="mainwindow.cpp" line="647"/> <source>Tutorials</source> - <translation type="unfinished"></translation> + <translation>æ•™å¸</translation> </message> <message> <location filename="mainwindow.cpp" line="686"/> <source>About</source> - <translation type="unfinished"></translation> + <translation>關於</translation> </message> <message> <location filename="mainwindow.cpp" line="687"/> <source>About Qt</source> - <translation type="unfinished"></translation> + <translation>關於 Qt</translation> </message> <message> <location filename="mainwindow.cpp" line="782"/> <source>failed to save load order: %1</source> - <translation type="unfinished">無法儲å˜åŠ è¼‰é †åº: %1</translation> + <translation>儲å˜åŠ è¼‰é †åºå¤±æ•—: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="793"/> <source>Name</source> - <translation type="unfinished">å稱</translation> + <translation>å稱</translation> </message> <message> <location filename="mainwindow.cpp" line="794"/> @@ -1886,991 +1884,990 @@ Right now this has very limited functionality</source> <message> <location filename="mainwindow.cpp" line="802"/> <source>failed to create profile: %1</source> - <translation type="unfinished">無法建立é…置檔案: %1</translation> + <translation>建立é…置檔案失敗: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="843"/> <source>Show tutorial?</source> - <translation type="unfinished"></translation> + <translation>顯示教å¸ï¼Ÿ</translation> </message> <message> <location filename="mainwindow.cpp" line="844"/> <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 "Help"-menu.</source> - <translation type="unfinished"></translation> + <translation>您æ£ç¬¬ä¸€æ¬¡å•Ÿå‹• Mod Organizer。您想è¦é¡¯ç¤ºå…¶åŸºæœ¬åŠŸèƒ½çš„æ•™å¸å—Žï¼Ÿå¦‚æžœä½ é¸æ“‡ä¸è¦ï¼Œæ‚¨ä»ç„¶å¯ä»¥è‡ª"幫助"é¸å–®é–‹å•Ÿæ•™å¸ã€‚</translation> </message> <message> <location filename="mainwindow.cpp" line="875"/> <source>Downloads in progress</source> - <translation type="unfinished">æ£åœ¨ä¸‹è¼‰</translation> + <translation>æ£åœ¨ä¸‹è¼‰</translation> </message> <message> <location filename="mainwindow.cpp" line="876"/> <source>There are still downloads in progress, do you really want to quit?</source> - <translation type="unfinished">仿œ‰æ£åœ¨é€²è¡Œä¸çš„下載,您確定è¦é€€å‡ºå—Žï¼Ÿ</translation> + <translation>仿œ‰æ£åœ¨é€²è¡Œä¸çš„下載,您確定è¦é€€å‡ºå—Žï¼Ÿ</translation> </message> <message> <location filename="mainwindow.cpp" line="930"/> <source>failed to read savegame: %1</source> - <translation type="unfinished">無法讀å–å˜æª”: %1</translation> + <translation>讀å–å˜æª”失敗: %1</translation> </message> <message> <location filename="mainwindow.cpp" line="1053"/> <source>Plugin "%1" failed: %2</source> - <translation type="unfinished"></translation> + <translation>æ’ä»¶ "%1" 無效: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1055"/> <source>Plugin "%1" failed</source> - <translation type="unfinished"></translation> + <translation>æ’ä»¶ "%1" 無效</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1098"/> + <source>Download?</source> + <translation>下載?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1099"/> + <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"/> + </message> + <message> + <location filename="mainwindow.cpp" line="1140"/> + <source>Browse Mod Page</source> + <translation>ç€è¦½ Mod é é¢</translation> </message> <message> <location filename="mainwindow.cpp" line="1225"/> <source>failed to init plugin %1: %2</source> - <translation type="unfinished"></translation> + <translation>åˆå§‹åŒ–æ’ä»¶ %1 失敗: %2</translation> </message> <message> <location filename="mainwindow.cpp" line="1263"/> <source>Plugin error</source> - <translation type="unfinished"></translation> + <translation>æ’件錯誤</translation> </message> <message> <location filename="mainwindow.cpp" line="1264"/> <source>It appears the plugin "%1" failed to load last startup and caused MO to crash. Do you want to disable it? (Please note: If this is the first time you see this message for this plugin you may want to give it another try. The plugin may be able to recover from the problem)</source> - <translation type="unfinished"></translation> + <translation>æ’ä»¶ "%1" 在開始時載入失敗並導致 MO 崩潰。您想è¦é—œé–‰å®ƒå—Žï¼Ÿ +(請注æ„:如果這是您第一次看到有關這個æ’件的訊æ¯ï¼Œæ‚¨æœ€å¥½å†è®“它試一次。這個æ’ä»¶å¯èƒ½æœ‰è¾¦æ³•自å•題ä¸ä¿®å¾©ã€‚)</translation> </message> <message> <location filename="mainwindow.cpp" line="1323"/> <source>Failed to start "%1"</source> - <translation type="unfinished">無法啟動 "%1"</translation> + <translation>啟動 "%1" 失敗</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> <source>Waiting</source> - <translation type="unfinished">ç¨ç‰</translation> + <translation>ç¨ç‰</translation> </message> <message> <location filename="mainwindow.cpp" line="1325"/> <source>Please press OK once you're logged into steam.</source> - <translation type="unfinished">當您登入 Steam 時請點擊確定。</translation> + <translation>當您登入 Steam 後請點擊確定。</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="1337"/> + <source>Executable "%1" not found</source> + <translation>找ä¸åˆ°å¯åŸ·è¡Œç¨‹å¼ "%1"</translation> </message> <message> <location filename="mainwindow.cpp" line="1351"/> <source>Start Steam?</source> - <translation type="unfinished">啟動 Steam?</translation> + <translation>啟動 Steam?</translation> </message> <message> <location filename="mainwindow.cpp" line="1352"/> <source>Steam is required to be running already to correctly start the game. Should MO try to start steam now?</source> - <translation type="unfinished">æƒ³è¦æ£ç¢ºåœ°å•Ÿå‹•éŠæˆ²ï¼ŒSteam å¿…é ˆè™•æ–¼é‹è¡Œç‹€æ…‹ï¼ŒMO è¦ç«‹å³å•Ÿå‹• Steam 嗎?</translation> + <translation>Steam å¿…é ˆè™•æ–¼é‹è¡Œç‹€æ…‹ä»¥æ£ç¢ºåœ°å•Ÿå‹•éŠæˆ²ï¼ŒMO è¦ç«‹å³å•Ÿå‹• Steam 嗎?</translation> </message> <message> - <location filename="mainwindow.cpp" line="1562"/> + <location filename="mainwindow.cpp" line="1572"/> <source>Also in: <br></source> - <translation type="unfinished">也在: <br></translation> + <translation>也在: <br></translation> </message> <message> - <location filename="mainwindow.cpp" line="1573"/> + <location filename="mainwindow.cpp" line="1583"/> <source>No conflict</source> - <translation type="unfinished">沒有è¡çª</translation> + <translation>沒有è¡çª</translation> </message> <message> - <location filename="mainwindow.cpp" line="1742"/> + <location filename="mainwindow.cpp" line="1752"/> <source><Edit...></source> - <translation type="unfinished"><編輯...></translation> + <translation><編輯...></translation> </message> <message> - <location filename="mainwindow.cpp" line="2008"/> - <source>This bsa is enabled in the ini file so it may be required!</source> - <translation type="unfinished">該 BSA 已在 Ini 檔案ä¸å•Ÿç”¨ï¼Œå› æ¤å®ƒå¯èƒ½æ˜¯å¿…需的。</translation> + <location filename="mainwindow.cpp" line="1849"/> + <source>Failed to refresh list of esps: %1</source> + <translation>釿–°æ•´ç† esp 列表失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2070"/> - <source>Activating Network Proxy</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2025"/> + <source>This bsa is enabled in the ini file so it may be required!</source> + <translation>該 BSA 已在 Ini 檔案ä¸å•Ÿç”¨ï¼Œå› æ¤å®ƒå¯èƒ½æ˜¯å¿…需的。</translation> </message> <message> - <location filename="mainwindow.cpp" line="2310"/> - <location filename="mainwindow.cpp" line="4349"/> - <source>Installation successful</source> - <translation type="unfinished">å®‰è£æˆåŠŸ</translation> + <location filename="mainwindow.cpp" line="2087"/> + <source>Activating Network Proxy</source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2321"/> - <location filename="mainwindow.cpp" line="4361"/> - <source>Configure Mod</source> - <translation type="unfinished">é…ç½® Mod</translation> + <location filename="mainwindow.cpp" line="2201"/> + <location filename="mainwindow.cpp" line="2208"/> + <source>Failed to write settings</source> + <translation>寫入è¨å®šå¤±æ•—</translation> </message> <message> - <location filename="mainwindow.cpp" line="2322"/> - <location filename="mainwindow.cpp" line="4362"/> - <source>This mod contains ini tweaks. Do you want to configure them now?</source> - <translation type="unfinished">æ¤ Mod ä¸åŒ…å« Ini è¨å®šæª”案,您想ç¾åœ¨å°±å°å®ƒå€‘進行é…置嗎?</translation> + <location filename="mainwindow.cpp" line="2202"/> + <location filename="mainwindow.cpp" line="2209"/> + <source>An error occured trying to write back MO settings: %1</source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2329"/> - <location filename="mainwindow.cpp" line="4369"/> - <source>mod "%1" not found</source> - <translation type="unfinished">Mod "%1" 未找到</translation> + <location filename="mainwindow.cpp" line="2205"/> + <source>File is write protected</source> + <translation>檔案是唯ç¨çš„狀態</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>Installation cancelled</source> - <translation type="unfinished">安è£å·²å–消</translation> + <location filename="mainwindow.cpp" line="2206"/> + <source>Invalid file format (probably a bug)</source> + <translation>ç„¡æ•ˆçš„æª”æ¡ˆæ ¼å¼ (å¯èƒ½æ˜¯ bug)</translation> </message> <message> - <location filename="mainwindow.cpp" line="2332"/> - <location filename="mainwindow.cpp" line="4375"/> - <source>The mod was not installed completely.</source> - <translation type="unfinished">Mod 沒有完全安è£ã€‚</translation> + <location filename="mainwindow.cpp" line="2207"/> + <source>Unknown error %1</source> + <translation>未知錯誤 %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2237"/> + <location filename="mainwindow.cpp" line="2254"/> <source>Some plugins could not be loaded</source> - <translation type="unfinished"></translation> + <translation>有些æ’件無法被載入</translation> </message> <message> - <location filename="mainwindow.cpp" line="2240"/> + <location filename="mainwindow.cpp" line="2257"/> <source>Too many esps and esms enabled</source> - <translation type="unfinished"></translation> + <translation>éŽå¤šçš„ esp å’Œ esm 啟動</translation> </message> <message> - <location filename="mainwindow.cpp" line="2243"/> - <location filename="mainwindow.cpp" line="2264"/> + <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2281"/> <source>Description missing</source> - <translation type="unfinished"></translation> + <translation>æè¿°éºå¤±</translation> </message> <message> - <location filename="mainwindow.cpp" line="2252"/> + <location filename="mainwindow.cpp" line="2269"/> <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> + <translation>以下的æ’ä»¶ç„¡æ³•è¢«è¼‰å…¥ã€‚åŽŸå› å¯èƒ½æ˜¯å› 為éºå¤±äº†å®ƒçš„ä¾å˜æª”案(例如 python)æˆ–æ˜¯éŽæœŸçš„版本:</translation> </message> <message> - <location filename="mainwindow.cpp" line="2260"/> + <location filename="mainwindow.cpp" line="2277"/> <source>The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or merge some plugins into one. You can find a guide here: <a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></source> - <translation type="unfinished"></translation> + <translation>éŠæˆ²ä¸å…è¨±è¶…éŽ 255 個啟動的æ’ä»¶(包括æ£å¼çš„)è¢«è¼‰å…¥ã€‚æ‚¨å¿…é ˆé—œé–‰ä¸€äº›æœªä½¿ç”¨çš„æ’件或是åˆä½µä¸€äº›æ’件。您å¯ä»¥åœ¨æ¤æ‰¾åˆ°å°Žè¦½:<a href="http://wiki.step-project.com/Guide:Merging_Plugins">http://wiki.step-project.com/Guide:Merging_Plugins</a></translation> </message> <message> - <location filename="mainwindow.cpp" line="2286"/> + <location filename="mainwindow.cpp" line="2303"/> <source>Choose Mod</source> - <translation type="unfinished">鏿“‡ Mod</translation> + <translation>鏿“‡ Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="2287"/> + <location filename="mainwindow.cpp" line="2304"/> <source>Mod Archive</source> - <translation type="unfinished">Mod 壓縮包</translation> + <translation>Mod 壓縮包</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2327"/> + <location filename="mainwindow.cpp" line="4382"/> + <source>Installation successful</source> + <translation>å®‰è£æˆåŠŸ</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2338"/> + <location filename="mainwindow.cpp" line="4394"/> + <source>Configure Mod</source> + <translation>é…ç½® Mod</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2339"/> + <location filename="mainwindow.cpp" line="4395"/> + <source>This mod contains ini tweaks. Do you want to configure them now?</source> + <translation>æ¤ Mod ä¸åŒ…å« ini è¨å®šæª”案,您想ç¾åœ¨å°±å°å®ƒå€‘進行é…置嗎?</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2346"/> + <location filename="mainwindow.cpp" line="4402"/> + <source>mod "%1" not found</source> + <translation>Mod "%1" 未找到</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>Installation cancelled</source> + <translation>安è£å·²å–消</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="2349"/> + <location filename="mainwindow.cpp" line="4408"/> + <source>The mod was not installed completely.</source> + <translation>Mod 沒有完全安è£ã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="2541"/> + <location filename="mainwindow.cpp" line="2558"/> <source>Start Tutorial?</source> - <translation type="unfinished"></translation> + <translation>é–‹å§‹æ•™å¸ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="2542"/> + <location filename="mainwindow.cpp" line="2559"/> <source>You're about to start a tutorial. For technical reasons it's not possible to end the tutorial early. Continue?</source> - <translation type="unfinished"></translation> + <translation>您å³å°‡é–‹å§‹æ•™å¸ã€‚å› ç‚ºæŠ€è¡“ä¸Šçš„åŽŸå› æ‰€å·²ç„¡æ³•æå‰çµæŸæ•™å¸ã€‚繼續?</translation> </message> <message> - <location filename="mainwindow.cpp" line="2686"/> - <location filename="mainwindow.cpp" line="4274"/> + <location filename="mainwindow.cpp" line="2703"/> + <location filename="mainwindow.cpp" line="4307"/> <source>Download started</source> - <translation type="unfinished">開始下載</translation> + <translation>開始下載</translation> </message> <message> - <location filename="mainwindow.cpp" line="2747"/> + <location filename="mainwindow.cpp" line="2764"/> <source>failed to update mod list: %1</source> - <translation type="unfinished">無法更新 Mod 列表: %1</translation> + <translation>æ›´æ–° Mod 列表失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2791"/> + <location filename="mainwindow.cpp" line="2808"/> <source>failed to spawn notepad.exe: %1</source> - <translation type="unfinished">ç„¡æ³•ç”Ÿæˆ notepad.exe: %1</translation> + <translation>ç”Ÿæˆ notepad.exe 失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="2828"/> + <location filename="mainwindow.cpp" line="2845"/> <source>failed to open %1</source> - <translation type="unfinished">無法開啟 %1</translation> + <translation>開啟 %1 失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="2903"/> + <location filename="mainwindow.cpp" line="2920"/> <source>failed to change origin name: %1</source> - <translation type="unfinished">無法更改原始檔案å: %1</translation> + <translation>更改原始檔å失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="1337"/> - <source>Executable "%1" not found</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1839"/> - <source>Failed to refresh list of esps: %1</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2950"/> + <source>failed to move "%1" from mod "%2" to "%3": %4</source> + <translation>自 Mod "%2" 移動 "%1" 到 Mod "%3" 失敗: %4</translation> </message> <message> - <location filename="mainwindow.cpp" line="2933"/> - <source>failed to move "%1" from mod "%2" to "%3": %4</source> - <translation type="unfinished"></translation> + <location filename="mainwindow.cpp" line="2973"/> + <source><Contains %1></source> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="2983"/> + <location filename="mainwindow.cpp" line="3006"/> <source><Checked></source> - <translation type="unfinished"><已勾é¸></translation> + <translation><已勾é¸></translation> </message> <message> - <location filename="mainwindow.cpp" line="2984"/> + <location filename="mainwindow.cpp" line="3007"/> <source><Unchecked></source> - <translation type="unfinished"><未勾é¸></translation> + <translation><未勾é¸></translation> </message> <message> - <location filename="mainwindow.cpp" line="2985"/> + <location filename="mainwindow.cpp" line="3008"/> <source><Update></source> - <translation type="unfinished"><有更新></translation> + <translation><有更新></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3009"/> + <source><Managed by MO></source> + <translation><ç”± MO 管ç†></translation> </message> <message> - <location filename="mainwindow.cpp" line="2988"/> + <location filename="mainwindow.cpp" line="3010"/> + <source><Managed outside MO></source> + <translation><éžç”± MO 管ç†></translation> + </message> + <message> + <location filename="mainwindow.cpp" line="3011"/> <source><No category></source> - <translation type="unfinished"><無類別></translation> + <translation><無類別></translation> </message> <message> - <location filename="mainwindow.cpp" line="2989"/> + <location filename="mainwindow.cpp" line="3012"/> <source><Conflicted></source> - <translation type="unfinished"></translation> + <translation><有è¡çª></translation> </message> <message> - <location filename="mainwindow.cpp" line="2990"/> + <location filename="mainwindow.cpp" line="3013"/> <source><Not Endorsed></source> - <translation type="unfinished"></translation> + <translation><尚未贊åŒ></translation> </message> <message> - <location filename="mainwindow.cpp" line="3026"/> + <location filename="mainwindow.cpp" line="3051"/> <source>failed to rename mod: %1</source> - <translation type="unfinished">ç„¡æ³•é‡æ–°å‘½å Mod: %1</translation> + <translation>釿–°å‘½å Mod 失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3039"/> + <location filename="mainwindow.cpp" line="3064"/> <source>Overwrite?</source> - <translation type="unfinished">覆蓋</translation> + <translation>覆蓋?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3040"/> + <location filename="mainwindow.cpp" line="3065"/> <source>This will replace the existing mod "%1". Continue?</source> - <translation type="unfinished"></translation> + <translation>å³å°‡å–代已å˜åœ¨çš„ Mod "%1"。繼續?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3043"/> + <location filename="mainwindow.cpp" line="3068"/> <source>failed to remove mod "%1"</source> - <translation type="unfinished">無法移動 Mod: %1</translation> + <translation>移除 Mod 失敗 "%1"</translation> </message> <message> - <location filename="mainwindow.cpp" line="3047"/> - <location filename="mainwindow.cpp" line="4547"/> - <location filename="mainwindow.cpp" line="4571"/> + <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="4580"/> + <location filename="mainwindow.cpp" line="4604"/> <source>failed to rename "%1" to "%2"</source> <translation>釿–°å‘½å "%1 "為 "%2" 時出錯</translation> </message> <message> - <location filename="mainwindow.cpp" line="3072"/> + <location filename="mainwindow.cpp" line="3097"/> <source>Multiple esps activated, please check that they don't conflict.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3121"/> - <location filename="mainwindow.cpp" line="3746"/> - <location filename="mainwindow.cpp" line="3754"/> - <location filename="mainwindow.cpp" line="3981"/> + <location filename="mainwindow.cpp" line="3146"/> + <location filename="mainwindow.cpp" line="3771"/> + <location filename="mainwindow.cpp" line="3779"/> + <location filename="mainwindow.cpp" line="4014"/> <source>Confirm</source> - <translation type="unfinished">確èª</translation> + <translation>確èª</translation> </message> <message> - <location filename="mainwindow.cpp" line="3122"/> + <location filename="mainwindow.cpp" line="3147"/> <source>Remove the following mods?<br><ul>%1</ul></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3133"/> + <location filename="mainwindow.cpp" line="3158"/> <source>failed to remove mod: %1</source> - <translation type="unfinished">無法移動 Mod: %1</translation> + <translation>移除 Mod 失敗: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> - <location filename="mainwindow.cpp" line="3171"/> + <location filename="mainwindow.cpp" line="3193"/> + <location filename="mainwindow.cpp" line="3196"/> <source>Failed</source> - <translation type="unfinished">失敗</translation> + <translation>失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="3168"/> + <location filename="mainwindow.cpp" line="3193"/> <source>Installation file no longer exists</source> - <translation type="unfinished">å®‰è£æª”案ä¸è¤‡å˜åœ¨</translation> + <translation>å®‰è£æª”案ä¸å¾©å˜åœ¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="3172"/> + <location filename="mainwindow.cpp" line="3197"/> <source>Mods installed with old versions of MO can't be reinstalled in this way.</source> - <translation type="unfinished">舊版 MO 安è£çš„ Mod ç„¡æ³•ä½¿ç”¨æ¤æ–¹æ³•釿–°å®‰è£ã€‚</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3203"/> - <location filename="mainwindow.cpp" line="3230"/> - <source>You need to be logged in with Nexus to endorse</source> - <translation type="unfinished"></translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="3981"/> - <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> - <translation type="unfinished"> - <numerusform></numerusform> - </translation> - </message> - <message numerus="yes"> - <location filename="mainwindow.cpp" line="4095"/> - <source>Delete %n save(s)</source> - <translation type="unfinished"> - <numerusform></numerusform> - </translation> + <translation>舊版 MO 安è£çš„ Mod ç„¡æ³•ä½¿ç”¨æ¤æ–¹æ³•釿–°å®‰è£ã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="4974"/> - <source>Extract BSA</source> - <translation type="unfinished">解壓 BSA</translation> + <location filename="mainwindow.cpp" line="3212"/> + <source>You need to be logged in with Nexus to resume a download</source> + <translation>æ‚¨å¿…é ˆç™»å…¥N網以回復下載。</translation> </message> <message> - <location filename="mainwindow.cpp" line="4931"/> - <location filename="mainwindow.cpp" line="4982"/> - <source>failed to read %1: %2</source> - <translation type="unfinished">ç„¡æ³•è®€å– %1: %2</translation> + <location filename="mainwindow.cpp" line="3228"/> + <location filename="mainwindow.cpp" line="3255"/> + <source>You need to be logged in with Nexus to endorse</source> + <translation>æ‚¨å¿…é ˆç™»å…¥N網以贊åŒã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="4993"/> - <source>This archive contains invalid hashes. Some files may be broken.</source> - <translation type="unfinished">壓縮包 Hash 值錯誤。部分檔案å¯èƒ½å·²ç¶“æå£žã€‚</translation> + <location filename="mainwindow.cpp" line="3289"/> + <source>Failed to display overwrite dialog: %1</source> + <translation>顯示覆蓋的å°è©±å¤±æ•—: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="3382"/> + <location filename="mainwindow.cpp" line="3407"/> <source>Nexus ID for this Mod is unknown</source> - <translation type="unfinished">æ¤ Mod çš„Nç¶² ID 未知</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1098"/> - <source>Download?</source> - <translation type="unfinished">下載</translation> - </message> - <message> - <location filename="mainwindow.cpp" line="1099"/> - <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="mainwindow.cpp" line="1140"/> - <source>Browse Mod Page</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2184"/> - <location filename="mainwindow.cpp" line="2191"/> - <source>Failed to write settings</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2185"/> - <location filename="mainwindow.cpp" line="2192"/> - <source>An error occured trying to write back MO settings: %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2188"/> - <source>File is write protected</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2189"/> - <source>Invalid file format (probably a bug)</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2190"/> - <source>Unknown error %1</source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2986"/> - <source><Managed by MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="2987"/> - <source><Managed outside MO></source> - <translation type="unfinished"></translation> - </message> - <message> - <location filename="mainwindow.cpp" line="3187"/> - <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="3264"/> - <source>Failed to display overwrite dialog: %1</source> - <translation type="unfinished"></translation> + <translation>æ¤ Mod çš„Nç¶² ID 未知</translation> </message> <message> - <location filename="mainwindow.cpp" line="3421"/> - <location filename="mainwindow.cpp" line="3861"/> + <location filename="mainwindow.cpp" line="3446"/> + <location filename="mainwindow.cpp" line="3886"/> <source>Create Mod...</source> - <translation type="unfinished"></translation> + <translation>å‰µé€ Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3422"/> + <location filename="mainwindow.cpp" line="3447"/> <source>This will move all files from overwrite into a new, regular mod. Please enter a name:</source> - <translation type="unfinished"></translation> + <translation>å³å°‡ç§»å‹•所有在 overwrite çš„æª”æ¡ˆåˆ°ä¸€å€‹æ–°çš„ã€æ£å¸¸çš„ Mod。 +請輸入一個å稱:</translation> </message> <message> - <location filename="mainwindow.cpp" line="3431"/> + <location filename="mainwindow.cpp" line="3456"/> <source>A mod with this name already exists</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3672"/> + <location filename="mainwindow.cpp" line="3697"/> <source>Continue?</source> - <translation type="unfinished"></translation> + <translation>繼續?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3673"/> + <location filename="mainwindow.cpp" line="3698"/> <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> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3693"/> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="3718"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry</source> - <translation type="unfinished"></translation> + <translation>抱æ‰</translation> </message> <message> - <location filename="mainwindow.cpp" line="3694"/> + <location filename="mainwindow.cpp" line="3719"/> <source>I don't know a versioning scheme where %1 is newer than %2.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3746"/> + <location filename="mainwindow.cpp" line="3771"/> <source>Really enable all visible mods?</source> - <translation type="unfinished">確定è¦å•Ÿç”¨å…¨éƒ¨å¯è¦‹çš„ Mod 嗎?</translation> + <translation>確定è¦å•Ÿç”¨æ‰€æœ‰å¯è¦‹çš„ Mod 嗎?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3754"/> + <location filename="mainwindow.cpp" line="3779"/> <source>Really disable all visible mods?</source> - <translation type="unfinished">確定è¦ç¦ç”¨å…¨éƒ¨å¯è¦‹çš„ Mod 嗎?</translation> + <translation>確定è¦ç¦ç”¨æ‰€æœ‰å¯è¦‹çš„ Mod 嗎?</translation> </message> <message> - <location filename="mainwindow.cpp" line="3762"/> + <location filename="mainwindow.cpp" line="3787"/> <source>Choose what to export</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>Everything</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3764"/> + <location filename="mainwindow.cpp" line="3789"/> <source>All installed mods are included in the list</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Active Mods</source> - <translation type="unfinished">激活 Mod</translation> + <translation>啟動 Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3765"/> + <location filename="mainwindow.cpp" line="3790"/> <source>Only active (checked) mods from your current profile are included</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>Visible</source> - <translation type="unfinished"></translation> + <translation>å¯è¦‹çš„</translation> </message> <message> - <location filename="mainwindow.cpp" line="3766"/> + <location filename="mainwindow.cpp" line="3791"/> <source>All mods visible in the mod list are included</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3809"/> + <location filename="mainwindow.cpp" line="3834"/> <source>export failed: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3826"/> + <location filename="mainwindow.cpp" line="3851"/> <source>Install Mod...</source> - <translation type="unfinished">å®‰è£ Mod...</translation> + <translation>å®‰è£ Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3828"/> + <location filename="mainwindow.cpp" line="3853"/> <source>Enable all visible</source> - <translation type="unfinished">啟用所有å¯è¦‹é …ç›®</translation> + <translation>啟用所有å¯è¦‹é …ç›®</translation> </message> <message> - <location filename="mainwindow.cpp" line="3829"/> + <location filename="mainwindow.cpp" line="3854"/> <source>Disable all visible</source> - <translation type="unfinished">ç¦ç”¨æ‰€æœ‰å¯è¦‹é …ç›®</translation> + <translation>ç¦ç”¨æ‰€æœ‰å¯è¦‹é …ç›®</translation> </message> <message> - <location filename="mainwindow.cpp" line="3831"/> + <location filename="mainwindow.cpp" line="3856"/> <source>Check all for update</source> - <translation type="unfinished">檢查更新</translation> + <translation>檢查所有的更新</translation> </message> <message> - <location filename="mainwindow.cpp" line="3835"/> + <location filename="mainwindow.cpp" line="3860"/> <source>Export to csv...</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3854"/> + <location filename="mainwindow.cpp" line="3879"/> <source>All Mods</source> - <translation type="unfinished"></translation> + <translation>所有 Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3860"/> + <location filename="mainwindow.cpp" line="3885"/> <source>Sync to Mods...</source> - <translation type="unfinished">åŒæ¥åˆ° Mod...</translation> + <translation>åŒæ¥åˆ° Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3864"/> + <location filename="mainwindow.cpp" line="3889"/> <source>Restore Backup</source> - <translation type="unfinished"></translation> + <translation>回復備份</translation> </message> <message> - <location filename="mainwindow.cpp" line="3865"/> + <location filename="mainwindow.cpp" line="3890"/> <source>Remove Backup...</source> - <translation type="unfinished"></translation> + <translation>移除備份</translation> </message> <message> - <location filename="mainwindow.cpp" line="3869"/> + <location filename="mainwindow.cpp" line="3894"/> <source>Add/Remove Categories</source> - <translation type="unfinished"></translation> + <translation>å¢žåŠ /移除類別</translation> </message> <message> - <location filename="mainwindow.cpp" line="3874"/> + <location filename="mainwindow.cpp" line="3899"/> <source>Replace Categories</source> - <translation type="unfinished"></translation> + <translation>å–代類別</translation> </message> <message> - <location filename="mainwindow.cpp" line="3879"/> + <location filename="mainwindow.cpp" line="3904"/> <source>Primary Category</source> - <translation type="unfinished"></translation> + <translation>主è¦é¡žåˆ¥</translation> </message> <message> - <location filename="mainwindow.cpp" line="3886"/> + <location filename="mainwindow.cpp" line="3911"/> <source>Change versioning scheme</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="3890"/> + <location filename="mainwindow.cpp" line="3915"/> <source>Un-ignore update</source> - <translation type="unfinished"></translation> + <translation>å–æ¶ˆå¿½ç•¥æ›´æ–°</translation> </message> <message> - <location filename="mainwindow.cpp" line="3892"/> + <location filename="mainwindow.cpp" line="3917"/> <source>Ignore update</source> - <translation type="unfinished"></translation> + <translation>忽略更新</translation> </message> <message> - <location filename="mainwindow.cpp" line="3897"/> + <location filename="mainwindow.cpp" line="3922"/> <source>Rename Mod...</source> - <translation type="unfinished">釿–°å‘½å...</translation> + <translation>釿–°å‘½å Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3898"/> + <location filename="mainwindow.cpp" line="3923"/> <source>Remove Mod...</source> - <translation type="unfinished">移除 Mod...</translation> + <translation>移除 Mod...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3899"/> + <location filename="mainwindow.cpp" line="3924"/> <source>Reinstall Mod</source> - <translation type="unfinished">釿–°å®‰è£ Mod</translation> + <translation>釿–°å®‰è£ Mod</translation> </message> <message> - <location filename="mainwindow.cpp" line="3902"/> + <location filename="mainwindow.cpp" line="3927"/> <source>Un-Endorse</source> - <translation type="unfinished"></translation> + <translation>å–æ¶ˆè´ŠåŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3905"/> - <location filename="mainwindow.cpp" line="3909"/> + <location filename="mainwindow.cpp" line="3930"/> + <location filename="mainwindow.cpp" line="3934"/> <source>Endorse</source> - <translation type="unfinished"></translation> + <translation>è´ŠåŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3906"/> + <location filename="mainwindow.cpp" line="3931"/> <source>Won't endorse</source> - <translation type="unfinished"></translation> + <translation>拒絕贊åŒ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3912"/> + <location filename="mainwindow.cpp" line="3937"/> <source>Endorsement state unknown</source> - <translation type="unfinished"></translation> + <translation>è´ŠåŒç‹€æ…‹ä¸æ˜Ž</translation> </message> <message> - <location filename="mainwindow.cpp" line="3919"/> + <location filename="mainwindow.cpp" line="3944"/> <source>Ignore missing data</source> - <translation type="unfinished"></translation> + <translation>忽略éºå¤±çš„æª”案</translation> </message> <message> - <location filename="mainwindow.cpp" line="3922"/> + <location filename="mainwindow.cpp" line="3947"/> <source>Visit on Nexus</source> - <translation type="unfinished">在N網上æµè¦½</translation> + <translation>在N網上訪å•</translation> </message> <message> - <location filename="mainwindow.cpp" line="3923"/> + <location filename="mainwindow.cpp" line="3948"/> <source>Open in explorer</source> - <translation type="unfinished">在檔案總管ä¸é–‹å•Ÿ</translation> + <translation>在檔案總管ä¸é–‹å•Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="3927"/> + <location filename="mainwindow.cpp" line="3952"/> <source>Information...</source> - <translation type="unfinished">訊æ¯...</translation> + <translation>訊æ¯...</translation> </message> <message> - <location filename="mainwindow.cpp" line="3934"/> - <location filename="mainwindow.cpp" line="5192"/> + <location filename="mainwindow.cpp" line="3959"/> + <location filename="mainwindow.cpp" line="5225"/> <source>Exception: </source> - <translation type="unfinished">例外: </translation> + <translation>例外: </translation> </message> <message> - <location filename="mainwindow.cpp" line="3936"/> - <location filename="mainwindow.cpp" line="5194"/> + <location filename="mainwindow.cpp" line="3961"/> + <location filename="mainwindow.cpp" line="5227"/> <source>Unknown exception</source> - <translation type="unfinished">未知的例外</translation> + <translation>未知的例外</translation> </message> <message> - <location filename="mainwindow.cpp" line="3955"/> + <location filename="mainwindow.cpp" line="3988"/> <source><All></source> - <translation type="unfinished"><全部></translation> + <translation><全部></translation> </message> <message> - <location filename="mainwindow.cpp" line="3957"/> + <location filename="mainwindow.cpp" line="3990"/> <source><Multiple></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> + </message> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4014"/> + <source>Are you sure you want to remove the following %n save(s)?<br><ul>%1</ul><br>Removed saves will be sent to the Recycle Bin.</source> + <translation type="unfinished"><numerusform></numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="5450"/> + <location filename="mainwindow.cpp" line="5483"/> <source>Please wait while LOOT is running</source> - <translation type="unfinished"></translation> + <translation>在 LOOT 執行時請ç‰å¾…</translation> </message> <message> - <location filename="mainwindow.cpp" line="4093"/> + <location filename="mainwindow.cpp" line="4126"/> <source>Fix Mods...</source> - <translation type="unfinished">修復 Mod...</translation> + <translation>修復 Mod...</translation> </message> - <message> - <source>Delete</source> - <translation type="obsolete">&刪除</translation> + <message numerus="yes"> + <location filename="mainwindow.cpp" line="4128"/> + <source>Delete %n save(s)</source> + <translation><numerusform>åˆªé™¤å˜æª” %n</numerusform></translation> </message> <message> - <location filename="mainwindow.cpp" line="4122"/> <location filename="mainwindow.cpp" line="4155"/> + <location filename="mainwindow.cpp" line="4188"/> <source>failed to remove %1</source> - <translation type="unfinished">無法刪除 %1</translation> + <translation>刪除 %1 失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="4139"/> - <location filename="mainwindow.cpp" line="4171"/> + <location filename="mainwindow.cpp" line="4172"/> + <location filename="mainwindow.cpp" line="4204"/> <source>failed to create %1</source> - <translation type="unfinished">無法建立 %1</translation> + <translation>建立 %1 失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="4195"/> + <location filename="mainwindow.cpp" line="4228"/> <source>Can't change download directory while downloads are in progress!</source> - <translation type="unfinished">下載檔案時ä¸èƒ½ä¿®æ”¹ä¸‹è¼‰ç›®éŒ„ï¼</translation> + <translation>下載檔案時ä¸èƒ½ä¿®æ”¹ä¸‹è¼‰è·¯å¾‘ï¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4277"/> + <location filename="mainwindow.cpp" line="4310"/> <source>Download failed</source> - <translation type="unfinished">下載失敗</translation> + <translation>下載失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="4424"/> + <location filename="mainwindow.cpp" line="4457"/> <source>failed to write to file %1</source> - <translation type="unfinished">無法寫入檔案 %1</translation> + <translation>寫入檔案 %1 失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="4430"/> + <location filename="mainwindow.cpp" line="4463"/> <source>%1 written</source> - <translation type="unfinished">已寫入 %1</translation> + <translation>已寫入 %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Select binary</source> - <translation type="unfinished">鏿“‡å¯åŸ·è¡Œæª”案</translation> + <translation>鏿“‡å¯åŸ·è¡Œæª”案</translation> </message> <message> - <location filename="mainwindow.cpp" line="4469"/> + <location filename="mainwindow.cpp" line="4502"/> <source>Binary</source> <translation>程å¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4495"/> + <location filename="mainwindow.cpp" line="4528"/> <source>Enter Name</source> - <translation type="unfinished">輸入å稱</translation> + <translation>輸入å稱</translation> </message> <message> - <location filename="mainwindow.cpp" line="4496"/> + <location filename="mainwindow.cpp" line="4529"/> <source>Please enter a name for the executable</source> - <translation type="unfinished">請為程å¼è¼¸å…¥ä¸€å€‹å稱</translation> + <translation>請為程å¼è¼¸å…¥ä¸€å€‹å稱</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>Not an executable</source> - <translation type="unfinished">䏿˜¯å¯åŸ·è¡Œç¨‹å¼</translation> + <translation>䏿˜¯å¯åŸ·è¡Œç¨‹å¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4507"/> + <location filename="mainwindow.cpp" line="4540"/> <source>This is not a recognized executable.</source> - <translation type="unfinished">無法è˜åˆ¥çš„å¯åŸ·è¡Œæª”案</translation> + <translation>無法è˜åˆ¥çš„å¯åŸ·è¡Œæª”案</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4565"/> + <location filename="mainwindow.cpp" line="4590"/> <source>Replace file?</source> - <translation type="unfinished">å–代檔案?</translation> + <translation>å–代檔案?</translation> </message> <message> - <location filename="mainwindow.cpp" line="4532"/> + <location filename="mainwindow.cpp" line="4565"/> <source>There already is a hidden version of this file. Replace it?</source> - <translation type="unfinished">å·²å˜åœ¨åŒå檔案,但該檔案被隱è—了。確定è¦è¦†è“‹å—Žï¼Ÿ</translation> + <translation>å·²å˜åœ¨åŒå檔案,但該檔案被隱è—了。確定è¦è¦†è“‹å—Žï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>File operation failed</source> - <translation type="unfinished">檔案æ“作錯誤</translation> + <translation>檔案æ“作失敗</translation> </message> <message> - <location filename="mainwindow.cpp" line="4535"/> - <location filename="mainwindow.cpp" line="4560"/> + <location filename="mainwindow.cpp" line="4568"/> + <location filename="mainwindow.cpp" line="4593"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>無法移除 "%1"。也許您需è¦è¶³å¤ 的檔案權é™ï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4557"/> + <location filename="mainwindow.cpp" line="4590"/> <source>There already is a visible version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå檔案。確定è¦è¦†è“‹å—Žï¼Ÿ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4590"/> + <location filename="mainwindow.cpp" line="4623"/> <source>file not found: %1</source> - <translation type="unfinished"></translation> + <translation>找ä¸åˆ°æª”案: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4603"/> + <location filename="mainwindow.cpp" line="4636"/> <source>failed to generate preview for %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4617"/> + <location filename="mainwindow.cpp" line="4650"/> <source>Sorry, can't preview anything. This function currently does not support extracting from bsas.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4648"/> + <location filename="mainwindow.cpp" line="4681"/> <source>Update available</source> - <translation type="unfinished">æ›´æ–°å¯ç”¨</translation> + <translation>有å¯ç”¨çš„æ›´æ–°</translation> </message> <message> - <location filename="mainwindow.cpp" line="4685"/> + <location filename="mainwindow.cpp" line="4718"/> <source>Open/Execute</source> - <translation type="unfinished">開啟/執行</translation> + <translation>開啟/執行</translation> </message> <message> - <location filename="mainwindow.cpp" line="4686"/> + <location filename="mainwindow.cpp" line="4719"/> <source>Add as Executable</source> - <translation type="unfinished">æ·»åŠ ç‚ºå¯åŸ·è¡Œæª”案</translation> + <translation>æ·»åŠ ç‚ºå¯åŸ·è¡Œæª”案</translation> </message> <message> - <location filename="mainwindow.cpp" line="4690"/> + <location filename="mainwindow.cpp" line="4723"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation>é 覽</translation> </message> <message> - <location filename="mainwindow.cpp" line="4696"/> + <location filename="mainwindow.cpp" line="4729"/> <source>Un-Hide</source> - <translation type="unfinished">å–æ¶ˆéš±è—</translation> + <translation>å–æ¶ˆéš±è—</translation> </message> <message> - <location filename="mainwindow.cpp" line="4698"/> + <location filename="mainwindow.cpp" line="4731"/> <source>Hide</source> - <translation type="unfinished">éš±è—</translation> + <translation>éš±è—</translation> </message> <message> - <location filename="mainwindow.cpp" line="4704"/> + <location filename="mainwindow.cpp" line="4737"/> <source>Write To File...</source> - <translation type="unfinished">寫入檔案...</translation> + <translation>寫入檔案...</translation> </message> <message> - <location filename="mainwindow.cpp" line="4729"/> + <location filename="mainwindow.cpp" line="4762"/> <source>Do you want to endorse Mod Organizer on %1 now?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you!</source> - <translation type="unfinished"></translation> + <translation>è¬è¬æ‚¨ï¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4825"/> + <location filename="mainwindow.cpp" line="4858"/> <source>Thank you for your endorsement!</source> - <translation type="unfinished"></translation> + <translation>æ„Ÿè¬æ‚¨çš„è´ŠåŒï¼</translation> </message> <message> - <location filename="mainwindow.cpp" line="4860"/> + <location filename="mainwindow.cpp" line="4893"/> <source>Request to Nexus failed: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="4867"/> - <location filename="mainwindow.cpp" line="4885"/> + <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4918"/> <source>login successful</source> - <translation type="unfinished">登入æˆåŠŸ</translation> + <translation>登入æˆåŠŸ</translation> </message> <message> - <location filename="mainwindow.cpp" line="4894"/> + <location filename="mainwindow.cpp" line="4927"/> <source>login failed: %1. Trying to download anyway</source> - <translation type="unfinished">登入失敗: %1,請嘗試使用別的方法下載</translation> + <translation>登入失敗: %1,ä»ç„¶å˜—試下載</translation> </message> <message> - <location filename="mainwindow.cpp" line="4900"/> + <location filename="mainwindow.cpp" line="4933"/> <source>login failed: %1</source> <translation>無法登入: %1</translation> </message> <message> - <location filename="mainwindow.cpp" line="4910"/> + <location filename="mainwindow.cpp" line="4943"/> <source>login failed: %1. You need to log-in with Nexus to update MO.</source> - <translation type="unfinished">登入失敗: %1。您需è¦ç™»å…¥åˆ°Nç¶²æ‰èƒ½æ›´æ–° MO</translation> + <translation>登入失敗: %1。您需è¦ç™»å…¥åˆ°Nç¶²æ‰èƒ½æ›´æ–° MO</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4964"/> + <location filename="mainwindow.cpp" line="5015"/> + <source>failed to read %1: %2</source> + <translation>è®€å– %1 失敗: %2</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="4976"/> <source>Error</source> - <translation type="unfinished">錯誤</translation> + <translation>錯誤</translation> </message> <message> - <location filename="mainwindow.cpp" line="4943"/> + <location filename="mainwindow.cpp" line="4976"/> <source>failed to extract %1 (errorcode %2)</source> - <translation type="unfinished">無法解壓 %1 (錯誤代碼 %2)</translation> + <translation>解壓 %1 失敗(錯誤代碼 %2)</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5007"/> + <source>Extract BSA</source> + <translation>解壓 BSA</translation> + </message> + <message> + <location filename="mainwindow.cpp" line="5026"/> + <source>This archive contains invalid hashes. Some files may be broken.</source> + <translation>壓縮包的 Hash 值錯誤。部分檔案å¯èƒ½å·²ç¶“æå£žã€‚</translation> </message> <message> - <location filename="mainwindow.cpp" line="5038"/> + <location filename="mainwindow.cpp" line="5071"/> <source>Extract...</source> - <translation type="unfinished">解壓...</translation> + <translation>解壓...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5100"/> + <location filename="mainwindow.cpp" line="5133"/> <source>Edit Categories...</source> - <translation type="unfinished">編輯類別...</translation> + <translation>編輯類別...</translation> </message> <message> - <location filename="mainwindow.cpp" line="5101"/> + <location filename="mainwindow.cpp" line="5134"/> <source>Deselect filter</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5152"/> + <location filename="mainwindow.cpp" line="5185"/> <source>Remove</source> <translation>移除</translation> </message> <message> - <location filename="mainwindow.cpp" line="5163"/> + <location filename="mainwindow.cpp" line="5196"/> <source>Enable all</source> - <translation type="unfinished">全部啟用</translation> + <translation>全部啟用</translation> </message> <message> - <location filename="mainwindow.cpp" line="5164"/> + <location filename="mainwindow.cpp" line="5197"/> <source>Disable all</source> - <translation type="unfinished">全部ç¦ç”¨</translation> + <translation>全部ç¦ç”¨</translation> </message> <message> - <location filename="mainwindow.cpp" line="5183"/> + <location filename="mainwindow.cpp" line="5216"/> <source>Unlock load order</source> - <translation type="unfinished"></translation> + <translation>è§£éŽ–è¼‰å…¥é †åº</translation> </message> <message> - <location filename="mainwindow.cpp" line="5186"/> + <location filename="mainwindow.cpp" line="5219"/> <source>Lock load order</source> - <translation type="unfinished"></translation> + <translation>éŽ–å®šè¼‰å…¥é †åº</translation> </message> <message> - <location filename="mainwindow.cpp" line="5319"/> + <location filename="mainwindow.cpp" line="5352"/> <source>depends on missing "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5323"/> + <location filename="mainwindow.cpp" line="5356"/> <source>incompatible with "%1"</source> - <translation type="unfinished"></translation> + <translation>與 "%1" ä¸ç›¸å®¹</translation> </message> <message> - <location filename="mainwindow.cpp" line="5343"/> + <location filename="mainwindow.cpp" line="5376"/> <source>No profile set</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5540"/> + <location filename="mainwindow.cpp" line="5573"/> <source>loot failed. Exit code was: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5546"/> + <location filename="mainwindow.cpp" line="5579"/> <source>failed to start loot</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5549"/> + <location filename="mainwindow.cpp" line="5582"/> <source>failed to run loot: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5552"/> + <location filename="mainwindow.cpp" line="5585"/> <source>Errors occured</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5601"/> + <location filename="mainwindow.cpp" line="5636"/> <source>Backup of load order created</source> - <translation type="unfinished"></translation> + <translation>ç”¢ç”Ÿçš„è¼‰å…¥é †åºå‚™ä»½</translation> </message> <message> - <location filename="mainwindow.cpp" line="5611"/> + <location filename="mainwindow.cpp" line="5646"/> <source>Choose backup to restore</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>No Backups</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5624"/> + <location filename="mainwindow.cpp" line="5659"/> <source>There are no backups to restore</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5645"/> - <location filename="mainwindow.cpp" line="5666"/> + <location filename="mainwindow.cpp" line="5680"/> + <location filename="mainwindow.cpp" line="5701"/> <source>Restore failed</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5646"/> - <location filename="mainwindow.cpp" line="5667"/> + <location filename="mainwindow.cpp" line="5681"/> + <location filename="mainwindow.cpp" line="5702"/> <source>Failed to restore the backup. Errorcode: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="mainwindow.cpp" line="5657"/> + <location filename="mainwindow.cpp" line="5692"/> <source>Backup of modlist created</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -2879,14 +2876,69 @@ This function will guess the versioning scheme under the assumption that the ins <location filename="messagedialog.ui" line="150"/> <location filename="messagedialog.ui" line="180"/> <source>Placeholder</source> - <translation>å ä½ç¬¦</translation> + <translation>é ç•™ä½ç½®</translation> </message> </context> <context> <name>ModInfo</name> <message> - <location filename="modinfo.cpp" line="106"/> - <location filename="modinfo.cpp" line="135"/> + <location filename="modinfo.cpp" line="87"/> + <source>Plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="88"/> + <source>Textures</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="89"/> + <source>Meshes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="90"/> + <source>UI Changes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="91"/> + <source>Music</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="92"/> + <source>Sound Effects</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="93"/> + <source>Scripts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="94"/> + <source>SKSE Plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="95"/> + <source>SkyProc Tools</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="96"/> + <source>Strings</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="97"/> + <source>invalid content type %1</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="modinfo.cpp" line="120"/> + <location filename="modinfo.cpp" line="149"/> <source>invalid index %1</source> <translation>無效的索引 %1</translation> </message> @@ -2894,9 +2946,9 @@ This function will guess the versioning scheme under the assumption that the ins <context> <name>ModInfoBackup</name> <message> - <location filename="modinfo.cpp" line="930"/> + <location filename="modinfo.cpp" line="949"/> <source>This is the backup of a mod</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -2935,7 +2987,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="91"/> <source>Ini Files</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="104"/> @@ -2950,17 +3002,17 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="114"/> <source>Ini Tweaks</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="130"/> <source>This is a list of ini tweaks (ini modifications that can be toggled).</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="133"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="169"/> @@ -2985,7 +3037,7 @@ This function will guess the versioning scheme under the assumption that the ins <message> <location filename="modinfodialog.ui" line="243"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="276"/> @@ -3004,7 +3056,7 @@ This function will guess the versioning scheme under the assumption that the ins They usually contain optional functionality, see the readme. Most mods do not have optional esps, so chances are good you are looking at an empty list.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="310"/> @@ -3024,7 +3076,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <message> <location filename="modinfodialog.ui" line="342"/> <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 "available", it will not necessarily be loaded! That is configured in the main window of omo.</source> - <translation>移動一個 esp 檔案到 esp 目錄,這樣它就å¯ä»¥åœ¨ä¸»çª—å£ä¸å•Ÿç”¨äº†ã€‚請注æ„: ESP åªæ˜¯è®Šå¾—“å¯ç”¨â€ï¼Œå®ƒå¹¶ä¸ä¸€å®šæœƒè¢«è¼‰å…¥ï¼æƒ³è¦è½½å…¥è¯·åœ¨ MO 的主窗å£ä¸å‹¾é¸ã€‚</translation> + <translation>移動一個 esp 檔案到 esp 目錄,這樣它就å¯ä»¥åœ¨ä¸»è¦–窗ä¸å•Ÿç”¨äº†ã€‚請注æ„: ESP åªæ˜¯è®Šå¾—“å¯ç”¨â€ï¼Œå®ƒä¸¦ä¸ä¸€å®šæœƒè¢«è¼‰å…¥ï¼æƒ³è¦è¼‰å…¥è«‹åœ¨ MO 的主視窗ä¸èª¿æ•´ã€‚</translation> </message> <message> <location filename="modinfodialog.ui" line="377"/> @@ -3085,7 +3137,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <message> <location filename="modinfodialog.ui" line="561"/> <source>Primary Category</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="578"/> @@ -3107,7 +3159,7 @@ Most mods do not have optional esps, so chances are good you are looking at an e <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Mod ID for this mod on Nexus. This is filled in automatically if you downloaded and installed the mod from inside MO. Otherwise you can enter it manually. To find the correct id, find the mod on nexus. The URL will look like this: </span><a href=" http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">http://skyrim.nexusmods.com/downloads/file.php?id=1334</span></a><a href="http://www.skyrimnexus.com/downloads/file.php?id=1334"><span style=" font-size:8pt; color:#000000;">. In this example, 1334 is the id you're looking for. Besides: The above is the link to Mod Organizer on the Nexus. Why not go there now and endorse?</span></a></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3120,7 +3172,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Installed Version of the Mod. The tooltip will contain the current version available on nexus. The installed version is only set if you installed the mod through MO.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -3136,12 +3188,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="657"/> <source>Refresh</source> - <translation type="unfinished">釿–°æ•´ç†</translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="660"/> <source>Refresh all information from Nexus.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="674"/> @@ -3153,19 +3205,19 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="724"/> <source>Endorse</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="738"/> <source>Notes</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="748"/> @@ -3182,7 +3234,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This is a modifiable directory view of the mod directory. You can move around files using drag &amp; drop and rename them (double click).</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Changes happen immediately on disc, so do</span><span style=" font-size:8pt; font-weight:600;"> be careful</span><span style=" font-size:8pt;">.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -3195,7 +3247,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="modinfodialog.ui" line="787"/> <source>Previous</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modinfodialog.ui" line="794"/> @@ -3208,264 +3260,264 @@ p, li { white-space: pre-wrap; } <translation>關閉</translation> </message> <message> - <location filename="modinfodialog.cpp" line="169"/> + <location filename="modinfodialog.cpp" line="170"/> <source>&Delete</source> <translation>&刪除</translation> </message> <message> - <location filename="modinfodialog.cpp" line="170"/> + <location filename="modinfodialog.cpp" line="171"/> <source>&Rename</source> <translation>&釿–°å‘½å</translation> </message> <message> - <location filename="modinfodialog.cpp" line="171"/> + <location filename="modinfodialog.cpp" line="172"/> <source>&Hide</source> <translation>&éš±è—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="172"/> + <location filename="modinfodialog.cpp" line="173"/> <source>&Unhide</source> <translation>&å–æ¶ˆéš±è—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="173"/> + <location filename="modinfodialog.cpp" line="174"/> <source>&Open</source> <translation>&開啟</translation> </message> <message> - <location filename="modinfodialog.cpp" line="174"/> + <location filename="modinfodialog.cpp" line="175"/> <source>&New Folder</source> <translation>&新增資料夾</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes?</source> <translation>å„²å˜æ›´æ”¹å—Žï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="420"/> - <location filename="modinfodialog.cpp" line="435"/> + <location filename="modinfodialog.cpp" line="421"/> + <location filename="modinfodialog.cpp" line="436"/> <source>Save changes to "%1"?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>File Exists</source> <translation>檔案已å˜åœ¨</translation> </message> <message> - <location filename="modinfodialog.cpp" line="625"/> + <location filename="modinfodialog.cpp" line="626"/> <source>A file with that name exists, please enter a new one</source> <translation>檔案åå·²å˜åœ¨ï¼Œè«‹è¼¸å…¥å…¶å®ƒå稱</translation> </message> <message> - <location filename="modinfodialog.cpp" line="642"/> + <location filename="modinfodialog.cpp" line="643"/> <source>failed to move file</source> <translation>無法移動檔案</translation> </message> <message> - <location filename="modinfodialog.cpp" line="667"/> + <location filename="modinfodialog.cpp" line="668"/> <source>failed to create directory "optional"</source> <translation>無法建立 "optional" 目錄</translation> </message> <message> - <location filename="modinfodialog.cpp" line="705"/> - <location filename="modinfodialog.cpp" line="1210"/> + <location filename="modinfodialog.cpp" line="706"/> + <location filename="modinfodialog.cpp" line="1211"/> <source>Info requested, please wait</source> <translation>請求訊æ¯å·²ç™¼å‡ºï¼Œè«‹ç¨å¾Œ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="759"/> + <location filename="modinfodialog.cpp" line="760"/> <source>Main</source> <translation>ä¸»è¦æª”案</translation> </message> <message> - <location filename="modinfodialog.cpp" line="760"/> + <location filename="modinfodialog.cpp" line="761"/> <source>Update</source> <translation>æ›´æ–°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="761"/> + <location filename="modinfodialog.cpp" line="762"/> <source>Optional</source> <translation>å¯é¸æª”案</translation> </message> <message> - <location filename="modinfodialog.cpp" line="762"/> + <location filename="modinfodialog.cpp" line="763"/> <source>Old</source> <translation>舊檔</translation> </message> <message> - <location filename="modinfodialog.cpp" line="763"/> + <location filename="modinfodialog.cpp" line="764"/> <source>Misc</source> <translation>é›œé …</translation> </message> <message> - <location filename="modinfodialog.cpp" line="764"/> + <location filename="modinfodialog.cpp" line="765"/> <source>Unknown</source> <translation>未知</translation> </message> <message> - <location filename="modinfodialog.cpp" line="775"/> + <location filename="modinfodialog.cpp" line="776"/> <source>Current Version: %1</source> <translation>ç•¶å‰ç‰ˆæœ¬: %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="779"/> + <location filename="modinfodialog.cpp" line="780"/> <source>No update available</source> <translation>沒有å¯ç”¨çš„æ›´æ–°</translation> </message> <message> - <location filename="modinfodialog.cpp" line="820"/> + <location filename="modinfodialog.cpp" line="821"/> <source>(description incomplete, please visit nexus)</source> <translation>(æè¿°è¨Šæ¯ä¸å®Œæ•´ï¼Œè«‹è¨ªå•Nç¶²)</translation> </message> <message> - <location filename="modinfodialog.cpp" line="835"/> + <location filename="modinfodialog.cpp" line="836"/> <source><a href="%1">Visit on Nexus</a></source> <translation><a href="%1">訪å•Nç¶²</a></translation> </message> <message> - <location filename="modinfodialog.cpp" line="914"/> + <location filename="modinfodialog.cpp" line="915"/> <source>Failed to delete %1</source> <translation>無法刪除 %1</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="926"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Confirm</source> <translation>確èª</translation> </message> <message> - <location filename="modinfodialog.cpp" line="925"/> + <location filename="modinfodialog.cpp" line="926"/> <source>Are sure you want to delete "%1"?</source> <translation>確定è¦åˆªé™¤ "%1" 嗎?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="930"/> + <location filename="modinfodialog.cpp" line="931"/> <source>Are sure you want to delete the selected files?</source> <translation>確定è¦åˆªé™¤æ‰€é¸çš„æª”案嗎?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1004"/> - <location filename="modinfodialog.cpp" line="1010"/> + <location filename="modinfodialog.cpp" line="1005"/> + <location filename="modinfodialog.cpp" line="1011"/> <source>New Folder</source> <translation>新增資料夾</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1016"/> + <location filename="modinfodialog.cpp" line="1017"/> <source>Failed to create "%1"</source> <translation>無法建立 "%1"</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1121"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>Replace file?</source> <translation>å–代檔案?</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1120"/> + <location filename="modinfodialog.cpp" line="1121"/> <source>There already is a hidden version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå檔案,但該檔案被隱è—了。確定è¦è¦†è“‹å—Žï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>File operation failed</source> <translation>檔案æ“作錯誤</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1123"/> - <location filename="modinfodialog.cpp" line="1147"/> + <location filename="modinfodialog.cpp" line="1124"/> + <location filename="modinfodialog.cpp" line="1148"/> <source>Failed to remove "%1". Maybe you lack the required file permissions?</source> <translation>無法移除 "%1"。也許您需è¦è¶³å¤ 的檔案權é™ï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1134"/> - <location filename="modinfodialog.cpp" line="1157"/> + <location filename="modinfodialog.cpp" line="1135"/> + <location filename="modinfodialog.cpp" line="1158"/> <source>failed to rename %1 to %2</source> <translation>ç„¡æ³•é‡æ–°å‘½å %1 為 %2</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1144"/> + <location filename="modinfodialog.cpp" line="1145"/> <source>There already is a visible version of this file. Replace it?</source> <translation>å·²å˜åœ¨åŒå檔案。確定è¦è¦†è“‹å—Žï¼Ÿ</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1190"/> + <location filename="modinfodialog.cpp" line="1191"/> <source>Un-Hide</source> <translation>å–æ¶ˆéš±è—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1192"/> + <location filename="modinfodialog.cpp" line="1193"/> <source>Hide</source> <translation>éš±è—</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Name</source> <translation>å稱</translation> </message> <message> - <location filename="modinfodialog.cpp" line="1233"/> + <location filename="modinfodialog.cpp" line="1234"/> <source>Please enter a name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1238"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>Error</source> - <translation type="unfinished">錯誤</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1237"/> + <location filename="modinfodialog.cpp" line="1238"/> <source>Invalid name. Must be a valid file name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1240"/> + <location filename="modinfodialog.cpp" line="1241"/> <source>A tweak by that name exists</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfodialog.cpp" line="1254"/> + <location filename="modinfodialog.cpp" line="1255"/> <source>Create Tweak</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoForeign</name> <message> - <location filename="modinfo.cpp" line="1021"/> + <location filename="modinfo.cpp" line="1040"/> <source>This pseudo mod represents content managed outside MO. It isn't modified by MO.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoOverwrite</name> <message> - <location filename="modinfo.cpp" line="975"/> + <location filename="modinfo.cpp" line="994"/> <source>This pseudo mod contains files from the virtual data tree that got modified (i.e. by the construction kit)</source> - <translation type="unfinished">æ¤è™›æ“¬å®‰è£åŒ…內包å«ä¾†è‡ªè™›æ“¬ Data 樹的檔案,但檔案發生了變化 (例: 被CK修改了)</translation> + <translation type="unfinished"/> </message> </context> <context> <name>ModInfoRegular</name> <message> - <location filename="modinfo.cpp" line="567"/> - <location filename="modinfo.cpp" line="570"/> + <location filename="modinfo.cpp" line="586"/> + <location filename="modinfo.cpp" line="589"/> <source>failed to write %1/meta.ini: error %2</source> - <translation type="unfinished">無法寫入 %1/meta.ini: %2</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfo.cpp" line="843"/> + <location filename="modinfo.cpp" line="862"/> <source>%1 contains no esp/esm and no asset (textures, meshes, interface, ...) directory</source> - <translation type="unfinished">%1 䏿œªåŒ…å« esp 或 esm 和有效的目錄 (textures, meshes, interface, ...)</translation> + <translation type="unfinished"/> </message> <message> - <location filename="modinfo.cpp" line="847"/> + <location filename="modinfo.cpp" line="866"/> <source>Categories: <br></source> - <translation type="unfinished">種類: <br></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3473,52 +3525,52 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="55"/> <source>Game plugins (esp/esm)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="56"/> <source>Interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="57"/> <source>Meshes</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="58"/> <source>Music</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="59"/> <source>Scripts (Papyrus)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="60"/> <source>Script Extender Plugin</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="61"/> <source>SkyProc Patcher</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="62"/> <source>Sound</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="63"/> <source>Strings</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="64"/> <source>Textures</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="117"/> @@ -3528,58 +3580,57 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="126"/> <source>Backup</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="127"/> <source>No valid game data</source> - <translation type="unfinished"></translation> + <translation>ç„¡æœ‰æ•ˆçš„éŠæˆ²è³‡æ–™</translation> </message> <message> <location filename="modlist.cpp" line="128"/> <source>Not endorsed yet</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="130"/> <source>Overwrites files</source> - <translation type="unfinished">覆蓋的 Mod</translation> + <translation>覆蓋檔案</translation> </message> <message> <location filename="modlist.cpp" line="131"/> <source>Overwritten files</source> - <translation type="unfinished">覆蓋的 Mod</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="132"/> <source>Overwrites & Overwritten</source> - <translation type="unfinished"></translation> + <translation>覆蓋與被覆蓋</translation> </message> <message> <location filename="modlist.cpp" line="133"/> <source>Redundant</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="208"/> <source>Non-MO</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="238"/> <source>invalid</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="364"/> <source>installed version: "%1", newest version: "%2"</source> - <oldsource>installed version: %1, newest version: %2</oldsource> - <translation type="unfinished">ç•¶å‰ç‰ˆæœ¬: %1,最新版本: %2</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="366"/> <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 "upgrade".</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="374"/> @@ -3589,12 +3640,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="403"/> <source>Invalid name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="814"/> <source>drag&drop failed: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="877"/> @@ -3609,17 +3660,17 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="934"/> <source>Flags</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="935"/> <source>Content</source> - <translation type="unfinished">內容</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="936"/> <source>Mod Name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="937"/> @@ -3634,28 +3685,28 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="939"/> <source>Category</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="940"/> <source>Nexus ID</source> - <translation type="unfinished">Nç¶² ID</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="941"/> <source>Installation</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="942"/> <location filename="modlist.cpp" line="970"/> <source>unknown</source> - <translation type="unfinished">未知</translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="950"/> <source>Name of your mods</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="951"/> @@ -3670,27 +3721,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="modlist.cpp" line="954"/> <source>Category of the mod.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="955"/> <source>Id of the mod as used on Nexus.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="956"/> <source>Emblemes to highlight things that might require attention.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="957"/> <source>Depicts the content of the mod:<br><img src=":/MO/gui/content/plugin" width=32/>Game plugins (esp/esm)<br><img src=":/MO/gui/content/interface" width=32/>interface<br><img src=":/MO/gui/content/mesh" width=32/>Meshes<br><img src=":/MO/gui/content/texture" width=32/>Textures<br><img src=":/MO/gui/content/sound" width=32/>Sounds<br><img src=":/MO/gui/content/music" width=32/>Music<br><img src=":/MO/gui/content/string" width=32/>Strings<br><img src=":/MO/gui/content/script" width=32/>Scripts (Papyrus)<br><img src=":/MO/gui/content/skse" width=32/>Script Extender plugins<br><img src=":/MO/gui/content/skyproc" width=32/>SkyProc Patcher<br></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="modlist.cpp" line="969"/> <source>Time this mod was installed</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3722,22 +3773,22 @@ p, li { white-space: pre-wrap; } <context> <name>NXMAccessManager</name> <message> - <location filename="nxmaccessmanager.cpp" line="144"/> + <location filename="nxmaccessmanager.cpp" line="152"/> <source>Logging into Nexus</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="nxmaccessmanager.cpp" line="159"/> + <location filename="nxmaccessmanager.cpp" line="167"/> <source>timeout</source> <translation>超時</translation> </message> <message> - <location filename="nxmaccessmanager.cpp" line="178"/> + <location filename="nxmaccessmanager.cpp" line="186"/> <source>Unknown error</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="nxmaccessmanager.cpp" line="204"/> + <location filename="nxmaccessmanager.cpp" line="212"/> <source>Please check your password</source> <translation>請檢查您的密碼</translation> </message> @@ -3747,7 +3798,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="nexusinterface.cpp" line="216"/> <source>Failed to guess mod id for "%1", please pick the correct one</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="nexusinterface.cpp" line="482"/> @@ -3770,7 +3821,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.ui" line="39"/> <source>You can use drag&drop to move files and directories to regular mods.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="overwriteinfodialog.cpp" line="88"/> @@ -3795,7 +3846,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="overwriteinfodialog.cpp" line="109"/> <source>%1 not found</source> - <translation type="unfinished">找ä¸åˆ° %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="overwriteinfodialog.cpp" line="144"/> @@ -3833,116 +3884,116 @@ p, li { white-space: pre-wrap; } <context> <name>PluginList</name> <message> - <location filename="pluginlist.cpp" line="103"/> + <location filename="pluginlist.cpp" line="104"/> <source>Name</source> <translation>å稱</translation> </message> <message> - <location filename="pluginlist.cpp" line="104"/> + <location filename="pluginlist.cpp" line="105"/> <source>Priority</source> <translation>優先級</translation> </message> <message> - <location filename="pluginlist.cpp" line="105"/> + <location filename="pluginlist.cpp" line="106"/> <source>Mod Index</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="106"/> + <location filename="pluginlist.cpp" line="107"/> <source>Flags</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="107"/> - <location filename="pluginlist.cpp" line="119"/> + <location filename="pluginlist.cpp" line="108"/> + <location filename="pluginlist.cpp" line="120"/> <source>unknown</source> - <translation type="unfinished">未知</translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="115"/> + <location filename="pluginlist.cpp" line="116"/> <source>Name of your mods</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="116"/> + <location filename="pluginlist.cpp" line="117"/> <source>Load priority of your mod. The higher, the more "important" it is and thus overwrites data from plugins with lower priority.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="118"/> + <location filename="pluginlist.cpp" line="119"/> <source>The modindex determins the formids of objects originating from this mods.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="159"/> + <location filename="pluginlist.cpp" line="160"/> <source>failed to update esp info for file %1 (source id: %2), error: %3</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="227"/> + <location filename="pluginlist.cpp" line="228"/> <source>esp not found: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="234"/> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="235"/> + <location filename="pluginlist.cpp" line="247"/> <source>Confirm</source> <translation>確èª</translation> </message> <message> - <location filename="pluginlist.cpp" line="234"/> + <location filename="pluginlist.cpp" line="235"/> <source>Really enable all plugins?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="246"/> + <location filename="pluginlist.cpp" line="247"/> <source>Really disable all plugins?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="397"/> + <location filename="pluginlist.cpp" line="398"/> <source>The file containing locked plugin indices is broken</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="438"/> + <location filename="pluginlist.cpp" line="439"/> <source>Some of your plugins have invalid names! These plugins can not be loaded by the game. Please see mo_interface.log for a list of affected plugins and rename them.</source> <translation>您的一些æ’ä»¶å稱無效ï¼é€™äº›æ’ä»¶ç„¡æ³•è¢«éŠæˆ²è¼‰å…¥ã€‚請查看 mo_interface.log 來確èªé‚£äº›å—影響的æ’件䏦釿–°å‘½å它們。</translation> </message> <message> <location filename="pluginlist.cpp" line="806"/> - <source><b>Origin</b>: %1</source> - <translation type="unfinished"></translation> + <source>This plugin can't be disabled (enforced by the game)</source> + <translation>這個æ’ä»¶ä¸èƒ½è¢«ç¦ç”¨ (ç”±éŠæˆ²åŸ·è¡Œ)</translation> </message> <message> <location filename="pluginlist.cpp" line="808"/> + <source><b>Origin</b>: %1</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="pluginlist.cpp" line="810"/> <source>Author</source> <translation>作者</translation> </message> <message> - <location filename="pluginlist.cpp" line="811"/> + <location filename="pluginlist.cpp" line="813"/> <source>Description</source> <translation>æè¿°</translation> </message> <message> - <location filename="pluginlist.cpp" line="804"/> - <source>This plugin can't be disabled (enforced by the game)</source> - <translation>這個æ’ä»¶ä¸èƒ½è¢«ç¦ç”¨ (ç”±éŠæˆ²åŸ·è¡Œ)</translation> - </message> - <message> - <location filename="pluginlist.cpp" line="814"/> + <location filename="pluginlist.cpp" line="816"/> <source>Missing Masters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="821"/> + <location filename="pluginlist.cpp" line="823"/> <source>Enabled Masters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="pluginlist.cpp" line="972"/> + <location filename="pluginlist.cpp" line="974"/> <source>failed to restore load order for %1</source> - <translation type="unfinished"></translation> + <translation>為 %1 å›žå¾©è¼‰å…¥é †åºå¤±æ•—</translation> </message> </context> <context> @@ -3950,7 +4001,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="previewdialog.ui" line="14"/> <source>Preview</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="previewdialog.ui" line="78"/> @@ -3963,16 +4014,16 @@ p, li { white-space: pre-wrap; } <message> <location filename="problemsdialog.ui" line="14"/> <source>Problems</source> - <translation type="unfinished">å•題</translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.ui" line="49"/> <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.ui" line="75"/> @@ -3983,12 +4034,12 @@ p, li { white-space: pre-wrap; } <location filename="problemsdialog.cpp" line="44"/> <location filename="problemsdialog.cpp" line="45"/> <source>Fix</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="problemsdialog.cpp" line="49"/> <source>No guided fix</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -3996,32 +4047,32 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="59"/> <source>invalid profile name %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="63"/> <source>failed to create %1</source> - <translation type="unfinished">無法建立 %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="184"/> <source>failed to write mod list: %1</source> - <translation type="unfinished">無法更新 Mod 列表: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="195"/> <source>failed to update tweaked ini file, wrong settings may be used: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="226"/> <source>failed to create tweaked ini: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="236"/> <source>"%1" is missing or inaccessible</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="282"/> @@ -4035,7 +4086,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="397"/> <source>Overwrite directory couldn't be parsed</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="406"/> @@ -4045,7 +4096,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="596"/> <source>failed to parse ini file (%1)</source> - <translation type="unfinished">ç„¡æ³•è§£æž Ini 檔案 (%1)</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="624"/> @@ -4056,17 +4107,17 @@ p, li { white-space: pre-wrap; } <location filename="profile.cpp" line="648"/> <location filename="profile.cpp" line="685"/> <source>failed to modify "%1"</source> - <translation type="unfinished">未能找到 "%1"</translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="713"/> <source>Delete savegames?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profile.cpp" line="714"/> <source>Do you want to delete local savegames? (If you select "No", the save games will show up again if you re-enable local savegames)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4114,28 +4165,28 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is the list of profiles. Each Profile contains its own list and installation order of enabled mods (from a shared pool), a configuration of enabled esps/esms, a copy of the games ini-file and an optional savegame filter.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Note</span> For technical reasons it's currently not possible to have seperate load-orders for esps. This means you can't load moda.esp before modb.esp in one profile and the other way around in another.</p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">這是é…置檔案的列表,æ¯å€‹é…置檔案都包å«äº†å®ƒå€‘自己的已激活 Mod 的列表和安è£é †åº (從共享å€åŸŸ)ã€ä¸€å€‹å·²æ¿€æ´»çš„ esp 或 esm çš„é…ç½®ã€ä¸€å€‹éŠæˆ² Ini 檔案的拷è²å’Œä¸€å€‹å¯é¸çš„å˜æª”éŽæ¿¾å™¨ã€‚</p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">這是é…置檔案的列表,æ¯å€‹é…置檔案都包å«äº†å®ƒå€‘自己的已啟動 Mod 的列表和安è£é †åº (從共享å€åŸŸ)ã€ä¸€å€‹å·²å•Ÿå‹•çš„ esp 或 esm çš„é…ç½®ã€ä¸€å€‹éŠæˆ² Ini 檔案的拷è²å’Œä¸€å€‹å¯é¸çš„å˜æª”éŽæ¿¾å™¨ã€‚</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">注æ„: </span>ç”±äºŽæŠ€è¡“ä¸Šçš„åŽŸå› ï¼Œç›®å‰ä¸å¯èƒ½æœ‰åˆ†é–‹å„²å˜çš„æ’ä»¶åŠ è¼‰é †åºã€‚這æ„味著您ä¸èƒ½åŒæ—¶åœ¨å…©å€‹é…置檔案裡使用兩種ä¸åŒçš„æ’ä»¶é…置方案。</p></body></html></translation> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">注æ„: </span>ç”±æ–¼æŠ€è¡“ä¸Šçš„åŽŸå› ï¼Œç›®å‰ä¸å¯èƒ½æœ‰åˆ†é–‹å„²å˜çš„æ’ä»¶è¼‰å…¥é †åºã€‚這æ„味著您ä¸èƒ½åŒæ™‚在兩個é…置檔案裡使用兩種ä¸åŒçš„æ’ä»¶é…置方案。</p></body></html></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> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="44"/> <source>Local Savegames</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="51"/> @@ -4147,7 +4198,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The games Oblivion, Fallout 3 and Fallout NV contain a bug which prevents texture and mesh replacers (that is: all modifications to meshes and textures already in game) from working.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Mod Organizer uses a workaround called &quot;BSA redirection&quot; (google is your friend) to fix this issue reliably and without further work. Simply activate and forget.</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p> @@ -4206,18 +4257,18 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.ui" line="123"/> <source>Rename</source> - <translation type="unfinished">&釿–°å‘½å</translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="133"/> <location filename="profilesdialog.ui" line="136"/> <source>Transfer save games to the selected profile.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="139"/> <source>Transfer Saves</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.ui" line="162"/> @@ -4253,12 +4304,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="165"/> <source>Invalid name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="165"/> <source>Invalid profile name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="172"/> @@ -4268,27 +4319,27 @@ p, li { white-space: pre-wrap; } <message> <location filename="profilesdialog.cpp" line="172"/> <source>Are you sure you want to remove this profile (including local savegames if any)?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="182"/> <source>Profile broken</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="183"/> <source>This profile you're about to delete seems to be broken or the path is invalid. I'm about to delete the following folder: "%1". Proceed?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="215"/> <source>Rename Profile</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="215"/> <source>New Name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="252"/> @@ -4324,47 +4375,47 @@ p, li { white-space: pre-wrap; } <message> <location filename="csvbuilder.cpp" line="70"/> <source>invalid field name "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="76"/> <source>invalid type for "%1" (should be integer)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="81"/> <source>invalid type for "%1" (should be string)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="86"/> <source>invalid type for "%1" (should be float)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="103"/> <source>no fields set up yet!</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="140"/> <source>field not set "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="237"/> <source>invalid character in field "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="csvbuilder.cpp" line="240"/> <source>empty field name</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="gameinfoimpl.cpp" line="41"/> <source>invalid game type %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="helper.cpp" line="53"/> @@ -4402,7 +4453,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="loadmechanism.cpp" line="144"/> <source>Failed to deactivate script extender loading</source> - <translation>無法åœç”¨è„šæœ¬æ‰©å±•åŠ è¼‰</translation> + <translation>åœç”¨è…³æœ¬æ“´å……載入失敗</translation> </message> <message> <location filename="loadmechanism.cpp" line="165"/> @@ -4418,7 +4469,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="loadmechanism.cpp" line="175"/> <source>Failed to deactivate proxy-dll loading</source> - <translation>無法åœç”¨ä»£ç†DLLåŠ è¼‰</translation> + <translation>åœç”¨ä»£ç†DLL載入失敗</translation> </message> <message> <location filename="loadmechanism.cpp" line="209"/> @@ -4430,7 +4481,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="loadmechanism.cpp" line="214"/> <source>Failed to set up script extender loading</source> - <translation>無法è¨å®šè…³æœ¬æ‹“å±•åŠ è¼‰</translation> + <translation>è¨å®šè…³æœ¬æ“´å……載入失敗</translation> </message> <message> <location filename="loadmechanism.cpp" line="240"/> @@ -4445,65 +4496,65 @@ p, li { white-space: pre-wrap; } <message> <location filename="loadmechanism.cpp" line="268"/> <source>Failed to set up proxy-dll loading</source> - <translation>無法è¨å®šä»£ç†DLLåŠ è¼‰</translation> + <translation>è¨å®šä»£ç†DLL載入失敗</translation> </message> <message> - <location filename="main.cpp" line="121"/> + <location filename="main.cpp" line="122"/> <source>Permissions required</source> <translation>éœ€è¦æ¬Šé™</translation> </message> <message> - <location filename="main.cpp" line="122"/> + <location filename="main.cpp" line="123"/> <source>The current user account doesn't have the required access rights to run Mod Organizer. The neccessary changes can be made automatically (the MO directory will be made writable for the current user account). You will be asked to run "helper.exe" with administrative rights.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="218"/> - <location filename="main.cpp" line="256"/> + <location filename="main.cpp" line="202"/> + <location filename="main.cpp" line="241"/> <source>Woops</source> <translation>糟糕</translation> </message> <message> - <location filename="main.cpp" line="219"/> + <location filename="main.cpp" line="203"/> <source>ModOrganizer has crashed! Should a diagnostic file be created? If you send me this file (%1) to sherb@gmx.net, the bug is a lot more likely to be fixed. Please include a short description of what you were doing when the crash happened</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="257"/> + <location filename="main.cpp" line="242"/> <source>ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1</source> <translation>Mod Organizer 崩潰了ï¼éºæ†¾çš„æ˜¯ï¼Œæˆ‘無法生æˆè¨ºæ–·æª”案: %1</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <location filename="settings.cpp" line="528"/> <source>Mod Organizer</source> <translation>Mod Organizer</translation> </message> <message> - <location filename="main.cpp" line="378"/> + <location filename="main.cpp" line="383"/> <source>An instance of Mod Organizer is already running</source> <translation>Mod Organizer 的一個實例æ£åœ¨é‹è¡Œ</translation> </message> <message> - <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="397"/> <source>No game identified in "%1". The directory is required to contain the game binary and its launcher.</source> <translation>"%1" 䏿œªæª¢æ¸¬åˆ°éŠæˆ²ã€‚請確ä¿è©²è·¯å¾‘ä¸åŒ…å«éŠæˆ²åŸ·è¡Œç¨‹å¼ä»¥åŠå°æ‡‰çš„ Launcher 檔案。</translation> </message> <message> - <location filename="main.cpp" line="403"/> - <location filename="main.cpp" line="432"/> + <location filename="main.cpp" line="400"/> + <location filename="main.cpp" line="429"/> <source>Please select the game to manage</source> <translation>è«‹é¸æ“‡æƒ³è¦ç®¡ç†çš„éŠæˆ²</translation> </message> <message> - <location filename="main.cpp" line="458"/> + <location filename="main.cpp" line="456"/> <source>Please select the game edition you have (MO can't start the game correctly if this is set incorrectly!)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="main.cpp" line="547"/> + <location filename="main.cpp" line="545"/> <source>failed to start application: %1</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="mainwindow.cpp" line="856"/> @@ -4511,28 +4562,28 @@ p, li { white-space: pre-wrap; } <translation>請使用工具列上的“幫助â€ä¾†ç²å¾—æ‰€æœ‰å…ƒç´ çš„ä½¿ç”¨èªªæ˜Ž</translation> </message> <message> - <location filename="mainwindow.cpp" line="1649"/> - <location filename="mainwindow.cpp" line="4314"/> + <location filename="mainwindow.cpp" line="1659"/> + <location filename="mainwindow.cpp" line="4347"/> <source><Manage...></source> <translation><管ç†...></translation> </message> <message> - <location filename="mainwindow.cpp" line="1667"/> + <location filename="mainwindow.cpp" line="1677"/> <source>failed to parse profile %1: %2</source> <translation>無法解æžé…置檔案 %1: %2</translation> </message> <message> - <location filename="pluginlist.cpp" line="352"/> + <location filename="pluginlist.cpp" line="353"/> <source>failed to find "%1"</source> <translation>未能找到 "%1"</translation> </message> <message> - <location filename="pluginlist.cpp" line="516"/> + <location filename="pluginlist.cpp" line="518"/> <source>failed to access %1</source> <translation>ç„¡æ³•è¨ªå• %1</translation> </message> <message> - <location filename="pluginlist.cpp" line="530"/> + <location filename="pluginlist.cpp" line="532"/> <source>failed to set file time %1</source> <translation>無法è¨å®šæª”案時間 %1</translation> </message> @@ -4544,8 +4595,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="profile.cpp" line="96"/> <source>"%1" is missing or inaccessible</source> - <oldsource>"%1" is missing</oldsource> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="profilesdialog.cpp" line="80"/> @@ -4559,6 +4609,11 @@ p, li { white-space: pre-wrap; } <translation>錯誤</translation> </message> <message> + <location filename="safewritefile.cpp" line="33"/> + <source>failed to open temporary file</source> + <translation type="unfinished"/> + </message> + <message> <location filename="savegamegamebryo.cpp" line="130"/> <location filename="savegamegamebryo.cpp" line="189"/> <location filename="savegamegamebryo.cpp" line="231"/> @@ -4581,87 +4636,82 @@ p, li { white-space: pre-wrap; } <translation>代ç†DLL</translation> </message> <message> - <location filename="spawn.cpp" line="133"/> + <location filename="spawn.cpp" line="140"/> <source>failed to spawn "%1"</source> <translation>ç„¡æ³•ç”Ÿæˆ "%1"</translation> </message> <message> - <location filename="spawn.cpp" line="140"/> + <location filename="spawn.cpp" line="147"/> <source>Elevation required</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="spawn.cpp" line="141"/> + <location filename="spawn.cpp" line="148"/> <source>This process requires elevation to run. This is a potential security risk so I highly advice you to investigate if "%1" can be installed to work without elevation. Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe to make changes to the system)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> - <location filename="spawn.cpp" line="156"/> + <location filename="spawn.cpp" line="163"/> <source>failed to spawn "%1": %2</source> <translation>ç„¡æ³•ç”Ÿæˆ "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="165"/> + <location filename="spawn.cpp" line="172"/> <source>"%1" doesn't exist</source> <translation>"%1" ä¸å˜åœ¨</translation> </message> <message> - <location filename="spawn.cpp" line="172"/> + <location filename="spawn.cpp" line="179"/> <source>failed to inject dll into "%1": %2</source> <translation>無法注入 dll 到 "%1": %2</translation> </message> <message> - <location filename="spawn.cpp" line="190"/> + <location filename="spawn.cpp" line="197"/> <source>failed to run "%1"</source> <translation>無法é‹è¡Œ "%1"</translation> </message> - <message> - <location filename="safewritefile.cpp" line="33"/> - <source>failed to open temporary file</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> + <translation type="unfinished"/> </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> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="63"/> <source>Keep Backup</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="70"/> <source>Merge</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="77"/> <source>Replace</source> - <translation type="unfinished">å–代</translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="84"/> <source>Rename</source> - <translation type="unfinished">&釿–°å‘½å</translation> + <translation type="unfinished"/> </message> <message> <location filename="queryoverwritedialog.ui" line="91"/> <source>Cancel</source> - <translation type="unfinished">å–æ¶ˆ</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4669,27 +4719,27 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidget.ui" line="39"/> <source>Save #</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="51"/> <source>Character</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="63"/> <source>Level</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="75"/> <source>Location</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savegameinfowidget.ui" line="87"/> <source>Date</source> - <translation type="unfinished">Data</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4697,7 +4747,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savegameinfowidgetgamebryo.cpp" line="41"/> <source>Missing ESPs</source> - <translation type="unfinished">缺失的 ESP</translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4705,37 +4755,37 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="savetextasdialog.ui" line="14"/> <source>Dialog</source> - <translation type="unfinished">å°è©±æ–¹å¡Š</translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.ui" line="32"/> <source>Copy To Clipboard</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.ui" line="39"/> <source>Save As...</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.ui" line="59"/> <source>Close</source> - <translation type="unfinished">關閉</translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Save CSV</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.cpp" line="36"/> <source>Text Files</source> - <translation type="unfinished">æ–‡å—æ–‡ä»¶</translation> + <translation type="unfinished"/> </message> <message> <location filename="savetextasdialog.cpp" line="40"/> <source>failed to open "%1" for writing</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> <context> @@ -4748,7 +4798,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selectiondialog.ui" line="23"/> <source>Placeholder</source> - <translation>å ä½ç¬¦</translation> + <translation>é ç•™ä½ç½®</translation> </message> <message> <location filename="selectiondialog.ui" line="77"/> @@ -4761,7 +4811,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="66"/> <source>archive.dll not loaded: "%1"</source> - <translation type="unfinished"></translation> + <translation>archive.dll 並未載入: "%1"</translation> </message> <message> <location filename="selfupdater.cpp" line="117"/> @@ -4799,7 +4849,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="251"/> <source>failed to move outdated files: %1. Please update manually.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="269"/> @@ -4819,12 +4869,12 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="417"/> <source>No incremental update available for this version, the complete package needs to be downloaded (%1 kB)</source> - <translation>沒有å¯ç”¨äºŽæ¤ç‰ˆæœ¬çš„æ›´æ–°æª”案,需è¦ä¸‹è¼‰å®Œæ•´çš„安è£åŒ… (%1 KB)</translation> + <translation>沒有å¯ç”¨æ–¼æ¤ç‰ˆæœ¬çš„æ›´æ–°æª”案,需è¦ä¸‹è¼‰å®Œæ•´çš„安è£åŒ… (%1 kB)</translation> </message> <message> <location filename="selfupdater.cpp" line="426"/> <source>no file for update found. Please update manually.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="selfupdater.cpp" line="441"/> @@ -4834,7 +4884,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="selfupdater.cpp" line="461"/> <source>No download server available. Please try again later.</source> - <translation type="unfinished">沒有å¯ç”¨çš„下載伺æœå™¨ï¼Œè«‹ç¨å¾Œå†å˜—試下載。</translation> + <translation>沒有å¯ç”¨çš„下載伺æœå™¨ï¼Œè«‹ç¨å¾Œå†å˜—試下載。</translation> </message> </context> <context> @@ -4842,18 +4892,18 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <message> <location filename="settings.cpp" line="115"/> <source>Failed</source> - <translation type="unfinished">失敗</translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="116"/> <source>Sorry, failed to start the helper application</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="335"/> <location filename="settings.cpp" line="354"/> <source>attempt to store setting for unknown plugin "%1"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settings.cpp" line="647"/> @@ -4893,7 +4943,7 @@ Start elevated anyway? (you will be asked if you want to allow ModOrganizer.exe <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The display language. This will only displaye languages for which you have a translation installed.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -4904,48 +4954,48 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="57"/> <source>Style</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="64"/> <source>graphical style</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="67"/> <source>graphical style of the MO user interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="78"/> <source>Log Level</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="85"/> <source>Decides the amount of data printed to "ModOrganizer.log"</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="88"/> <source>Decides the amount of data printed to "ModOrganizer.log". "Debug" produces very useful information for finding problems. There is usually no noteworthy performance impact but the file may become rather large. If this is a problem you may prefer the "Info" level for regluar use. On the "Error" level the log file usually remains empty.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="93"/> <source>Debug</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="98"/> <source>Info</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="103"/> <source>Error</source> - <translation type="unfinished">錯誤</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="113"/> @@ -4986,37 +5036,37 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="199"/> <source>User interface</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="205"/> <source>If checked, the download interface will be more compact.</source> - <translation type="unfinished"></translation> + <translation>如果勾é¸ï¼Œä¸‹è¼‰ä»‹é¢å°‡æœƒæ›´ç°¡æ½”。</translation> </message> <message> <location filename="settingsdialog.ui" line="208"/> <source>Compact Download Interface</source> - <translation type="unfinished"></translation> + <translation>壓縮下載介é¢</translation> </message> <message> <location filename="settingsdialog.ui" line="215"/> <source>If checked, the download list will display meta information instead of file names.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="218"/> <source>Download Meta Information</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="234"/> <source>Reset stored information from dialogs.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="237"/> <source>This will make all dialogs show up again where you checked the "Remember selection"-box.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="240"/> @@ -5050,7 +5100,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Allows automatic log-in when the Nexus-Page for the game is clicked. Please note that the obfuscation with which the password is stored in modorganizer.ini is not very strong. If you're worried someone might steal your password, don't store it here.</span></p></body></html></source> <translation><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> @@ -5061,7 +5111,7 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="299"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="302"/> @@ -5081,82 +5131,82 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="347"/> <source>Disable automatic internet features</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="350"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="353"/> <source>Offline Mode</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="360"/> <source>Use a proxy for network connections.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="363"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="366"/> <source>Use HTTP Proxy (Uses System Settings)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="375"/> <source>Associate with "Download with manager" links</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="404"/> <source>Known Servers (updated on download)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="425"/> <source>Preferred Servers (Drag & Drop)</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="460"/> <source>Plugins</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="482"/> <source>Author:</source> - <translation type="unfinished">作者</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="496"/> <source>Version:</source> - <translation type="unfinished">版本</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="510"/> <source>Description:</source> - <translation type="unfinished">æè¿°</translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="548"/> <source>Key</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="553"/> <source>Value</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="565"/> <source>Blacklisted Plugins (use <del> to remove):</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="576"/> @@ -5178,7 +5228,7 @@ p, li { white-space: pre-wrap; } <source><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The Steam App ID is required to directly start some games. For Skyrim, if this is not set or wrong, the &quot;Mod Organizer&quot; load mechanism may not work properly.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The preset for this is the App ID of the &quot;regular&quot; version so in most cases, you should be set.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">If you think you have a different version (GotY or something), follow these steps to get to the id:</span></p> @@ -5191,8 +5241,8 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Steam App ID æ˜¯å¿…é ˆçš„ï¼Œå®ƒè¢«ç”¨ä¾†ç›´æŽ¥å•Ÿå‹•ä¸€äº›éŠæˆ²ã€‚å°æ–¼å¤©éš›ï¼Œå¦‚果沒有è¨å®šæˆ–è¨å®šéŒ¯èª¤ï¼Œ&quot;Mod Organizer&quot; çš„åŠ è¼‰æ©Ÿåˆ¶å¯èƒ½æœƒç„¡æ³•æ£å¸¸å·¥ä½œã€‚</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">æ¤é è¨æ˜¯æ‡‰ç”¨ç¨‹å¼ ID 的“常è¦â€ç‰ˆæœ¬ï¼Œå› æ¤åœ¨å¤§å¤šæ•¸æƒ…æ³ä¸‹ï¼Œæ‚¨æ‡‰è©²è¦é‡æ–°è¨å®šä¸€ä¸‹ã€‚</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">Steam App ID æ˜¯å¿…é ˆçš„ï¼Œå®ƒè¢«ç”¨ä¾†ç›´æŽ¥å•Ÿå‹•ä¸€äº›éŠæˆ²ã€‚å°æ–¼ Skyrim,如果沒有è¨å®šæˆ–è¨å®šéŒ¯èª¤ï¼Œ&quot;Mod Organizer&quot; çš„åŠ è¼‰æ©Ÿåˆ¶å¯èƒ½æœƒç„¡æ³•æ£å¸¸å·¥ä½œã€‚</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">æ¤é è¨æ˜¯æ‡‰ç”¨ç¨‹å¼ ID 的“æ£å¸¸â€ç‰ˆæœ¬ï¼Œå› æ¤åœ¨å¤§å¤šæ•¸æƒ…æ³ä¸‹ï¼Œæ‚¨æ‡‰è©²è¦é‡æ–°è¨å®šä¸€ä¸‹ã€‚</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">如果您èªç‚ºæ‚¨æœ‰ä¸åŒçš„版本 (年度版或其它版本),那麼請åƒç…§ä¸‹åˆ—çš„æ¥é©Ÿä¾†ç²å– ID: </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">1. 進入 Steam è£¡çš„éŠæˆ²åº«</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:9pt;">2. å³éµé»žæ“Šæ‚¨æƒ³è¦ç²å– ID çš„éŠæˆ²ï¼Œé¸æ“‡</span><span style=" font-size:9pt; font-weight:600;">å»ºç«‹æ¡Œé¢æ·å¾‘</span></p> @@ -5203,12 +5253,12 @@ p, li { white-space: pre-wrap; } <message> <location filename="settingsdialog.ui" line="638"/> <source>Load Mechanism</source> - <translation>åŠ è¼‰æ©Ÿåˆ¶</translation> + <translation>載入機制</translation> </message> <message> <location filename="settingsdialog.ui" line="658"/> <source>Select loading mechanism. See help for details.</source> - <translation>鏿“‡åŠ è¼‰æ©Ÿåˆ¶ï¼Œä½¿ç”¨å¹«åŠ©æŸ¥çœ‹æ›´å¤šç´°ç¯€ã€‚</translation> + <translation>鏿“‡è¼‰å…¥æ©Ÿåˆ¶ï¼Œä½¿ç”¨å¹«åŠ©æŸ¥çœ‹æ›´å¤šç´°ç¯€ã€‚</translation> </message> <message> <location filename="settingsdialog.ui" line="661"/> @@ -5216,10 +5266,10 @@ p, li { white-space: pre-wrap; } There are several means to do this: *Mod Organizer* (default) In this mode the Mod Organizer itself injects the dll. The disadvantage is that you always have to start the game through MO or a link created by it. *Script Extender* In this mode, MO is installed as a Script Extender (obse, fose, nvse, skse) plugin. -*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. +*Proxy DLL* In this mode, MO replaces one of the game's dlls with one that loads MO (and the original dll of course). This will ONLY work with Steam games and it has only been tested with Skyrim. Please use this only if the other mechanisms don't work. If you use the Steam version of Oblivion the default will NOT work. In this case, please install obse and use "Script Extender" as the load mechanism. Also you can then not start Oblivion from MO. Instead, use MO only to set up your mods, then quit and start Oblivion through Steam.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="678"/> @@ -5234,11 +5284,11 @@ If you use the Steam version of Oblivion the default will NOT work. In this case <message> <location filename="settingsdialog.ui" line="701"/> <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't need an update. Therefore you can configure the version to identify as here. -Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. +On top of this Nexus has used the client identification to lock out outdated versions of NMM to force users to update. This means that MO also needs to impersonate the new version of NMM even if MO doesn't need an update. Therefore you can configure the version to identify as here. +Please note that MO does identify itself as MO to the webserver, it's not lying about what it is. It is merely adding a "compatible" NMM version to the user agent. tl;dr-version: If Nexus-features don't work, insert the current version number of NMM here and try again.</source> - <translation>Mod Organizer 使用了一個N網所æä¾›çš„ API 來進行類似於檢查更新和下載檔案這樣的æ“ä½œã€‚éºæ†¾çš„æ˜¯é€™å€‹ API 並沒有給第三方工具 (比如 MO) æ£å¼çš„æŽˆæ¬Šï¼Œæ‰€ä»¥æˆ‘å€‘éœ€è¦æ¨¡æ“¬ NMM 來進行這些æ“作。 + <translation>Mod Organizer 使用了N網所æä¾›çš„ API 來進行類似於檢查更新和下載檔案這樣的æ“ä½œã€‚éºæ†¾çš„æ˜¯é€™å€‹ API 並沒有給第三方工具 (比如 MO) æ£å¼çš„æŽˆæ¬Šï¼Œæ‰€ä»¥æˆ‘å€‘éœ€è¦æ¨¡æ“¬ NMM 來進行這些æ“作。 在æ¤ä¹‹å‰ï¼ŒN網使用了客戶端辨è˜ç³»çµ±éŽ–å®šäº†èˆŠç‰ˆæœ¬çš„ NMM,強制用戶更新版本。這æ„味著 MO ä¹Ÿè¦æ¨¡æ“¬æ–°ç‰ˆæœ¬çš„ NMM,å³ä¾¿ MO 自己並ä¸éœ€è¦æ›´æ–°ã€‚å› æ¤æ‚¨éœ€è¦åœ¨é€™è£¡é…置版本號來進行辨è˜ã€‚ 請注æ„: MO 辨è˜è‡ªå·±ç‚º MO 到網路伺æœå™¨ï¼Œé€™ä¸¦ä¸æ˜¯æ¬ºé¨™ã€‚å®ƒåƒ…åƒ…æ˜¯ç‚ºç”¨æˆ¶ä»£ç†æ·»åŠ äº†ä¸€å€‹â€œå…¼å®¹â€çš„ NMM 版本。 @@ -5247,13 +5297,13 @@ tl;dr-version: If Nexus-features don't work, insert the current version num <message> <location filename="settingsdialog.ui" line="723"/> <source>Enforces that inactive ESPs and ESMs are never loaded.</source> - <translation>強制執行,未激活的 ESP å’Œ ESM 將䏿œƒè¢«åŠ è¼‰ã€‚</translation> + <translation>強制執行,未啟用的 ESP å’Œ ESM 將䏿œƒè¢«è¼‰å…¥ã€‚</translation> </message> <message> <location filename="settingsdialog.ui" line="726"/> - <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. + <source>It seems that the Games occasionally load ESP or ESM files even if they haven't been activated as plugins. I don't yet know what the circumstances are, but user reports imply it is in some cases unwanted. If this is checked, ESPs and ESMs not checked in the List are invisible to the game and can not be loaded.</source> - <translation>çœ‹ä¾†ï¼ŒéŠæˆ²å¶çˆ¾æœƒåŠ è¼‰ä¸€äº›æ²’æœ‰è¢«æ¿€æ´»æˆæ’ä»¶çš„ ESP 或 ESM 檔案。 + <translation>çœ‹ä¾†éŠæˆ²å¶çˆ¾æœƒè¼‰å…¥ä¸€äº›æ²’æœ‰è¢«å•Ÿå‹•æˆæ’ä»¶çš„ ESP 或 ESM 檔案。 我還尚ä¸çŸ¥é“它在什麼情æ³ä¸‹æœƒé€™æ¨£ï¼Œä½†æ˜¯æœ‰ç”¨æˆ¶å ±å‘Šèªªå®ƒåœ¨æŸäº›æƒ…æ³ä¸‹æ˜¯å¾ˆä¸å¿…è¦çš„。如果這個é¸é …被é¸ä¸ï¼Œé‚£éº¼åœ¨åˆ—è¡¨ä¸æ²’有被勾é¸çš„ ESP å’Œ ESM 將䏿œƒåœ¨éŠæˆ²ä¸å‡ºç¾ï¼Œä¸¦ä¸”ä¹Ÿä¸æœƒè¢«è¼‰å…¥ã€‚</translation> </message> <message> @@ -5264,36 +5314,36 @@ I don't yet know what the circumstances are, but user reports imply it is i <message> <location filename="settingsdialog.ui" line="737"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="740"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="744"/> <source>Force-enable game files</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="754"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="757"/> <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't be resolved correctly. +However, if you installed loose file mods outside MO which conflict with BSAs also installed outside MO those conflicts can't be resolved correctly. If you disable this feature, MO will only display official DLCs this way. Please note that plugins (esps and esms) displayed in the right pane are completely unaffected by this feature.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="763"/> <source>Display mods installed outside MO</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.ui" line="773"/> @@ -5311,7 +5361,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="settingsdialog.ui" line="805"/> <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> + <translation type="unfinished"/> </message> <message> <location filename="settingsdialog.cpp" line="95"/> @@ -5388,7 +5438,7 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="singleinstance.cpp" line="88"/> <source>failed to communicate with running instance: %1</source> - <translation type="unfinished">無法連接到æ£åœ¨é‹è¡Œçš„實例: %1</translation> + <translation type="unfinished"/> </message> <message> <location filename="singleinstance.cpp" line="100"/> @@ -5434,17 +5484,17 @@ For the other games this is not a sufficient replacement for AI!</source> <message> <location filename="transfersavesdialog.ui" line="14"/> <source>Transfer Savegames</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="22"/> <source>Global Characters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="29"/> <source>This is a list of characters in the global location.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="32"/> @@ -5456,7 +5506,7 @@ On Windows Vista/Windows 7: On Windows XP: C:\Documents and Settings\[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="46"/> @@ -5469,47 +5519,47 @@ On Windows XP: C:\Documents and Settings[UserName]\My Documents\My Games\Skyrim\Saves </source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="87"/> <source>Move -></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="97"/> <source>Copy -></source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="123"/> <source><- Move</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="133"/> <source><- Copy</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.ui" line="156"/> <source>Done</source> - <translation type="unfinished">完æˆ</translation> + <translation>完æˆ</translation> </message> <message> <location filename="transfersavesdialog.ui" line="167"/> <source>Profile Characters</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="140"/> <source>Overwrite</source> - <translation type="unfinished">覆蓋</translation> + <translation>覆蓋</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="141"/> <source>Overwrite the file "%1"</source> - <translation type="unfinished"></translation> + <translation>覆蓋檔案 "%1"</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="157"/> @@ -5517,23 +5567,23 @@ On Windows XP: <location filename="transfersavesdialog.cpp" line="230"/> <location filename="transfersavesdialog.cpp" line="269"/> <source>Confirm</source> - <translation type="unfinished">確èª</translation> + <translation>確èª</translation> </message> <message> <location filename="transfersavesdialog.cpp" line="158"/> <location filename="transfersavesdialog.cpp" line="196"/> <source>Copy all save games of character "%1" to the profile?</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="231"/> <source>Move all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> <message> <location filename="transfersavesdialog.cpp" line="270"/> <source>Copy all save games of character "%1" to the global location? Please be aware that this will mess up the running number of save games.</source> - <translation type="unfinished"></translation> + <translation type="unfinished"/> </message> </context> -</TS> +</TS>
\ No newline at end of file diff --git a/src/organizercore.cpp b/src/organizercore.cpp new file mode 100644 index 00000000..68989c8c --- /dev/null +++ b/src/organizercore.cpp @@ -0,0 +1,1249 @@ +#include "organizercore.h"
+#include "mainwindow.h"
+#include "gameinfoimpl.h"
+#include "messagedialog.h"
+#include "logbuffer.h"
+#include "credentialsdialog.h"
+#include "filedialogmemory.h"
+#include "lockeddialog.h"
+#include "modinfodialog.h"
+#include "report.h"
+#include "spawn.h"
+#include "safewritefile.h"
+#include <ipluginmodpage.h>
+#include <directoryentry.h>
+#include <scopeguard.h>
+#include <utility.h>
+#include <appconfig.h>
+#include <questionboxmemory.h>
+#include <QNetworkInterface>
+#include <QMessageBox>
+#include <QDialogButtonBox>
+#include <QApplication>
+#include <Psapi.h>
+
+
+using namespace MOShared;
+using namespace MOBase;
+
+
+static bool isOnline()
+{
+ QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+
+ bool connected = false;
+ for (auto iter = interfaces.begin(); iter != interfaces.end() && !connected; ++iter) {
+ if ( (iter->flags() & QNetworkInterface::IsUp) &&
+ (iter->flags() & QNetworkInterface::IsRunning) &&
+ !(iter->flags() & QNetworkInterface::IsLoopBack)) {
+ auto addresses = iter->addressEntries();
+ if (addresses.count() == 0) {
+ continue;
+ }
+ qDebug("interface %s seems to be up (address: %s)",
+ qPrintable(iter->humanReadableName()),
+ qPrintable(addresses[0].ip().toString()));
+ connected = true;
+ }
+ }
+
+ return connected;
+}
+
+static bool renameFile(const QString &oldName, const QString &newName, bool overwrite = true)
+{
+ if (overwrite && QFile::exists(newName)) {
+ QFile::remove(newName);
+ }
+ return QFile::rename(oldName, newName);
+}
+
+static std::wstring getProcessName(DWORD processId)
+{
+ HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION, false, processId);
+
+ wchar_t buffer[MAX_PATH];
+ if (::GetProcessImageFileNameW(process, buffer, MAX_PATH) != 0) {
+ wchar_t *fileName = wcsrchr(buffer, L'\\');
+ if (fileName == nullptr) {
+ fileName = buffer;
+ } else {
+ fileName += 1;
+ }
+ return fileName;
+ } else {
+ return std::wstring(L"unknown");
+ }
+}
+
+static bool testForSteam()
+{
+ DWORD processIDs[1024];
+ DWORD bytesReturned;
+ if (!::EnumProcesses(processIDs, sizeof(processIDs), &bytesReturned)) {
+ qWarning("failed to determine if steam is running");
+ return true;
+ }
+
+ TCHAR processName[MAX_PATH];
+ for (unsigned int i = 0; i < bytesReturned / sizeof(DWORD); ++i) {
+ memset(processName, '\0', sizeof(TCHAR) * MAX_PATH);
+ if (processIDs[i] != 0) {
+ HANDLE process = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processIDs[i]);
+
+ if (process != NULL) {
+ HMODULE module;
+ DWORD ignore;
+
+ // first module in a process is always the binary
+ if (::EnumProcessModules(process, &module, sizeof(HMODULE) * 1, &ignore)) {
+ ::GetModuleBaseName(process, module, processName, MAX_PATH);
+ if ((_tcsicmp(processName, TEXT("steam.exe")) == 0) ||
+ (_tcsicmp(processName, TEXT("steamservice.exe")) == 0)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static void startSteam(QWidget *widget)
+{
+ QSettings steamSettings("HKEY_CURRENT_USER\\Software\\Valve\\Steam", QSettings::NativeFormat);
+ QString exe = steamSettings.value("SteamExe", "").toString();
+ if (!exe.isEmpty()) {
+ QString temp = QString("\"%1\"").arg(exe);
+ if (!QProcess::startDetached(temp)) {
+ reportError(QObject::tr("Failed to start \"%1\"").arg(temp));
+ } else {
+ QMessageBox::information(widget, QObject::tr("Waiting"),
+ QObject::tr("Please press OK once you're logged into steam."));
+ }
+ }
+}
+
+template <typename InputIterator>
+QStringList toStringList(InputIterator current, InputIterator end)
+{
+ QStringList result;
+ for (; current != end; ++current) {
+ result.append(*current);
+ }
+ return result;
+}
+
+
+OrganizerCore::OrganizerCore(const QSettings &initSettings)
+ : m_GameInfo(new GameInfoImpl())
+ , m_UserInterface(nullptr)
+ , m_PluginContainer(nullptr)
+ , m_CurrentProfile(nullptr)
+ , m_Settings()
+ , m_Updater(NexusInterface::instance())
+ , m_AboutToRun()
+ , m_FinishedRun()
+ , m_ModInstalled()
+ , m_ModList(this)
+ , m_PluginList(this)
+ , m_DirectoryRefresher()
+ , m_DirectoryStructure(new DirectoryEntry(L"data", nullptr, 0))
+ , m_DownloadManager(NexusInterface::instance(), this)
+ , m_InstallationManager()
+ , m_RefresherThread()
+ , m_AskForNexusPW(false)
+ , m_DirectoryUpdate(false)
+ , m_ArchivesInit(false)
+{
+ m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory());
+ m_DownloadManager.setPreferredServers(m_Settings.getPreferredServers());
+
+ NexusInterface::instance()->setCacheDirectory(m_Settings.getCacheDirectory());
+ NexusInterface::instance()->setNMMVersion(m_Settings.getNMMVersion());
+
+ m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory());
+
+ connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString,int)), this, SLOT(downloadSpeed(QString,int)));
+ connect(&m_DirectoryRefresher, SIGNAL(refreshed()), this, SLOT(directory_refreshed()));
+
+ connect(&m_ModList, SIGNAL(removeOrigin(QString)), this, SLOT(removeOrigin(QString)));
+
+ connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginSuccessful(bool)), this, SLOT(loginSuccessful(bool)));
+ connect(NexusInterface::instance()->getAccessManager(), SIGNAL(loginFailed(QString)), this, SLOT(loginFailed(QString)));
+
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
+
+ // make directory refresher run in a separate thread
+ m_RefresherThread.start();
+ m_DirectoryRefresher.moveToThread(&m_RefresherThread);
+
+ m_AskForNexusPW = initSettings.value("ask_for_nexuspw", true).toBool();
+}
+
+OrganizerCore::~OrganizerCore()
+{
+ m_RefresherThread.exit();
+ m_RefresherThread.wait();
+
+ prepareStart();
+
+ // profile has to be cleaned up before the modinfo-buffer is cleared
+ delete m_CurrentProfile;
+ m_CurrentProfile = nullptr;
+
+ ModInfo::clear();
+ LogBuffer::cleanQuit();
+ m_ModList.setProfile(nullptr);
+ NexusInterface::instance()->cleanup();
+
+ delete m_GameInfo;
+ delete m_DirectoryStructure;
+}
+
+void OrganizerCore::storeSettings()
+{
+ QString iniFile = ToQString(GameInfo::instance().getIniFilename());
+ shellCopy(iniFile, iniFile + ".new", true, qApp->activeWindow());
+
+ QSettings::Status result = QSettings::NoError;
+ {
+ QSettings settings(iniFile + ".new", QSettings::IniFormat);
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->storeSettings(settings);
+ }
+ settings.setValue("selected_profile", m_CurrentProfile->getName().toUtf8().constData());
+ settings.setValue("ask_for_nexuspw", m_AskForNexusPW);
+
+ settings.remove("customExecutables");
+ settings.beginWriteArray("customExecutables");
+ std::vector<Executable>::const_iterator current, end;
+ m_ExecutablesList.getExecutables(current, end);
+ int count = 0;
+ for (; current != end; ++current) {
+ const Executable &item = *current;
+ if (item.m_Custom || item.m_Toolbar) {
+ settings.setArrayIndex(count++);
+ settings.setValue("binary", item.m_BinaryInfo.absoluteFilePath());
+ settings.setValue("title", item.m_Title);
+ settings.setValue("arguments", item.m_Arguments);
+ settings.setValue("workingDirectory", item.m_WorkingDirectory);
+ settings.setValue("closeOnStart", item.m_CloseMO == ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE);
+ settings.setValue("steamAppID", item.m_SteamAppID);
+ settings.setValue("custom", item.m_Custom);
+ settings.setValue("toolbar", item.m_Toolbar);
+ }
+ }
+ settings.endArray();
+
+ QComboBox *executableBox = findChild<QComboBox*>("executablesListBox");
+ settings.setValue("selected_executable", executableBox->currentIndex());
+
+ FileDialogMemory::save(settings);
+
+ settings.sync();
+ result = settings.status();
+ }
+ if (result == QSettings::NoError) {
+ if (!shellRename(iniFile + ".new", iniFile, true, qApp->activeWindow())) {
+ DWORD err = ::GetLastError();
+ // make a second attempt using qt functions but if that fails print the error from the first attempt
+ if (!renameFile(iniFile + ".new", iniFile)) {
+ QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"),
+ tr("An error occured trying to write back MO settings: %1").arg(windowsErrorString(err)));
+ }
+ }
+ } else {
+ QString reason = result == QSettings::AccessError ? tr("File is write protected")
+ : result == QSettings::FormatError ? tr("Invalid file format (probably a bug)")
+ : tr("Unknown error %1").arg(result);
+ QMessageBox::critical(qApp->activeWindow(), tr("Failed to write settings"),
+ tr("An error occured trying to write back MO settings: %1").arg(reason));
+ }
+}
+
+void OrganizerCore::updateExecutablesList(QSettings &settings)
+{
+ m_ExecutablesList.init(m_PluginContainer->managedGame(ToQString(GameInfo::instance().getGameName())));
+
+ qDebug("setting up configured executables");
+
+ int numCustomExecutables = settings.beginReadArray("customExecutables");
+ for (int i = 0; i < numCustomExecutables; ++i) {
+ settings.setArrayIndex(i);
+ ExecutableInfo::CloseMOStyle closeMO =
+ settings.value("closeOnStart").toBool() ? ExecutableInfo::CloseMOStyle::DEFAULT_CLOSE
+ : ExecutableInfo::CloseMOStyle::DEFAULT_STAY;
+ m_ExecutablesList.addExecutable(settings.value("title").toString(),
+ settings.value("binary").toString(),
+ settings.value("arguments").toString(),
+ settings.value("workingDirectory", "").toString(),
+ closeMO,
+ settings.value("steamAppID", "").toString(),
+ settings.value("custom", true).toBool(),
+ settings.value("toolbar", false).toBool());
+ }
+
+ settings.endArray();
+}
+
+void OrganizerCore::setUserInterface(IUserInterface *userInterface, QWidget *widget)
+{
+ storeSettings();
+
+ m_UserInterface = userInterface;
+
+ connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex,int)), widget, SLOT(modorder_changed()));
+ connect(&m_ModList, SIGNAL(showMessage(QString)), widget, SLOT(showMessage(QString)));
+ connect(&m_ModList, SIGNAL(modRenamed(QString,QString)), widget, SLOT(modRenamed(QString,QString)));
+ connect(&m_ModList, SIGNAL(modUninstalled(QString)), widget, SLOT(modRemoved(QString)));
+ connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), widget, SLOT(modlistChanged(QModelIndex, int)));
+ connect(&m_ModList, SIGNAL(removeSelectedMods()), widget, SLOT(removeMod_clicked()));
+ connect(&m_ModList, SIGNAL(requestColumnSelect(QPoint)), widget, SLOT(displayColumnSelection(QPoint)));
+ connect(&m_ModList, SIGNAL(fileMoved(QString, QString, QString)), widget, SLOT(fileMoved(QString, QString, QString)));
+ connect(&m_DownloadManager, SIGNAL(downloadAdded()), widget, SLOT(scrollToBottom()));
+ connect(&m_DownloadManager, SIGNAL(showMessage(QString)), widget, SLOT(showMessage(QString)));
+
+ m_InstallationManager.setParentWidget(widget);
+ m_Updater.setUserInterface(widget);
+
+ // this currently wouldn't work reliably if the ui isn't initialized yet to display the result
+ if (isOnline() && !m_Settings.offlineMode()) {
+ m_Updater.testForUpdate();
+ } else {
+ qDebug("user doesn't seem to be connected to the internet");
+ }
+}
+
+void OrganizerCore::connectPlugins(PluginContainer *container)
+{
+ m_DownloadManager.setSupportedExtensions(m_InstallationManager.getSupportedExtensions());
+ m_PluginContainer = container;
+}
+
+void OrganizerCore::disconnectPlugins()
+{
+ m_AboutToRun.disconnect_all_slots();
+ m_FinishedRun.disconnect_all_slots();
+ m_ModInstalled.disconnect_all_slots();
+ m_ModList.disconnectSlots();
+ m_PluginList.disconnectSlots();
+
+ m_Settings.clearPlugins();
+ m_PluginContainer = nullptr;
+}
+
+Settings &OrganizerCore::settings()
+{
+ return m_Settings;
+}
+
+bool OrganizerCore::nexusLogin()
+{
+ QString username, password;
+
+ NXMAccessManager *accessManager = NexusInterface::instance()->getAccessManager();
+
+ if (!accessManager->loginAttempted()
+ && !accessManager->loggedIn()
+ && (m_Settings.getNexusLogin(username, password)
+ || (m_AskForNexusPW
+ && queryLogin(username, password)))) {
+ accessManager->login(username, password);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool OrganizerCore::queryLogin(QString &username, QString &password)
+{
+ CredentialsDialog dialog(qApp->activeWindow());
+ int res = dialog.exec();
+ if (dialog.neverAsk()) {
+ m_AskForNexusPW = false;
+ }
+ if (res == QDialog::Accepted) {
+ username = dialog.username();
+ password = dialog.password();
+ if (dialog.store()) {
+ m_Settings.setNexusLogin(username, password);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void OrganizerCore::startMOUpdate()
+{
+ if (nexusLogin()) {
+ m_PostLoginTasks.append([&]() { m_Updater.startUpdate(); });
+ } else {
+ m_Updater.startUpdate();
+ }
+}
+
+void OrganizerCore::downloadRequestedNXM(const QString &url)
+{
+ qDebug("download requested: %s", qPrintable(url));
+ if (nexusLogin()) {
+ m_PendingDownloads.append(url);
+ } else {
+ m_DownloadManager.addNXMDownload(url);
+ }
+}
+
+void OrganizerCore::externalMessage(const QString &message)
+{
+ if (message.left(6).toLower() == "nxm://") {
+ MessageDialog::showMessage(tr("Download started"), qApp->activeWindow());
+ downloadRequestedNXM(message);
+ }
+}
+
+void OrganizerCore::downloadRequested(QNetworkReply *reply, int modID, const QString &fileName)
+{
+ try {
+ if (m_DownloadManager.addDownload(reply, QStringList(), fileName, modID, 0, new ModRepositoryFileInfo(modID))) {
+ MessageDialog::showMessage(tr("Download started"), qApp->activeWindow());
+ }
+ } catch (const std::exception &e) {
+ MessageDialog::showMessage(tr("Download failed"), qApp->activeWindow());
+ qCritical("exception starting download: %s", e.what());
+ }
+}
+
+void OrganizerCore::removeOrigin(const QString &name)
+{
+ FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(name));
+ origin.enable(false);
+ refreshLists();
+}
+
+InstallationManager *OrganizerCore::installationManager()
+{
+ return &m_InstallationManager;
+}
+
+void OrganizerCore::setCurrentProfile(Profile *profile) {
+ delete m_CurrentProfile;
+ m_CurrentProfile = profile;
+ m_ModList.setProfile(profile);
+}
+
+MOBase::IGameInfo &OrganizerCore::gameInfo() const
+{
+ return *m_GameInfo;
+}
+
+MOBase::IModRepositoryBridge *OrganizerCore::createNexusBridge() const
+{
+ return new NexusBridge();
+}
+
+QString OrganizerCore::profileName() const
+{
+ if (m_CurrentProfile != NULL) {
+ return m_CurrentProfile->getName();
+ } else {
+ return "";
+ }
+}
+
+QString OrganizerCore::profilePath() const
+{
+ if (m_CurrentProfile != NULL) {
+ return m_CurrentProfile->getPath();
+ } else {
+ return "";
+ }
+}
+
+QString OrganizerCore::downloadsPath() const
+{
+ return QDir::fromNativeSeparators(m_Settings.getDownloadDirectory());
+}
+
+MOBase::VersionInfo OrganizerCore::appVersion() const
+{
+ return m_Updater.getVersion();
+}
+
+MOBase::IModInterface *OrganizerCore::getMod(const QString &name)
+{
+ unsigned int index = ModInfo::getIndex(name);
+ if (index == UINT_MAX) {
+ return NULL;
+ } else {
+ return ModInfo::getByIndex(index).data();
+ }
+}
+
+MOBase::IModInterface *OrganizerCore::createMod(GuessedValue<QString> &name)
+{
+ if (!m_InstallationManager.testOverwrite(name)) {
+ return NULL;
+ }
+
+ m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+
+ QString targetDirectory = QDir::fromNativeSeparators(m_Settings.getModDirectory()).append("/").append(name);
+
+ QSettings settingsFile(targetDirectory.mid(0).append("/meta.ini"), QSettings::IniFormat);
+
+ settingsFile.setValue("modid", 0);
+ settingsFile.setValue("version", "");
+ settingsFile.setValue("newestVersion", "");
+ settingsFile.setValue("category", 0);
+ settingsFile.setValue("installationFile", "");
+ return ModInfo::createFrom(QDir(targetDirectory), &m_DirectoryStructure).data();
+}
+
+bool OrganizerCore::removeMod(MOBase::IModInterface *mod)
+{
+ unsigned int index = ModInfo::getIndex(mod->name());
+ if (index == UINT_MAX) {
+ return mod->remove();
+ } else {
+ return ModInfo::removeMod(index);
+ }
+}
+
+void OrganizerCore::modDataChanged(MOBase::IModInterface *mod)
+{
+ refreshModList(false);
+}
+
+QVariant OrganizerCore::pluginSetting(const QString &pluginName, const QString &key) const
+{
+ return m_Settings.pluginSetting(pluginName, key);
+}
+
+void OrganizerCore::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
+{
+ m_Settings.setPluginSetting(pluginName, key, value);
+}
+
+QVariant OrganizerCore::persistent(const QString &pluginName, const QString &key, const QVariant &def) const
+{
+ return m_Settings.pluginPersistent(pluginName, key, def);
+}
+
+void OrganizerCore::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
+{
+ m_Settings.setPluginPersistent(pluginName, key, value, sync);
+}
+
+QString OrganizerCore::pluginDataPath() const
+{
+ QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
+ return pluginPath + "/data";
+}
+
+MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName)
+{
+ if (m_CurrentProfile == nullptr) {
+ return nullptr;
+ }
+
+ bool hasIniTweaks = false;
+ GuessedValue<QString> modName;
+ m_CurrentProfile->writeModlistNow();
+ m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
+ MessageDialog::showMessage(tr("Installation successful"), qApp->activeWindow());
+ refreshModList();
+
+ int modIndex = ModInfo::getIndex(modName);
+ if (modIndex != UINT_MAX) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
+ if (hasIniTweaks
+ && (m_UserInterface != nullptr)
+ && (QMessageBox::question(qApp->activeWindow(), tr("Configure Mod"),
+ tr("This mod contains ini tweaks. Do you want to configure them now?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
+ m_UserInterface->displayModInformation(modInfo, modIndex, ModInfoDialog::TAB_INIFILES);
+ }
+ m_ModInstalled(modName);
+ return modInfo.data();
+ } else {
+ reportError(tr("mod \"%1\" not found").arg(modName));
+ }
+ } else if (m_InstallationManager.wasCancelled()) {
+ QMessageBox::information(qApp->activeWindow(), tr("Installation cancelled"),
+ tr("The mod was not installed completely."), QMessageBox::Ok);
+ }
+ return nullptr;
+}
+
+QString OrganizerCore::resolvePath(const QString &fileName) const
+{
+ if (m_DirectoryStructure == nullptr) {
+ return QString();
+ }
+ const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(fileName), nullptr);
+ if (file.get() != nullptr) {
+ return ToQString(file->getFullPath());
+ } else {
+ return QString();
+ }
+}
+
+QStringList OrganizerCore::listDirectories(const QString &directoryName) const
+{
+ QStringList result;
+ DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(directoryName));
+ if (dir != NULL) {
+ std::vector<DirectoryEntry*>::iterator current, end;
+ dir->getSubDirectories(current, end);
+ for (; current != end; ++current) {
+ result.append(ToQString((*current)->getName()));
+ }
+ }
+ return result;
+}
+
+QStringList OrganizerCore::findFiles(const QString &path, const std::function<bool (const QString &)> &filter) const
+{
+ QStringList result;
+ DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path));
+ if (dir != NULL) {
+ std::vector<FileEntry::Ptr> files = dir->getFiles();
+ foreach (FileEntry::Ptr file, files) {
+ if (filter(ToQString(file->getFullPath()))) {
+ result.append(ToQString(file->getFullPath()));
+ }
+ }
+ } else {
+ qWarning("directory %s not found", qPrintable(path));
+ }
+ return result;
+}
+
+QStringList OrganizerCore::getFileOrigins(const QString &fileName) const
+{
+ QStringList result;
+ const FileEntry::Ptr file = m_DirectoryStructure->searchFile(ToWString(QFileInfo(fileName).fileName()), NULL);
+
+ if (file.get() != NULL) {
+ result.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin()).getName()));
+ foreach (int i, file->getAlternatives()) {
+ result.append(ToQString(m_DirectoryStructure->getOriginByID(i).getName()));
+ }
+ } else {
+ qDebug("%s not found", qPrintable(fileName));
+ }
+ return result;
+}
+
+QList<MOBase::IOrganizer::FileInfo> OrganizerCore::findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const
+{
+ QList<IOrganizer::FileInfo> result;
+ DirectoryEntry *dir = m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path));
+ if (dir != NULL) {
+ std::vector<FileEntry::Ptr> files = dir->getFiles();
+ foreach (FileEntry::Ptr file, files) {
+ IOrganizer::FileInfo info;
+ info.filePath = ToQString(file->getFullPath());
+ bool fromArchive = false;
+ info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)).getName()));
+ info.archive = fromArchive ? ToQString(file->getArchive()) : "";
+ foreach (int idx, file->getAlternatives()) {
+ info.origins.append(ToQString(m_DirectoryStructure->getOriginByID(idx).getName()));
+ }
+
+ if (filter(info)) {
+ result.append(info);
+ }
+ }
+ }
+ return result;
+}
+
+DownloadManager *OrganizerCore::downloadManager()
+{
+ return &m_DownloadManager;
+}
+
+PluginList *OrganizerCore::pluginList()
+{
+ return &m_PluginList;
+}
+
+ModList *OrganizerCore::modList()
+{
+ return &m_ModList;
+}
+
+void OrganizerCore::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID)
+{
+ LockedDialog *dialog = new LockedDialog(qApp->activeWindow());
+ dialog->show();
+ ON_BLOCK_EXIT([&] () { dialog->hide(); dialog->deleteLater(); });
+
+ HANDLE processHandle = spawnBinaryDirect(binary, arguments, m_CurrentProfile->getName(), currentDirectory, steamAppID);
+ if (processHandle != INVALID_HANDLE_VALUE) {
+ if (closeAfterStart && (m_UserInterface != nullptr)) {
+ m_UserInterface->close();
+ } else {
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->setEnabled(false);
+ }
+ // re-enable the locked dialog because what'd be the point otherwise?
+ dialog->setEnabled(true);
+
+ QCoreApplication::processEvents();
+
+ DWORD processExitCode;
+ DWORD retLen;
+ JOBOBJECT_BASIC_PROCESS_ID_LIST info;
+
+ {
+ DWORD currentProcess = 0UL;
+ bool isJobHandle = true;
+
+ DWORD res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
+ while ((res != WAIT_FAILED) && (res != WAIT_OBJECT_0) && !dialog->unlockClicked()) {
+ if (isJobHandle) {
+ if (::QueryInformationJobObject(processHandle, JobObjectBasicProcessIdList, &info, sizeof(info), &retLen) > 0) {
+ if (info.NumberOfProcessIdsInList == 0) {
+ break;
+ } else {
+ if (info.ProcessIdList[0] != currentProcess) {
+ currentProcess = info.ProcessIdList[0];
+ dialog->setProcessName(ToQString(getProcessName(currentProcess)));
+ }
+ }
+ } else {
+ // the info-object I passed only provides space for 1 process id. but since this code only cares about whether there
+ // is more than one that's good enough. ERROR_MORE_DATA simply signals there are at least two processes running.
+ // any other error probably means the handle is a regular process handle, probably caused by running MO in a job without
+ // the right to break out.
+ if (::GetLastError() != ERROR_MORE_DATA) {
+ isJobHandle = false;
+ }
+ }
+ }
+
+ // keep processing events so the app doesn't appear dead
+ QCoreApplication::processEvents();
+
+ res = ::MsgWaitForMultipleObjects(1, &processHandle, false, 1000, QS_KEY | QS_MOUSE);
+ }
+ ::GetExitCodeProcess(processHandle, &processExitCode);
+ }
+ ::CloseHandle(processHandle);
+
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->setEnabled(true);
+ }
+ refreshDirectoryStructure();
+ // need to remove our stored load order because it may be outdated if a foreign tool changed the
+ // file time. After removing that file, refreshESPList will use the file time as the order
+ if (GameInfo::instance().getLoadOrderMechanism() == GameInfo::TYPE_FILETIME) {
+ QFile::remove(m_CurrentProfile->getLoadOrderFileName());
+ refreshESPList();
+ }
+
+ m_FinishedRun(binary.absoluteFilePath(), processExitCode);
+ }
+ }
+}
+
+HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName,
+ const QDir ¤tDirectory, const QString &steamAppID)
+{
+ prepareStart();
+
+ if (!binary.exists()) {
+ reportError(tr("Executable \"%1\" not found").arg(binary.fileName()));
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!steamAppID.isEmpty()) {
+ ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(steamAppID).c_str());
+ } else {
+ ::SetEnvironmentVariableW(L"SteamAPPId", ToWString(m_Settings.getSteamAppID()).c_str());
+ }
+
+ if ((GameInfo::instance().requiresSteam())
+ && (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) {
+ if (!testForSteam()) {
+ QWidget *window = qApp->activeWindow();
+ if ((window != nullptr) && (!window->isVisible())) {
+ window = nullptr;
+ }
+ if (QuestionBoxMemory::query(window, "steamQuery",
+ tr("Start Steam?"),
+ tr("Steam is required to be running already to correctly start the game. "
+ "Should MO try to start steam now?"),
+ QDialogButtonBox::Yes | QDialogButtonBox::No) == QDialogButtonBox::Yes) {
+ startSteam(qApp->activeWindow());
+ }
+ }
+ }
+
+ while (m_DirectoryUpdate) {
+ ::Sleep(100);
+ QCoreApplication::processEvents();
+ }
+
+ // need to make sure all data is saved before we start the application
+ if (m_CurrentProfile != nullptr) {
+ m_CurrentProfile->writeModlistNow(true);
+ }
+
+ // TODO: should also pass arguments
+ if (m_AboutToRun(binary.absoluteFilePath())) {
+ return startBinary(binary, arguments, profileName, m_Settings.logLevel(), currentDirectory, true);
+ } else {
+ qDebug("start of \"%s\" canceled by plugin", qPrintable(binary.absoluteFilePath()));
+ return INVALID_HANDLE_VALUE;
+ }
+}
+
+HANDLE OrganizerCore::startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile)
+{
+ if (m_UserInterface != nullptr) {
+ return m_UserInterface->startApplication(executable, args, cwd, profile);
+ }
+}
+
+bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode) const
+{
+ if (m_UserInterface != nullptr) {
+ return m_UserInterface->waitForProcessOrJob(handle, exitCode);
+ }
+}
+
+bool OrganizerCore::onAboutToRun(const std::function<bool (const QString &)> &func)
+{
+ auto conn = m_AboutToRun.connect(func);
+ return conn.connected();
+}
+
+bool OrganizerCore::onFinishedRun(const std::function<void (const QString &, unsigned int)> &func)
+{
+ auto conn = m_FinishedRun.connect(func);
+ return conn.connected();
+}
+
+bool OrganizerCore::onModInstalled(const std::function<void (const QString &)> &func)
+{
+ auto conn = m_ModInstalled.connect(func);
+ return conn.connected();
+}
+
+void OrganizerCore::refreshModList(bool saveChanges)
+{
+ // don't lose changes!
+ if (saveChanges) {
+ m_CurrentProfile->writeModlistNow(true);
+ }
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
+
+ m_CurrentProfile->refreshModStatus();
+
+ m_ModList.notifyChange(-1);
+
+ refreshDirectoryStructure();
+}
+
+void OrganizerCore::refreshESPList()
+{
+ m_CurrentProfile->writeModlist();
+
+ // clear list
+ try {
+ m_PluginList.refresh(m_CurrentProfile->getName(),
+ *m_DirectoryStructure,
+ m_CurrentProfile->getPluginsFileName(),
+ m_CurrentProfile->getLoadOrderFileName(),
+ m_CurrentProfile->getLockedOrderFileName());
+ } catch (const std::exception &e) {
+ reportError(tr("Failed to refresh list of esps: %1").arg(e.what()));
+ }
+}
+
+
+void OrganizerCore::refreshBSAList()
+{
+ m_ArchivesInit = false;
+
+ m_DefaultArchives.clear();
+
+ wchar_t buffer[256];
+ std::wstring iniFileName = ToWString(QDir::toNativeSeparators(m_CurrentProfile->getIniFileName()));
+ if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
+ L"", buffer, 256, iniFileName.c_str()) != 0) {
+ m_DefaultArchives = ToQString(buffer).split(',');
+ } else {
+ std::vector<std::wstring> vanillaBSAs = GameInfo::instance().getVanillaBSAs();
+ for (auto iter = vanillaBSAs.begin(); iter != vanillaBSAs.end(); ++iter) {
+ m_DefaultArchives.append(ToQString(*iter));
+ }
+ }
+
+ if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().append(L"2").c_str(),
+ L"", buffer, 256, iniFileName.c_str()) != 0) {
+ m_DefaultArchives.append(ToQString(buffer).split(','));
+ }
+
+ for (int i = 0; i < m_DefaultArchives.count(); ++i) {
+ m_DefaultArchives[i] = m_DefaultArchives[i].trimmed();
+ }
+
+ m_ActiveArchives.clear();
+
+ auto iter = enabledArchives();
+ m_ActiveArchives = toStringList(iter.begin(), iter.end());
+ if (m_ActiveArchives.isEmpty()) {
+ m_ActiveArchives = m_DefaultArchives;
+ }
+
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->updateBSAList();
+ }
+
+ m_ArchivesInit = true;
+}
+
+void OrganizerCore::refreshLists()
+{
+ if ((m_CurrentProfile != nullptr) && m_DirectoryStructure->isPopulated()) {
+ refreshESPList();
+ refreshBSAList();
+ } // no point in refreshing lists if no files have been added to the directory tree
+}
+
+void OrganizerCore::updateModActiveState(int index, bool active)
+{
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
+
+ QDir dir(modInfo->absolutePath());
+ foreach (const QString &esm, dir.entryList(QStringList("*.esm"), QDir::Files)) {
+ m_PluginList.enableESP(esm, active);
+ }
+ int enabled = 0;
+ QStringList esps = dir.entryList(QStringList("*.esp"), QDir::Files);
+ foreach (const QString &esp, esps) {
+ if (active != m_PluginList.isEnabled(esp)) {
+ m_PluginList.enableESP(esp, active);
+ ++enabled;
+ }
+ }
+ if (active && (enabled > 1)) {
+ MessageDialog::showMessage(tr("Multiple esps activated, please check that they don't conflict."), qApp->activeWindow());
+ }
+ m_PluginList.refreshLoadOrder();
+ // immediately save affected lists
+ savePluginList();
+// refreshBSAList();
+}
+
+void OrganizerCore::updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo)
+{
+ // add files of the bsa to the directory structure
+ m_DirectoryRefresher.addModFilesToStructure(m_DirectoryStructure
+ , modInfo->name()
+ , m_CurrentProfile->getModPriority(index)
+ , modInfo->absolutePath()
+ , modInfo->stealFiles()
+ );
+ DirectoryRefresher::cleanStructure(m_DirectoryStructure);
+ // need to refresh plugin list now so we can activate esps
+ refreshESPList();
+ // activate all esps of the specified mod so the bsas get activated along with it
+ updateModActiveState(index, true);
+ // now we need to refresh the bsa list and save it so there is no confusion about what archives are avaiable and active
+ refreshBSAList();
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->saveArchiveList();
+ }
+ m_DirectoryRefresher.setMods(m_CurrentProfile->getActiveMods(), enabledArchives());
+
+ // finally also add files from bsas to the directory structure
+ m_DirectoryRefresher.addModBSAToStructure(m_DirectoryStructure
+ , modInfo->name()
+ , m_CurrentProfile->getModPriority(index)
+ , modInfo->absolutePath()
+ , modInfo->archives()
+ );
+}
+
+void OrganizerCore::requestDownload(const QUrl &url, QNetworkReply *reply)
+{
+ if (m_PluginContainer != nullptr) {
+ for (IPluginModPage *modPage : m_PluginContainer->plugins<IPluginModPage>()) {
+ ModRepositoryFileInfo *fileInfo = new ModRepositoryFileInfo();
+ if (modPage->handlesDownload(url, reply->url(), *fileInfo)) {
+ fileInfo->repository = modPage->name();
+ m_DownloadManager.addDownload(reply, fileInfo);
+ return;
+ }
+ }
+ }
+
+ // no mod found that could handle the download. Is it a nexus mod?
+ if (url.host() == "www.nexusmods.com") {
+ int modID = 0;
+ int fileID = 0;
+ QRegExp modExp("mods/(\\d+)");
+ if (modExp.indexIn(url.toString()) != -1) {
+ modID = modExp.cap(1).toInt();
+ }
+ QRegExp fileExp("fid=(\\d+)");
+ if (fileExp.indexIn(reply->url().toString()) != -1) {
+ fileID = fileExp.cap(1).toInt();
+ }
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo(modID, fileID));
+ } else {
+ if (QMessageBox::question(qApp->activeWindow(), tr("Download?"),
+ tr("A download has been started but no installed page plugin recognizes it.\n"
+ "If you download anyway no information (i.e. version) will be associated with the download.\n"
+ "Continue?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ m_DownloadManager.addDownload(reply, new ModRepositoryFileInfo());
+ }
+ }
+}
+
+ModListSortProxy *OrganizerCore::createModListProxyModel()
+{
+ ModListSortProxy *result = new ModListSortProxy(m_CurrentProfile, this);
+ result->setSourceModel(&m_ModList);
+ return result;
+}
+
+PluginListSortProxy *OrganizerCore::createPluginListProxyModel()
+{
+ PluginListSortProxy *result = new PluginListSortProxy(this);
+ result->setSourceModel(&m_PluginList);
+ return result;
+}
+
+std::set<QString> OrganizerCore::enabledArchives()
+{
+ std::set<QString> result;
+ QFile archiveFile(m_CurrentProfile->getArchivesFileName());
+ if (archiveFile.open(QIODevice::ReadOnly)) {
+ while (!archiveFile.atEnd()) {
+ result.insert(QString::fromUtf8(archiveFile.readLine()).trimmed());
+ }
+ archiveFile.close();
+ }
+ return result;
+}
+
+void OrganizerCore::refreshDirectoryStructure()
+{
+ if (!m_DirectoryUpdate) {
+ m_CurrentProfile->writeModlistNow(true);
+
+ m_DirectoryUpdate = true;
+ std::vector<std::tuple<QString, QString, int> > activeModList = m_CurrentProfile->getActiveMods();
+
+ m_DirectoryRefresher.setMods(activeModList, enabledArchives());
+
+ QTimer::singleShot(0, &m_DirectoryRefresher, SLOT(refresh()));
+ } else {
+ qDebug("directory update");
+ }
+}
+
+void OrganizerCore::directory_refreshed()
+{
+ DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure();
+ Q_ASSERT(newStructure != m_DirectoryStructure);
+ if (newStructure != nullptr) {
+ std::swap(m_DirectoryStructure, newStructure);
+ delete newStructure;
+ } else {
+ // TODO: don't know why this happens, this slot seems to get called twice with only one emit
+ return;
+ }
+ m_DirectoryUpdate = false;
+ if (m_CurrentProfile != nullptr) {
+ refreshLists();
+ }
+
+ for (int i = 0; i < m_ModList.rowCount(); ++i) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ modInfo->clearCaches();
+ }
+}
+
+void OrganizerCore::profileRefresh()
+{
+ // have to refresh mods twice (again in refreshModList), otherwise the refresh isn't complete. Not sure why
+ ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure, m_Settings.displayForeign());
+ m_CurrentProfile->refreshModStatus();
+
+ refreshModList();
+}
+
+void OrganizerCore::modStatusChanged(unsigned int index)
+{
+ try {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
+ if (m_CurrentProfile->modEnabled(index)) {
+ updateModInDirectoryStructure(index, modInfo);
+ } else {
+ updateModActiveState(index, false);
+ refreshESPList();
+ if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
+ FilesOrigin &origin = m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()));
+ origin.enable(false);
+ }
+ }
+ modInfo->clearCaches();
+
+ for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ int priority = m_CurrentProfile->getModPriority(i);
+ if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
+ // priorities in the directory structure are one higher because data is 0
+ m_DirectoryStructure->getOriginByName(ToWString(modInfo->name())).setPriority(priority + 1);
+ }
+ }
+ m_DirectoryStructure->getFileRegister()->sortOrigins();
+
+ refreshLists();
+ } catch (const std::exception& e) {
+ reportError(tr("failed to update mod list: %1").arg(e.what()));
+ }
+}
+
+void OrganizerCore::loginSuccessful(bool necessary)
+{
+ if (necessary) {
+ MessageDialog::showMessage(tr("login successful"), qApp->activeWindow());
+ }
+ foreach (QString url, m_PendingDownloads) {
+ downloadRequestedNXM(url);
+ }
+ m_PendingDownloads.clear();
+ for (auto task : m_PostLoginTasks) {
+ task();
+ }
+
+ m_PostLoginTasks.clear();
+ NexusInterface::instance()->loginCompleted();
+}
+
+void OrganizerCore::loginSuccessfulUpdate(bool necessary)
+{
+ if (necessary) {
+ MessageDialog::showMessage(tr("login successful"), qApp->activeWindow());
+ }
+ m_Updater.startUpdate();
+}
+
+void OrganizerCore::loginFailed(const QString &message)
+{
+ if (!m_PendingDownloads.isEmpty()) {
+ MessageDialog::showMessage(tr("login failed: %1. Trying to download anyway").arg(message), qApp->activeWindow());
+ foreach (QString url, m_PendingDownloads) {
+ downloadRequestedNXM(url);
+ }
+ m_PendingDownloads.clear();
+ } else {
+ MessageDialog::showMessage(tr("login failed: %1").arg(message), qApp->activeWindow());
+ m_PostLoginTasks.clear();
+ }
+ NexusInterface::instance()->loginCompleted();
+}
+
+
+void OrganizerCore::loginFailedUpdate(const QString &message)
+{
+ MessageDialog::showMessage(tr("login failed: %1. You need to log-in with Nexus to update MO.").arg(message), qApp->activeWindow());
+}
+
+
+std::vector<unsigned int> OrganizerCore::activeProblems() const
+{
+ std::vector<unsigned int> problems;
+ if (enabledCount() > 255) {
+ problems.push_back(PROBLEM_TOOMANYPLUGINS);
+ }
+ return problems;
+}
+
+QString OrganizerCore::shortDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_TOOMANYPLUGINS: {
+ return tr("Too many esps and esms enabled");
+ } break;
+ default: {
+ return tr("Description missing");
+ } break;
+ }
+}
+
+QString OrganizerCore::fullDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_TOOMANYPLUGINS: {
+ return tr("The game doesn't allow more than 255 active plugins (including the official ones) to be loaded. You have to disable some unused plugins or "
+ "merge some plugins into one. You can find a guide here: <a href=\"http://wiki.step-project.com/Guide:Merging_Plugins\">http://wiki.step-project.com/Guide:Merging_Plugins</a>");
+ } break;
+ default: {
+ return tr("Description missing");
+ } break;
+ }
+}
+
+bool OrganizerCore::hasGuidedFix(unsigned int) const
+{
+ return false;
+}
+
+void OrganizerCore::startGuidedFix(unsigned int) const
+{
+}
+
+bool OrganizerCore::saveCurrentLists()
+{
+ if (m_DirectoryUpdate) {
+ qWarning("not saving lists during directory update");
+ return false;
+ }
+
+ try {
+ savePluginList();
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->saveArchiveList();
+ }
+ } catch (const std::exception &e) {
+ reportError(tr("failed to save load order: %1").arg(e.what()));
+ }
+
+ return true;
+}
+
+void OrganizerCore::savePluginList()
+{
+ m_PluginList.saveTo(m_CurrentProfile->getPluginsFileName(),
+ m_CurrentProfile->getLoadOrderFileName(),
+ m_CurrentProfile->getLockedOrderFileName(),
+ m_CurrentProfile->getDeleterFileName(),
+ m_Settings.hideUncheckedPlugins());
+ m_PluginList.saveLoadOrder(*m_DirectoryStructure);
+}
+
+void OrganizerCore::prepareStart() {
+ if (m_CurrentProfile == nullptr) {
+ return;
+ }
+ m_CurrentProfile->writeModlist();
+ m_CurrentProfile->createTweakedIniFile();
+ saveCurrentLists();
+ m_Settings.setupLoadMechanism();
+ storeSettings();
+}
+
diff --git a/src/organizercore.h b/src/organizercore.h new file mode 100644 index 00000000..b362a002 --- /dev/null +++ b/src/organizercore.h @@ -0,0 +1,239 @@ +#ifndef ORGANIZERCORE_H
+#define ORGANIZERCORE_H
+
+
+#include "profile.h"
+#include "selfupdater.h"
+#include "iuserinterface.h"
+#include "settings.h"
+#include "modlist.h"
+#include "pluginlist.h"
+#include "directoryrefresher.h"
+#include "installationmanager.h"
+#include "downloadmanager.h"
+#include "modlistsortproxy.h"
+#include "pluginlistsortproxy.h"
+#include "executableslist.h"
+#include <directoryentry.h>
+#include <imoinfo.h>
+#include <iplugindiagnose.h>
+#include <versioninfo.h>
+#include <guessedvalue.h>
+#include <boost/signals2.hpp>
+#include <QSettings>
+#include <QString>
+#include <QThread>
+
+
+class PluginContainer;
+
+
+class OrganizerCore : public QObject, public MOBase::IPluginDiagnose
+{
+
+ Q_OBJECT
+ Q_INTERFACES(MOBase::IPluginDiagnose)
+
+private:
+
+ struct SignalCombinerAnd
+ {
+ typedef bool result_type;
+ template<typename InputIterator>
+ bool operator()(InputIterator first, InputIterator last) const
+ {
+ while (first != last) {
+ if (!(*first)) {
+ return false;
+ }
+ ++first;
+ }
+ return true;
+ }
+ };
+
+private:
+
+ typedef boost::signals2::signal<bool (const QString&), SignalCombinerAnd> SignalAboutToRunApplication;
+ typedef boost::signals2::signal<void (const QString&, unsigned int)> SignalFinishedRunApplication;
+ typedef boost::signals2::signal<void (const QString&)> SignalModInstalled;
+
+public:
+
+ OrganizerCore(const QSettings &initSettings);
+
+ ~OrganizerCore();
+
+ void setUserInterface(IUserInterface *userInterface, QWidget *widget);
+ void connectPlugins(PluginContainer *container);
+ void disconnectPlugins();
+
+ void updateExecutablesList(QSettings &settings);
+
+ void startMOUpdate();
+
+ Settings &settings();
+ SelfUpdater *updater() { return &m_Updater; }
+ InstallationManager *installationManager();
+ MOShared::DirectoryEntry *directoryStructure() { return m_DirectoryStructure; }
+ DirectoryRefresher *directoryRefresher() { return &m_DirectoryRefresher; }
+ ExecutablesList *executablesList() { return &m_ExecutablesList; }
+ void setExecutablesDialog(const ExecutablesList &executablesList) { m_ExecutablesList = executablesList; }
+
+ Profile *currentProfile() { return m_CurrentProfile; }
+ void setCurrentProfile(Profile *profile);
+
+ void setExecutablesList(const ExecutablesList &executablesList);
+
+ std::set<QString> enabledArchives();
+
+ MOBase::VersionInfo getVersion() const { return m_Updater.getVersion(); }
+
+ ModListSortProxy *createModListProxyModel();
+ PluginListSortProxy *createPluginListProxyModel();
+
+ bool isArchivesInit() const { return m_ArchivesInit; }
+
+ bool saveCurrentLists();
+ void savePluginList();
+
+ void prepareStart();
+
+ void refreshESPList();
+ void refreshBSAList();
+
+ void refreshDirectoryStructure();
+ void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
+
+ void requestDownload(const QUrl &url, QNetworkReply *reply);
+
+ void doAfterLogin(std::function<void()> &function) { m_PostLoginTasks.append(function); }
+
+ void spawnBinary(const QFileInfo &binary, const QString &arguments = "", const QDir ¤tDirectory = QDir(), bool closeAfterStart = true, const QString &steamAppID = "");
+
+ void modStatusChanged(unsigned int index);
+
+ void loginSuccessful(bool necessary);
+ void loginSuccessfulUpdate(bool necessary);
+ void loginFailed(const QString &message);
+ void loginFailedUpdate(const QString &message);
+
+public:
+ virtual MOBase::IGameInfo &gameInfo() const;
+ virtual MOBase::IModRepositoryBridge *createNexusBridge() const;
+ virtual QString profileName() const;
+ virtual QString profilePath() const;
+ virtual QString downloadsPath() const;
+ virtual MOBase::VersionInfo appVersion() const;
+ virtual MOBase::IModInterface *getMod(const QString &name);
+ virtual MOBase::IModInterface *createMod(MOBase::GuessedValue<QString> &name);
+ virtual bool removeMod(MOBase::IModInterface *mod);
+ virtual void modDataChanged(MOBase::IModInterface *mod);
+ virtual QVariant pluginSetting(const QString &pluginName, const QString &key) const;
+ virtual void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
+ virtual QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def) const;
+ virtual void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
+ virtual QString pluginDataPath() const;
+ virtual MOBase::IModInterface *installMod(const QString &fileName);
+ virtual QString resolvePath(const QString &fileName) const;
+ virtual QStringList listDirectories(const QString &directoryName) const;
+ virtual QStringList findFiles(const QString &path, const std::function<bool (const QString &)> &filter) const;
+ virtual QStringList getFileOrigins(const QString &fileName) const;
+ virtual QList<MOBase::IOrganizer::FileInfo> findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const;
+ virtual DownloadManager *downloadManager();
+ virtual PluginList *pluginList();
+ virtual ModList *modList();
+ virtual HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile);
+ virtual bool waitForApplication(HANDLE handle, LPDWORD exitCode) const;
+ virtual bool onModInstalled(const std::function<void (const QString &)> &func);
+ virtual bool onAboutToRun(const std::function<bool (const QString &)> &func);
+ virtual bool onFinishedRun(const std::function<void (const QString &, unsigned int)> &func);
+ virtual void refreshModList(bool saveChanges = true);
+
+public: // IPluginDiagnose interface
+
+ virtual std::vector<unsigned int> activeProblems() const;
+ virtual QString shortDescription(unsigned int key) const;
+ virtual QString fullDescription(unsigned int key) const;
+ virtual bool hasGuidedFix(unsigned int key) const;
+ virtual void startGuidedFix(unsigned int key) const;
+
+public slots:
+
+ void profileRefresh();
+ void externalMessage(const QString &message);
+
+ void refreshLists();
+
+signals:
+
+ /**
+ * @brief emitted after a mod has been installed
+ * @node this is currently only used for tutorials
+ */
+ void modInstalled();
+
+private:
+
+ void storeSettings();
+
+ bool queryLogin(QString &username, QString &password);
+
+ bool nexusLogin();
+
+ HANDLE spawnBinaryDirect(const QFileInfo &binary, const QString &arguments, const QString &profileName, const QDir ¤tDirectory, const QString &steamAppID);
+ void updateModActiveState(int index, bool active);
+
+private slots:
+
+ void directory_refreshed();
+ void downloadRequestedNXM(const QString &url);
+ void downloadRequested(QNetworkReply *reply, int modID, const QString &fileName);
+ void removeOrigin(const QString &name);
+
+private:
+
+ static const unsigned int PROBLEM_TOOMANYPLUGINS = 1;
+
+private:
+
+ MOBase::IGameInfo *m_GameInfo;
+
+ IUserInterface *m_UserInterface;
+ PluginContainer *m_PluginContainer;
+
+ Profile *m_CurrentProfile;
+
+ Settings m_Settings;
+
+ SelfUpdater m_Updater;
+
+ SignalAboutToRunApplication m_AboutToRun;
+ SignalFinishedRunApplication m_FinishedRun;
+ SignalModInstalled m_ModInstalled;
+
+ ModList m_ModList;
+ PluginList m_PluginList;
+
+ QList<std::function<void()>> m_PostLoginTasks;
+
+ ExecutablesList m_ExecutablesList;
+ QStringList m_PendingDownloads;
+ QStringList m_DefaultArchives;
+ QStringList m_ActiveArchives;
+
+ DirectoryRefresher m_DirectoryRefresher;
+ MOShared::DirectoryEntry *m_DirectoryStructure;
+
+ DownloadManager m_DownloadManager;
+ InstallationManager m_InstallationManager;
+
+ QThread m_RefresherThread;
+
+ bool m_AskForNexusPW;
+ bool m_DirectoryUpdate;
+ bool m_ArchivesInit;
+
+};
+
+#endif // ORGANIZERCORE_H
diff --git a/src/organizerproxy.cpp b/src/organizerproxy.cpp index 903c979e..07a006f5 100644 --- a/src/organizerproxy.cpp +++ b/src/organizerproxy.cpp @@ -7,50 +7,40 @@ using namespace MOBase; using namespace MOShared;
-OrganizerProxy::OrganizerProxy(MainWindow *window, const QString &pluginName)
- : m_Proxied(window)
+OrganizerProxy::OrganizerProxy(OrganizerCore *organizer, const QString &pluginName)
+ : m_Proxied(organizer)
, m_PluginName(pluginName)
{
}
IGameInfo &OrganizerProxy::gameInfo() const
{
- return *m_Proxied->m_GameInfo;
+ return m_Proxied->gameInfo();
}
-
IModRepositoryBridge *OrganizerProxy::createNexusBridge() const
{
return new NexusBridge(m_PluginName);
}
-
QString OrganizerProxy::profileName() const
{
- if (m_Proxied->m_CurrentProfile != NULL) {
- return m_Proxied->m_CurrentProfile->getName();
- } else {
- return "";
- }
+ return m_Proxied->profileName();
}
QString OrganizerProxy::profilePath() const
{
- if (m_Proxied->m_CurrentProfile != NULL) {
- return m_Proxied->m_CurrentProfile->getPath();
- } else {
- return "";
- }
+ return m_Proxied->profilePath();
}
QString OrganizerProxy::downloadsPath() const
{
- return QDir::fromNativeSeparators(m_Proxied->m_Settings.getDownloadDirectory());
+ return m_Proxied->downloadsPath();
}
VersionInfo OrganizerProxy::appVersion() const
{
- return m_Proxied->m_Updater.getVersion();
+ return m_Proxied->appVersion();
}
IModInterface *OrganizerProxy::getMod(const QString &name)
@@ -68,35 +58,34 @@ bool OrganizerProxy::removeMod(IModInterface *mod) return m_Proxied->removeMod(mod);
}
-void OrganizerProxy::modDataChanged(IModInterface*)
+void OrganizerProxy::modDataChanged(IModInterface *mod)
{
- m_Proxied->refreshModList();
+ m_Proxied->modDataChanged(mod);
}
QVariant OrganizerProxy::pluginSetting(const QString &pluginName, const QString &key) const
{
- return m_Proxied->m_Settings.pluginSetting(pluginName, key);
+ return m_Proxied->pluginSetting(pluginName, key);
}
void OrganizerProxy::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
{
- m_Proxied->m_Settings.setPluginSetting(pluginName, key, value);
+ m_Proxied->setPluginSetting(pluginName, key, value);
}
QVariant OrganizerProxy::persistent(const QString &pluginName, const QString &key, const QVariant &def) const
{
- return m_Proxied->m_Settings.pluginPersistent(pluginName, key, def);
+ return m_Proxied->persistent(pluginName, key, def);
}
void OrganizerProxy::setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
{
- m_Proxied->m_Settings.setPluginPersistent(pluginName, key, value, sync);
+ m_Proxied->setPersistent(pluginName, key, value, sync);
}
QString OrganizerProxy::pluginDataPath() const
{
- QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
- return pluginPath + "/data";
+ return m_Proxied->pluginDataPath();
}
HANDLE OrganizerProxy::startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile)
@@ -106,26 +95,31 @@ HANDLE OrganizerProxy::startApplication(const QString &executable, const QString bool OrganizerProxy::waitForApplication(HANDLE handle, LPDWORD exitCode) const
{
- return m_Proxied->waitForProcessOrJob(handle, exitCode);
+ return m_Proxied->waitForApplication(handle, exitCode);
}
bool OrganizerProxy::onAboutToRun(const std::function<bool (const QString &)> &func)
{
- auto conn = m_Proxied->m_AboutToRun.connect(func);
- return conn.connected();
+ return m_Proxied->onAboutToRun(func);
+}
+
+bool OrganizerProxy::onFinishedRun(const std::function<void (const QString &, unsigned int)> &func)
+{
+ return m_Proxied->onFinishedRun(func);
}
bool OrganizerProxy::onModInstalled(const std::function<void (const QString &)> &func)
{
- auto conn = m_Proxied->m_ModInstalled.connect(func);
- return conn.connected();
+ return m_Proxied->onModInstalled(func);
}
+
void OrganizerProxy::refreshModList(bool saveChanges)
{
m_Proxied->refreshModList(saveChanges);
}
+
IModInterface *OrganizerProxy::installMod(const QString &fileName)
{
return m_Proxied->installMod(fileName);
@@ -133,62 +127,22 @@ IModInterface *OrganizerProxy::installMod(const QString &fileName) QString OrganizerProxy::resolvePath(const QString &fileName) const
{
- if (m_Proxied->m_DirectoryStructure == NULL) {
- return QString();
- }
- const FileEntry::Ptr file = m_Proxied->m_DirectoryStructure->searchFile(ToWString(fileName), NULL);
- if (file.get() != NULL) {
- return ToQString(file->getFullPath());
- } else {
- return QString();
- }
+ return m_Proxied->resolvePath(fileName);
}
QStringList OrganizerProxy::listDirectories(const QString &directoryName) const
{
- QStringList result;
- DirectoryEntry *dir = m_Proxied->m_DirectoryStructure->findSubDirectoryRecursive(ToWString(directoryName));
- if (dir != NULL) {
- std::vector<DirectoryEntry*>::iterator current, end;
- dir->getSubDirectories(current, end);
- for (; current != end; ++current) {
- result.append(ToQString((*current)->getName()));
- }
- }
- return result;
+ return m_Proxied->listDirectories(directoryName);
}
QStringList OrganizerProxy::findFiles(const QString &path, const std::function<bool(const QString&)> &filter) const
{
- QStringList result;
- DirectoryEntry *dir = m_Proxied->m_DirectoryStructure->findSubDirectoryRecursive(ToWString(path));
- if (dir != NULL) {
- std::vector<FileEntry::Ptr> files = dir->getFiles();
- foreach (FileEntry::Ptr file, files) {
- if (filter(ToQString(file->getFullPath()))) {
- result.append(ToQString(file->getFullPath()));
- }
- }
- } else {
- qWarning("directory %s not found", qPrintable(path));
- }
- return result;
+ return m_Proxied->findFiles(path, filter);
}
QStringList OrganizerProxy::getFileOrigins(const QString &fileName) const
{
- QStringList result;
- const FileEntry::Ptr file = m_Proxied->m_DirectoryStructure->searchFile(ToWString(QFileInfo(fileName).fileName()), NULL);
-
- if (file.get() != NULL) {
- result.append(ToQString(m_Proxied->m_DirectoryStructure->getOriginByID(file->getOrigin()).getName()));
- foreach (int i, file->getAlternatives()) {
- result.append(ToQString(m_Proxied->m_DirectoryStructure->getOriginByID(i).getName()));
- }
- } else {
- qDebug("%s not found", qPrintable(fileName));
- }
- return result;
+ return m_Proxied->getFileOrigins(fileName);
}
QList<MOBase::IOrganizer::FileInfo> OrganizerProxy::findFileInfos(const QString &path, const std::function<bool (const MOBase::IOrganizer::FileInfo &)> &filter) const
@@ -198,15 +152,15 @@ QList<MOBase::IOrganizer::FileInfo> OrganizerProxy::findFileInfos(const QString MOBase::IDownloadManager *OrganizerProxy::downloadManager()
{
- return &m_Proxied->m_DownloadManager;
+ return m_Proxied->downloadManager();
}
MOBase::IPluginList *OrganizerProxy::pluginList()
{
- return &m_Proxied->m_PluginList;
+ return m_Proxied->pluginList();
}
MOBase::IModList *OrganizerProxy::modList()
{
- return &m_Proxied->m_ModList;
+ return m_Proxied->modList();
}
diff --git a/src/organizerproxy.h b/src/organizerproxy.h index affa2d55..625e86aa 100644 --- a/src/organizerproxy.h +++ b/src/organizerproxy.h @@ -7,8 +7,10 @@ class OrganizerProxy : public MOBase::IOrganizer
{
+
public:
- OrganizerProxy(MainWindow *window, const QString &pluginName);
+
+ OrganizerProxy(OrganizerCore *organizer, const QString &pluginName);
virtual MOBase::IGameInfo &gameInfo() const;
virtual MOBase::IModRepositoryBridge *createNexusBridge() const;
@@ -40,10 +42,14 @@ public: virtual void refreshModList(bool saveChanges);
virtual bool onAboutToRun(const std::function<bool(const QString&)> &func);
- virtual bool onModInstalled(const std::function<void (const QString &)> &func);
+ virtual bool onFinishedRun(const std::function<void (const QString&, unsigned int)> &func);
+ virtual bool onModInstalled(const std::function<void (const QString&)> &func);
+
private:
- MainWindow *m_Proxied;
+
+ OrganizerCore *m_Proxied;
+
const QString &m_PluginName;
};
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp new file mode 100644 index 00000000..bd96828e --- /dev/null +++ b/src/plugincontainer.cpp @@ -0,0 +1,329 @@ +#include "plugincontainer.h"
+#include "organizerproxy.h"
+#include "report.h"
+#include <gameinfo.h>
+#include <ipluginproxy.h>
+#include <idownloadmanager.h>
+#include <appconfig.h>
+#include <gameinfo.h>
+#include <QAction>
+#include <QToolButton>
+#include <QCoreApplication>
+#include <QMessageBox>
+#include <QDirIterator>
+#include <boost/fusion/sequence/intrinsic/at_key.hpp>
+#include <boost/fusion/include/at_key.hpp>
+#include <boost/fusion/algorithm/iteration/for_each.hpp>
+#include <boost/fusion/include/for_each.hpp>
+
+using namespace MOBase;
+using namespace MOShared;
+
+namespace bf = boost::fusion;
+
+
+PluginContainer::PluginContainer(OrganizerCore *organizer)
+ : m_Organizer(organizer)
+{
+}
+
+
+void PluginContainer::setUserInterface(IUserInterface *userInterface, QWidget *widget)
+{
+ for (IPluginProxy *proxy : bf::at_key<IPluginProxy>(m_Plugins)) {
+ proxy->setParentWidget(widget);
+ }
+ m_UserInterface = userInterface;
+}
+
+
+QStringList PluginContainer::pluginFileNames() const
+{
+ QStringList result;
+ for (QPluginLoader *loader : m_PluginLoaders) {
+ result.append(loader->fileName());
+ }
+ return result;
+}
+
+
+bool PluginContainer::verifyPlugin(IPlugin *plugin)
+{
+ if (plugin == NULL) {
+ return false;
+ } else if (!plugin->init(new OrganizerProxy(m_Organizer, plugin->name()))) {
+ qWarning("plugin failed to initialize");
+ return false;
+ }
+ return true;
+}
+
+
+void PluginContainer::registerGame(IPluginGame *game)
+{
+ m_SupportedGames.insert({ game->gameName(), game });
+}
+
+
+bool PluginContainer::registerPlugin(QObject *plugin, const QString &fileName)
+{
+ { // generic treatment for all plugins
+ IPlugin *pluginObj = qobject_cast<IPlugin*>(plugin);
+ if (pluginObj == NULL) {
+ qDebug("not an IPlugin");
+ return false;
+ }
+ plugin->setProperty("filename", fileName);
+ m_Organizer->settings().registerPlugin(pluginObj);
+ }
+
+ { // diagnosis plugins
+ IPluginDiagnose *diagnose = qobject_cast<IPluginDiagnose*>(plugin);
+ if (diagnose != NULL) {
+ bf::at_key<IPluginDiagnose>(m_Plugins).push_back(diagnose);
+ m_DiagnosisConnections.push_back(
+ diagnose->onInvalidated([&] () { emit diagnosisUpdate(); })
+ );
+ }
+ }
+ { // mod page plugin
+ IPluginModPage *modPage = qobject_cast<IPluginModPage*>(plugin);
+ if (verifyPlugin(modPage)) {
+ bf::at_key<IPluginModPage>(m_Plugins).push_back(modPage);
+ registerModPage(modPage);
+ return true;
+ }
+ }
+ { // game plugin
+ IPluginGame *game = qobject_cast<IPluginGame*>(plugin);
+ if (verifyPlugin(game)) {
+ bf::at_key<IPluginGame>(m_Plugins).push_back(game);
+ registerGame(game);
+ return true;
+ }
+ }
+ { // tool plugins
+ IPluginTool *tool = qobject_cast<IPluginTool*>(plugin);
+ if (verifyPlugin(tool)) {
+ bf::at_key<IPluginTool>(m_Plugins).push_back(tool);
+ registerPluginTool(tool);
+ return true;
+ }
+ }
+ { // installer plugins
+ IPluginInstaller *installer = qobject_cast<IPluginInstaller*>(plugin);
+ if (verifyPlugin(installer)) {
+ bf::at_key<IPluginInstaller>(m_Plugins).push_back(installer);
+ m_Organizer->installationManager()->registerInstaller(installer);
+ return true;
+ }
+ }
+ { // preview plugins
+ IPluginPreview *preview = qobject_cast<IPluginPreview*>(plugin);
+ if (verifyPlugin(preview)) {
+ bf::at_key<IPluginPreview>(m_Plugins).push_back(preview);
+ m_PreviewGenerator.registerPlugin(preview);
+ return true;
+ }
+ }
+ { // proxy plugins
+ IPluginProxy *proxy = qobject_cast<IPluginProxy*>(plugin);
+ if (verifyPlugin(proxy)) {
+ bf::at_key<IPluginProxy>(m_Plugins).push_back(proxy);
+ QStringList pluginNames = proxy->pluginList(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::pluginPath()));
+ foreach (const QString &pluginName, pluginNames) {
+ try {
+ QObject *proxiedPlugin = proxy->instantiate(pluginName);
+ if (proxiedPlugin != NULL) {
+ if (registerPlugin(proxiedPlugin, pluginName)) {
+ qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
+ } else {
+ qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
+ }
+ }
+ } catch (const std::exception &e) {
+ reportError(QObject::tr("failed to init plugin %1: %2").arg(pluginName).arg(e.what()));
+ }
+ }
+ return true;
+ }
+ }
+
+ { // dummy plugins
+ // only initialize these, no processing otherwise
+ IPlugin *dummy = qobject_cast<IPlugin*>(plugin);
+ if (verifyPlugin(dummy)) {
+ bf::at_key<IPlugin>(m_Plugins).push_back(dummy);
+ return true;
+ }
+ }
+
+ qDebug("no matching plugin interface");
+
+ return false;
+}
+
+struct clearPlugins
+{
+ template<typename T>
+ void operator()(T& t) const
+ {
+ t.second.clear();
+ }
+};
+
+void PluginContainer::unloadPlugins()
+{
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->disconnectPlugins();
+ }
+
+ // disconnect all slots before unloading plugins so plugins don't have to take care of that
+ m_Organizer->disconnectPlugins();
+
+ bf::for_each(m_Plugins, clearPlugins());
+
+ foreach (const boost::signals2::connection &connection, m_DiagnosisConnections) {
+ connection.disconnect();
+ }
+ m_DiagnosisConnections.clear();
+
+ while (!m_PluginLoaders.empty()) {
+ QPluginLoader *loader = m_PluginLoaders.back();
+ m_PluginLoaders.pop_back();
+ if (!loader->unload()) {
+ qDebug("failed to unload %s: %s", qPrintable(loader->fileName()), qPrintable(loader->errorString()));
+ }
+ delete loader;
+ }
+}
+
+IPluginGame *PluginContainer::managedGame(const QString &name) const
+{
+ auto iter = m_SupportedGames.find(name);
+ if (iter != m_SupportedGames.end()) {
+ return iter->second;
+ } else {
+ return nullptr;
+ }
+}
+
+const PreviewGenerator &PluginContainer::previewGenerator() const
+{
+ return m_PreviewGenerator;
+}
+
+void PluginContainer::loadPlugins()
+{
+ unloadPlugins();
+
+ foreach (QObject *plugin, QPluginLoader::staticInstances()) {
+ registerPlugin(plugin, "");
+ }
+
+ QFile loadCheck(qApp->property("dataPath").toString() + "/plugin_loadcheck.tmp");
+ if (loadCheck.exists() && loadCheck.open(QIODevice::ReadOnly)) {
+ // oh, there was a failed plugin load last time. Find out which plugin was loaded last
+ QString fileName;
+ while (!loadCheck.atEnd()) {
+ fileName = QString::fromUtf8(loadCheck.readLine().constData()).trimmed();
+ }
+ if (QMessageBox::question(nullptr, QObject::tr("Plugin error"),
+ QObject::tr("It appears the plugin \"%1\" failed to load last startup and caused MO to crash. Do you want to disable it?\n"
+ "(Please note: If this is the first time you see this message for this plugin you may want to give it another try. "
+ "The plugin may be able to recover from the problem)").arg(fileName),
+ QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
+ m_Organizer->settings().addBlacklistPlugin(fileName);
+ }
+ loadCheck.close();
+ }
+
+ loadCheck.open(QIODevice::WriteOnly);
+
+ QString pluginPath = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getOrganizerDirectory())) + "/" + ToQString(AppConfig::pluginPath());
+ qDebug("looking for plugins in %s", QDir::toNativeSeparators(pluginPath).toUtf8().constData());
+ QDirIterator iter(pluginPath, QDir::Files | QDir::NoDotAndDotDot);
+
+ while (iter.hasNext()) {
+ iter.next();
+ if (m_Organizer->settings().pluginBlacklisted(iter.fileName())) {
+ qDebug("plugin \"%s\" blacklisted", qPrintable(iter.fileName()));
+ continue;
+ }
+ loadCheck.write(iter.fileName().toUtf8());
+ loadCheck.write("\n");
+ loadCheck.flush();
+ QString pluginName = iter.filePath();
+ if (QLibrary::isLibrary(pluginName)) {
+ QPluginLoader *pluginLoader = new QPluginLoader(pluginName, this);
+ if (pluginLoader->instance() == NULL) {
+ m_FailedPlugins.push_back(pluginName);
+ qCritical("failed to load plugin %s: %s",
+ qPrintable(pluginName), qPrintable(pluginLoader->errorString()));
+ } else {
+ if (registerPlugin(pluginLoader->instance(), pluginName)) {
+ qDebug("loaded plugin \"%s\"", qPrintable(pluginName));
+ m_PluginLoaders.push_back(pluginLoader);
+ } else {
+ m_FailedPlugins.push_back(pluginName);
+ qWarning("plugin \"%s\" failed to load", qPrintable(pluginName));
+ }
+ }
+ }
+ }
+
+ // remove the load check file on success
+ loadCheck.remove();
+
+ bf::at_key<IPluginDiagnose>(m_Plugins).push_back(this);
+
+ m_Organizer->connectPlugins(this);
+}
+
+
+std::vector<unsigned int> PluginContainer::activeProblems() const
+{
+ std::vector<unsigned int> problems;
+ if (m_FailedPlugins.size()) {
+ problems.push_back(PROBLEM_PLUGINSNOTLOADED);
+ }
+ return problems;
+}
+
+QString PluginContainer::shortDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_PLUGINSNOTLOADED: {
+ return tr("Some plugins could not be loaded");
+ } break;
+ default: {
+ return tr("Description missing");
+ } break;
+ }
+}
+
+QString PluginContainer::fullDescription(unsigned int key) const
+{
+ switch (key) {
+ case PROBLEM_PLUGINSNOTLOADED: {
+ QString result = tr("The following plugins could not be loaded. The reason may be missing dependencies (i.e. python) or an outdated version:") + "<ul>";
+ for (const QString &plugin : m_FailedPlugins) {
+ result += "<li>" + plugin + "</li>";
+ }
+ result += "<ul>";
+ return result;
+ } break;
+ default: {
+ return tr("Description missing");
+ } break;
+ }
+}
+
+bool PluginContainer::hasGuidedFix(unsigned int) const
+{
+ return false;
+}
+
+void PluginContainer::startGuidedFix(unsigned int) const
+{
+}
diff --git a/src/plugincontainer.h b/src/plugincontainer.h new file mode 100644 index 00000000..213b4154 --- /dev/null +++ b/src/plugincontainer.h @@ -0,0 +1,102 @@ +#ifndef PLUGINCONTAINER_H
+#define PLUGINCONTAINER_H
+
+
+#include "organizercore.h"
+#include "previewgenerator.h"
+#include <iplugindiagnose.h>
+#include <ipluginmodpage.h>
+#include <iplugingame.h>
+#include <iplugintool.h>
+#include <ipluginproxy.h>
+#include <iplugininstaller.h>
+#include <QtPlugin>
+#include <QPluginLoader>
+#include <QFile>
+#ifndef Q_MOC_RUN
+#include <boost/fusion/container.hpp>
+#endif // Q_MOC_RUN
+#include <vector>
+
+
+class PluginContainer : public QObject, public MOBase::IPluginDiagnose
+{
+
+ Q_OBJECT
+ Q_INTERFACES(MOBase::IPluginDiagnose)
+
+public:
+
+ PluginContainer(OrganizerCore *organizer);
+
+ void setUserInterface(IUserInterface *userInterface, QWidget *widget);
+
+ void loadPlugins();
+ void unloadPlugins();
+
+ MOBase::IPluginGame *managedGame(const QString &name) const;
+
+ template <typename T>
+ std::vector<T*> plugins() const {
+ return boost::fusion::at_key<T>(m_Plugins);
+ }
+
+ const PreviewGenerator &previewGenerator() const;
+
+ QStringList pluginFileNames() const;
+
+public: // IPluginDiagnose interface
+
+ virtual std::vector<unsigned int> activeProblems() const;
+ virtual QString shortDescription(unsigned int key) const;
+ virtual QString fullDescription(unsigned int key) const;
+ virtual bool hasGuidedFix(unsigned int key) const;
+ virtual void startGuidedFix(unsigned int key) const;
+
+signals:
+
+ void diagnosisUpdate();
+
+private:
+
+ bool verifyPlugin(MOBase::IPlugin *plugin);
+ void registerPluginTool(MOBase::IPluginTool *tool);
+ void registerModPage(MOBase::IPluginModPage *modPage);
+ void registerGame(MOBase::IPluginGame *game);
+ bool registerPlugin(QObject *pluginObj, const QString &fileName);
+ bool unregisterPlugin(QObject *pluginObj, const QString &fileName);
+
+private:
+
+ typedef boost::fusion::map<
+ boost::fusion::pair<MOBase::IPlugin, std::vector<MOBase::IPlugin*>>,
+ boost::fusion::pair<MOBase::IPluginDiagnose, std::vector<MOBase::IPluginDiagnose*>>,
+ boost::fusion::pair<MOBase::IPluginGame, std::vector<MOBase::IPluginGame*>>,
+ boost::fusion::pair<MOBase::IPluginInstaller, std::vector<MOBase::IPluginInstaller*>>,
+ boost::fusion::pair<MOBase::IPluginModPage, std::vector<MOBase::IPluginModPage*>>,
+ boost::fusion::pair<MOBase::IPluginPreview, std::vector<MOBase::IPluginPreview*>>,
+ boost::fusion::pair<MOBase::IPluginTool, std::vector<MOBase::IPluginTool*>>,
+ boost::fusion::pair<MOBase::IPluginProxy, std::vector<MOBase::IPluginProxy*>>
+ > PluginMap;
+
+ static const unsigned int PROBLEM_PLUGINSNOTLOADED = 1;
+
+private:
+
+ OrganizerCore *m_Organizer;
+
+ IUserInterface *m_UserInterface;
+
+ PluginMap m_Plugins;
+
+ std::map<QString, MOBase::IPluginGame*> m_SupportedGames;
+ std::vector<boost::signals2::connection> m_DiagnosisConnections;
+ QStringList m_FailedPlugins;
+ std::vector<QPluginLoader*> m_PluginLoaders;
+
+ PreviewGenerator m_PreviewGenerator;
+
+ QFile m_PluginsCheck;
+};
+
+#endif // PLUGINCONTAINER_H
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index f37f9e3a..b2d02cd2 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -23,6 +23,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "settings.h"
#include "safewritefile.h"
#include "scopeguard.h"
+#include "modinfo.h"
#include <utility.h>
#include <gameinfo.h>
#include <espfile.h>
@@ -33,6 +34,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QMimeData>
#include <QCoreApplication>
#include <QDir>
+#include <QFile>
#include <QTextCodec>
#include <QFileInfo>
#include <QListWidgetItem>
@@ -95,6 +97,8 @@ PluginList::PluginList(QObject *parent) PluginList::~PluginList()
{
+ m_Refreshed.disconnect_all_slots();
+ m_PluginMoved.disconnect_all_slots();
}
@@ -155,7 +159,14 @@ void PluginList::refresh(const QString &profileName, const DirectoryEntry &baseD QString iniPath = QFileInfo(filename).baseName() + ".ini";
bool hasIni = baseDirectory.findFile(ToWString(iniPath)).get() != NULL;
- m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), ToQString(origin.getName()), ToQString(current->getFullPath()), hasIni));
+ QString originName = ToQString(origin.getName());
+ unsigned int modIndex = ModInfo::getIndex(originName);
+ if (modIndex != UINT_MAX) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex);
+ originName = modInfo->name();
+ }
+
+ m_ESPs.push_back(ESPInfo(filename, forceEnabled, current->getFileTime(), originName, ToQString(current->getFullPath()), hasIni));
} catch (const std::exception &e) {
reportError(tr("failed to update esp info for file %1 (source id: %2), error: %3").arg(filename).arg(current->getOrigin(archive)).arg(e.what()));
}
@@ -287,6 +298,8 @@ void PluginList::addInformation(const QString &name, const QString &message) if (iter != m_ESPsByName.end()) {
m_AdditionalInfo[name.toLower()].m_Messages.append(message);
+ } else {
+ qWarning("failed to associate message for \"%s\"", qPrintable(name));
}
}
@@ -484,7 +497,7 @@ void PluginList::saveTo(const QString &pluginFileName if (deleterFile.commitIfDifferent(m_LastSaveHash[deleterFileName])) {
qDebug("%s saved", qPrintable(QDir::toNativeSeparators(deleterFileName)));
}
- } else {
+ } else if (QFile::exists(deleterFileName)) {
shellDelete(QStringList() << deleterFileName);
}
@@ -664,11 +677,25 @@ bool PluginList::isMaster(const QString &name) const }
}
+QStringList PluginList::masters(const QString &name) const
+{
+ auto iter = m_ESPsByName.find(name.toLower());
+ if (iter == m_ESPsByName.end()) {
+ return QStringList();
+ } else {
+ QStringList result;
+ foreach (const QString &master, m_ESPs[iter->second].m_Masters) {
+ result.append(master);
+ }
+ return result;
+ }
+}
+
QString PluginList::origin(const QString &name) const
{
auto iter = m_ESPsByName.find(name.toLower());
if (iter == m_ESPsByName.end()) {
- return false;
+ return QString();
} else {
return m_ESPs[iter->second].m_OriginName;
}
@@ -819,7 +846,7 @@ QVariant PluginList::data(const QModelIndex &modelIndex, int role) const std::set_difference(m_ESPs[index].m_Masters.begin(), m_ESPs[index].m_Masters.end(),
m_ESPs[index].m_MasterUnset.begin(), m_ESPs[index].m_MasterUnset.end(),
std::inserter(enabledMasters, enabledMasters.end()));
- if (enabledMasters.size() > 0) {
+ if (!enabledMasters.empty()) {
text += "<br><b>" + tr("Enabled Masters") + "</b>: " + SetJoin(enabledMasters, ", ");
}
if (m_ESPs[index].m_HasIni) {
@@ -1085,34 +1112,34 @@ bool PluginList::eventFilter(QObject *obj, QEvent *event) ((keyEvent->key() == Qt::Key_Up) || (keyEvent->key() == Qt::Key_Down))) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
const QSortFilterProxyModel *proxyModel = qobject_cast<const QSortFilterProxyModel*>(selectionModel->model());
- int diff = -1;
- if (((keyEvent->key() == Qt::Key_Up) && (proxyModel->sortOrder() == Qt::DescendingOrder)) ||
- ((keyEvent->key() == Qt::Key_Down) && (proxyModel->sortOrder() == Qt::AscendingOrder))) {
- diff = 1;
- }
- QModelIndexList rows = selectionModel->selectedRows();
- // remove elements that aren't supposed to be movable
- QMutableListIterator<QModelIndex> iter(rows);
- while (iter.hasNext()) {
- if ((iter.next().flags() & Qt::ItemIsDragEnabled) == 0) {
- iter.remove();
+ if (proxyModel != NULL) {
+ int diff = -1;
+ if (((keyEvent->key() == Qt::Key_Up) && (proxyModel->sortOrder() == Qt::DescendingOrder)) ||
+ ((keyEvent->key() == Qt::Key_Down) && (proxyModel->sortOrder() == Qt::AscendingOrder))) {
+ diff = 1;
}
- }
- if (keyEvent->key() == Qt::Key_Down) {
- for (int i = 0; i < rows.size() / 2; ++i) {
- rows.swap(i, rows.size() - i - 1);
+ QModelIndexList rows = selectionModel->selectedRows();
+ // remove elements that aren't supposed to be movable
+ QMutableListIterator<QModelIndex> iter(rows);
+ while (iter.hasNext()) {
+ if ((iter.next().flags() & Qt::ItemIsDragEnabled) == 0) {
+ iter.remove();
+ }
}
- }
- foreach (QModelIndex idx, rows) {
- if (proxyModel != NULL) {
- idx = proxyModel->mapToSource(idx);
+ if (keyEvent->key() == Qt::Key_Down) {
+ for (int i = 0; i < rows.size() / 2; ++i) {
+ rows.swap(i, rows.size() - i - 1);
+ }
}
- int newPriority = m_ESPs[idx.row()].m_Priority + diff;
- if ((newPriority >= 0) && (newPriority < rowCount())) {
- setPluginPriority(idx.row(), newPriority);
+ foreach (QModelIndex idx, rows) {
+ idx = proxyModel->mapToSource(idx);
+ int newPriority = m_ESPs[idx.row()].m_Priority + diff;
+ if ((newPriority >= 0) && (newPriority < rowCount())) {
+ setPluginPriority(idx.row(), newPriority);
+ }
}
+ refreshLoadOrder();
}
- refreshLoadOrder();
return true;
} else if (keyEvent->key() == Qt::Key_Space) {
QItemSelectionModel *selectionModel = itemView->selectionModel();
diff --git a/src/pluginlist.h b/src/pluginlist.h index 67d1b640..729c6f8b 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -26,15 +26,16 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QListWidget>
#include <QTimer>
#include <QTemporaryFile>
+#ifndef Q_MOC_RUN
#include <boost/signals2.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
+#endif
#include <vector>
#include <map>
#include "pdll.h"
#include <BOSS-API.h>
-
template <class C>
class ChangeBracket {
public:
@@ -212,12 +213,18 @@ public: void refreshLoadOrder();
+ void disconnectSlots() {
+ m_PluginMoved.disconnect_all_slots();
+ m_Refreshed.disconnect_all_slots();
+ }
+
public:
virtual PluginState state(const QString &name) const;
virtual int priority(const QString &name) const;
virtual int loadOrder(const QString &name) const;
virtual bool isMaster(const QString &name) const;
+ virtual QStringList masters(const QString &name) const;
virtual QString origin(const QString &name) const;
virtual bool onRefreshed(const std::function<void()> &callback);
virtual bool onPluginMoved(const std::function<void (const QString &, int, int)> &func);
@@ -333,13 +340,11 @@ private: mutable QTimer m_SaveTimer;
SignalRefreshed m_Refreshed;
+ SignalPluginMoved m_PluginMoved;
QTemporaryFile m_TempFile;
- SignalPluginMoved m_PluginMoved;
};
-
-
#endif // PLUGINLIST_H
diff --git a/src/profile.cpp b/src/profile.cpp index ca47d327..6e9d8f0f 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -1,783 +1,790 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "profile.h"
-#include "report.h"
-#include "gameinfo.h"
-#include "windows_error.h"
-#include "dummybsa.h"
-#include "modinfo.h"
-#include "safewritefile.h"
-#include <utility.h>
-#include <util.h>
-#include <error_report.h>
-#include <appconfig.h>
-#include <QMessageBox>
-#include <QApplication>
-#include <QSettings>
-#include <QTemporaryFile>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <shlobj.h>
-#include <stdexcept>
-
-using namespace MOBase;
-using namespace MOShared;
-
-Profile::Profile()
- : m_SaveTimer(NULL)
-{
- initTimer();
-}
-
-Profile::Profile(const QString &name, bool useDefaultSettings)
- : m_SaveTimer(NULL)
-{
- initTimer();
- QString profilesDir = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir()));
- QDir profileBase(profilesDir);
-
- QString fixedName = name;
- if (!fixDirectoryName(fixedName)) {
- throw MyException(tr("invalid profile name %1").arg(name));
- }
-
- if (!profileBase.exists() || !profileBase.mkdir(fixedName)) {
- throw MyException(tr("failed to create %1").arg(fixedName).toUtf8().constData());
- }
- QString fullPath = profilesDir + "/" + fixedName;
- m_Directory = QDir(fullPath);
- QFile modList(m_Directory.filePath("modlist.txt"));
- if (!modList.open(QIODevice::ReadWrite)) {
- profileBase.rmdir(fixedName);
- throw std::runtime_error(QObject::tr("failed to create %1").arg(m_Directory.filePath("modlist.txt")).toUtf8().constData());
- }
- modList.close();
-
- try {
- GameInfo::instance().createProfile(ToWString(fullPath), useDefaultSettings);
- } catch (...) {
- // clean up in case of an error
- shellDelete(QStringList(profileBase.absoluteFilePath(fixedName)));
- throw;
- }
- refreshModStatus();
-}
-
-
-Profile::Profile(const QDir& directory)
- : m_Directory(directory), m_SaveTimer(NULL)
-{
- initTimer();
- if (!QFile::exists(m_Directory.filePath("modlist.txt"))) {
- qWarning("missing modlist.txt in %s", qPrintable(directory.path()));
- }
-
- GameInfo::instance().repairProfile(ToWString(m_Directory.absolutePath()));
-
- if (!QFile::exists(getIniFileName())) {
- reportError(QObject::tr("\"%1\" is missing or inaccessible").arg(getIniFileName()));
- }
- refreshModStatus();
-}
-
-
-Profile::Profile(const Profile& reference)
- : m_Directory(reference.m_Directory), m_SaveTimer(NULL)
-{
- initTimer();
- refreshModStatus();
-}
-
-
-Profile::~Profile()
-{
- writeModlistNow();
-}
-
-
-void Profile::initTimer()
-{
- m_SaveTimer = new QTimer(this);
- m_SaveTimer->setSingleShot(true);
- connect(m_SaveTimer, SIGNAL(timeout()), this, SLOT(writeModlistNow()));
-}
-
-
-bool Profile::exists() const
-{
- return m_Directory.exists();
-}
-
-
-void Profile::writeModlist() const
-{
- if (!m_SaveTimer->isActive()) {
- m_SaveTimer->start(2000);
- }
-}
-
-
-void Profile::cancelWriteModlist() const
-{
- m_SaveTimer->stop();
-}
-
-
-void Profile::writeModlistNow(bool onlyOnTimer) const
-{
- if (onlyOnTimer && !m_SaveTimer->isActive()) return;
-
- m_SaveTimer->stop();
- if (!m_Directory.exists()) return;
-
- try {
- QString fileName = getModlistFileName();
- SafeWriteFile file(fileName);
-
- file->write(QString("# This file was automatically generated by Mod Organizer.\r\n").toUtf8());
- if (m_ModStatus.empty()) {
- return;
- }
-
- for (int i = m_ModStatus.size() - 1; i >= 0; --i) {
- // the priority order was inverted on load so it has to be inverted again
- unsigned int index = m_ModIndexByPriority[i];
- if (index != UINT_MAX) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
- std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
- if ((modInfo->getFixedPriority() == INT_MIN)) {
- if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) {
- file->write("*");
- } else if (m_ModStatus[index].m_Enabled) {
- file->write("+");
- } else {
- file->write("-");
- }
- file->write(modInfo->name().toUtf8());
- file->write("\r\n");
- }
- }
- }
-
- if (file.commitIfDifferent(m_LastModlistHash)) {
- qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData());
- }
- } catch (const std::exception &e) {
- reportError(tr("failed to write mod list: %1").arg(e.what()));
- return;
- }
-}
-
-
-void Profile::createTweakedIniFile()
-{
- QString tweakedIni = m_Directory.absoluteFilePath("initweaks.ini");
-
- if (QFile::exists(tweakedIni) && !shellDeleteQuiet(tweakedIni)) {
- reportError(tr("failed to update tweaked ini file, wrong settings may be used: %1").arg(windowsErrorString(::GetLastError())));
- return;
- }
-
- for (unsigned int i = 0; i < m_ModStatus.size(); ++i) {
- if (m_ModStatus[i].m_Enabled) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- mergeTweaks(modInfo, tweakedIni);
- }
- }
-
- mergeTweak(getProfileTweaks(), tweakedIni);
-
- bool error = false;
- if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", ToWString(tweakedIni).c_str())) {
- error = true;
- }
-
- if (localSavesEnabled()) {
- if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"1", ToWString(tweakedIni).c_str())) {
- error = true;
- }
-
- if (!::WritePrivateProfileStringW(L"General", L"SLocalSavePath",
- AppConfig::localSavePlaceholder(),
- ToWString(tweakedIni).c_str())) {
- error = true;
- }
- }
-
- if (error) {
- reportError(tr("failed to create tweaked ini: %1").arg(getCurrentErrorStringA().c_str()));
- }
- qDebug("%s saved", qPrintable(QDir::toNativeSeparators(tweakedIni)));
-}
-
-
-void Profile::refreshModStatus()
-{
- QFile file(getModlistFileName());
- if (!file.exists()) {
- throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName()));
- }
-
- bool modStatusModified = false;
- m_ModStatus.clear();
- m_ModStatus.resize(ModInfo::getNumMods());
-
- std::set<QString> namesRead;
-
- // load mods from file and update enabled state and priority for them
- file.open(QIODevice::ReadOnly);
- int index = 0;
- while (!file.atEnd()) {
- QByteArray line = file.readLine();
- bool enabled = true;
- QString modName;
- if (line.length() == 0) {
- // empty line
- continue;
- } else if (line.at(0) == '#') {
- // comment line
- continue;
- } else if (line.at(0) == '-') {
- enabled = false;
- modName = QString::fromUtf8(line.mid(1).trimmed().constData());
- } else if ((line.at(0) == '+')
- || (line.at(0) == '*')) {
- modName = QString::fromUtf8(line.mid(1).trimmed().constData());
- } else {
- modName = QString::fromUtf8(line.trimmed().constData());
- }
- if (modName.size() > 0) {
- QString lookupName = modName + (line.at(0) == '*' ? ModInfoForeign::INT_IDENTIFIER : "");
- if (namesRead.find(lookupName) != namesRead.end()) {
- continue;
- } else {
- namesRead.insert(lookupName);
- }
- unsigned int modIndex = ModInfo::getIndex(lookupName);
- if (modIndex != UINT_MAX) {
- ModInfo::Ptr info = ModInfo::getByIndex(modIndex);
- if ((modIndex < m_ModStatus.size())
- && (info->getFixedPriority() == INT_MIN)) {
- m_ModStatus[modIndex].m_Enabled = enabled || info->alwaysEnabled();
- if (m_ModStatus[modIndex].m_Priority == -1) {
- if (static_cast<size_t>(index) >= m_ModStatus.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
- m_ModStatus[modIndex].m_Priority = index++;
- }
- } else {
- qDebug("mod \"%s\" (profile \"%s\") not found",
- modName.toUtf8().constData(), m_Directory.path().toUtf8().constData());
- // need to rewrite the modlist to fix this
- modStatusModified = true;
- }
- }
- } else {
- // line was empty after trimming
- }
- }
-
- int numKnownMods = index;
-
- int topInsert = 0;
-
- // invert priority order to match that of the pluginlist. Also
- // give priorities to mods not referenced in the profile
- for (size_t i = 0; i < m_ModStatus.size(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- if (modInfo->getFixedPriority() == INT_MAX) {
- continue;
- }
-
- if (m_ModStatus[i].m_Priority != -1) {
- m_ModStatus[i].m_Priority = numKnownMods - m_ModStatus[i].m_Priority - 1;
- } else {
- if (static_cast<size_t>(index) >= m_ModStatus.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
- if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) {
- m_ModStatus[i].m_Priority = --topInsert;
- } else {
- m_ModStatus[i].m_Priority = index++;
- }
- // also, mark the mod-list as changed
- modStatusModified = true;
- }
- }
- // to support insertion of new mods at the top we may now have mods with negative priority. shift them all up
- // to align priority with 0
- if (topInsert < 0) {
- int offset = topInsert * -1;
- for (size_t i = 0; i < m_ModStatus.size(); ++i) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
- if (modInfo->getFixedPriority() == INT_MAX) {
- continue;
- }
-
- m_ModStatus[i].m_Priority += offset;
- }
- }
-
- file.close();
- updateIndices();
- if (modStatusModified) {
- writeModlist();
- }
-}
-
-
-void Profile::dumpModStatus() const
-{
- for (unsigned int i = 0; i < m_ModStatus.size(); ++i) {
- ModInfo::Ptr info = ModInfo::getByIndex(i);
- qWarning("%d: %s - %d (%s)", i, info->name().toUtf8().constData(), m_ModStatus[i].m_Priority,
- m_ModStatus[i].m_Enabled ? "enabled" : "disabled");
- }
-}
-
-
-void Profile::updateIndices()
-{
- m_NumRegularMods = 0;
- m_ModIndexByPriority.clear();
- m_ModIndexByPriority.resize(m_ModStatus.size(), UINT_MAX);
- for (unsigned int i = 0; i < m_ModStatus.size(); ++i) {
- int priority = m_ModStatus[i].m_Priority;
- if (priority < 0) {
- // don't assign this to mapping at all, it's probably the overwrite mod
- continue;
- } else if (priority >= static_cast<int>(m_ModIndexByPriority.size())) {
- qCritical("invalid priority %d for mod", priority);
- continue;
- } else {
- ++m_NumRegularMods;
- m_ModIndexByPriority.at(priority) = i;
- }
- }
-}
-
-
-std::vector<std::tuple<QString, QString, int> > Profile::getActiveMods()
-{
- std::vector<std::tuple<QString, QString, int> > result;
- for (std::vector<unsigned int>::const_iterator iter = m_ModIndexByPriority.begin();
- iter != m_ModIndexByPriority.end(); ++iter) {
- if ((*iter != UINT_MAX) && m_ModStatus[*iter].m_Enabled) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(*iter);
- result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[*iter].m_Priority));
- }
- }
-
- unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool {
- std::vector<ModInfo::EFlag> flags = mod->getFlags();
- return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); });
-
- if (overwriteIndex != UINT_MAX) {
- ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(overwriteIndex);
- result.push_back(std::make_tuple(overwriteInfo->name(), overwriteInfo->absolutePath(), UINT_MAX));
- } else {
- reportError(tr("Overwrite directory couldn't be parsed"));
- }
- return result;
-}
-
-
-unsigned int Profile::modIndexByPriority(unsigned int priority) const
-{
- if (priority >= m_ModStatus.size()) {
- throw MyException(tr("invalid priority %1").arg(priority));
- }
-
- return m_ModIndexByPriority[priority];
-}
-
-
-void Profile::setModEnabled(unsigned int index, bool enabled)
-{
- if (index >= m_ModStatus.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
-
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
- // we could quit in the following case, this shouldn't be a change anyway,
- // but at least this allows the situation to be fixed in case of an error
- if (modInfo->alwaysEnabled()) {
- enabled = true;
- }
-
- if (enabled != m_ModStatus[index].m_Enabled) {
- m_ModStatus[index].m_Enabled = enabled;
- emit modStatusChanged(index);
- }
-}
-
-
-bool Profile::modEnabled(unsigned int index) const
-{
- if (index >= m_ModStatus.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
-
- return m_ModStatus[index].m_Enabled;
-}
-
-
-int Profile::getModPriority(unsigned int index) const
-{
- if (index >= m_ModStatus.size()) {
- throw MyException(tr("invalid index %1").arg(index));
- }
-
- return m_ModStatus[index].m_Priority;
-}
-
-
-void Profile::setModPriority(unsigned int index, int &newPriority)
-{
- if (m_ModStatus.at(index).m_Overwrite) {
- // can't change priority of the overwrite
- return;
- }
-
- int newPriorityTemp = (std::max)(0, (std::min<int>)(m_ModStatus.size() - 1, newPriority));
-
- // don't try to place below overwrite
- while ((m_ModIndexByPriority.at(newPriorityTemp) >= m_ModStatus.size()) ||
- m_ModStatus.at(m_ModIndexByPriority.at(newPriorityTemp)).m_Overwrite) {
- --newPriorityTemp;
- }
-
- int oldPriority = m_ModStatus.at(index).m_Priority;
- if (newPriorityTemp > oldPriority) {
- // priority is higher than the old, so the gap we left is in lower priorities
- for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) {
- --m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority;
- }
- } else {
- for (int i = newPriorityTemp; i < oldPriority; ++i) {
- ++m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority;
- }
- ++newPriority;
- }
-
- m_ModStatus.at(index).m_Priority = newPriorityTemp;
-
- updateIndices();
- writeModlist();
-}
-
-
-Profile Profile::createFrom(const QString &name, const Profile &reference)
-{
- QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name);
- reference.copyFilesTo(profileDirectory);
- return Profile(QDir(profileDirectory));
-}
-
-
-Profile *Profile::createPtrFrom(const QString &name, const Profile &reference)
-{
- QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name);
- reference.copyFilesTo(profileDirectory);
- return new Profile(QDir(profileDirectory));
-}
-
-
-void Profile::copyFilesTo(QString &target) const
-{
- copyDir(m_Directory.absolutePath(), target, false);
-}
-
-
-std::vector<std::wstring> Profile::splitDZString(const wchar_t *buffer) const
-{
- std::vector<std::wstring> result;
- const wchar_t *pos = buffer;
- size_t length = wcslen(pos);
- while (length != 0U) {
- result.push_back(pos);
- pos += length + 1;
- length = wcslen(pos);
- }
- return result;
-}
-
-
-void Profile::mergeTweak(const QString &tweakName, const QString &tweakedIni) const
-{
- static const int bufferSize = 32768;
-
- std::wstring tweakNameW = ToWString(tweakName);
- std::wstring tweakedIniW = ToWString(tweakedIni);
- QScopedArrayPointer<wchar_t> buffer(new wchar_t[bufferSize]);
-
- // retrieve a list of sections
- DWORD size = ::GetPrivateProfileSectionNamesW(
- buffer.data(), bufferSize, tweakNameW.c_str());
-
- if (size == bufferSize - 2) {
- // unfortunately there is no good way to find the required size
- // of the buffer
- throw MyException(QString("Buffer too small. Please report this as a bug. "
- "For now you might want to split up %1").arg(tweakName));
- }
-
- std::vector<std::wstring> sections = splitDZString(buffer.data());
-
- // now iterate over all sections and retrieve a list of keys in each
- for (std::vector<std::wstring>::iterator iter = sections.begin();
- iter != sections.end(); ++iter) {
- // retrieve the names of all keys
- size = ::GetPrivateProfileStringW(iter->c_str(), NULL, NULL, buffer.data(),
- bufferSize, tweakNameW.c_str());
- if (size == bufferSize - 2) {
- throw MyException(QString("Buffer too small. Please report this as a bug. "
- "For now you might want to split up %1").arg(tweakName));
- }
-
- std::vector<std::wstring> keys = splitDZString(buffer.data());
-
- for (std::vector<std::wstring>::iterator keyIter = keys.begin();
- keyIter != keys.end(); ++keyIter) {
- //TODO this treats everything as strings but how could I differentiate the type?
- ::GetPrivateProfileStringW(iter->c_str(), keyIter->c_str(),
- NULL, buffer.data(), bufferSize, ToWString(tweakName).c_str());
- ::WritePrivateProfileStringW(iter->c_str(), keyIter->c_str(),
- buffer.data(), tweakedIniW.c_str());
- }
- }
-}
-
-void Profile::mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const
-{
- std::vector<QString> iniTweaks = modInfo->getIniTweaks();
- for (std::vector<QString>::iterator iter = iniTweaks.begin();
- iter != iniTweaks.end(); ++iter) {
- mergeTweak(*iter, tweakedIni);
- }
-}
-
-
-bool Profile::invalidationActive(bool *supported) const
-{
- if (GameInfo::instance().requiresBSAInvalidation()) {
- *supported = true;
- wchar_t buffer[1024];
- std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName()));
- // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value
- // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured
- errno = 0;
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- L"", buffer, 1024, iniFileName.c_str()) == 0) {
- if (errno != 0x02) {
- if (supported != NULL) {
- *supported = false;
- }
- return false;
- } else {
- QString errorMessage = tr("failed to parse ini file (%1)").arg(ToQString(iniFileName));
- throw windows_error(errorMessage.toUtf8().constData());
- }
- }
- QStringList archives = ToQString(buffer).split(',');
-
- for (int i = 0; i < archives.count(); ++i) {
- QString bsaName = archives.at(i).trimmed();
- if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) {
- return true;
- }
- }
- } else {
- *supported = false;
- }
- return false;
-}
-
-
-void Profile::deactivateInvalidation() const
-{
- if (GameInfo::instance().requiresBSAInvalidation()) {
- wchar_t buffer[1024];
- std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName()));
- errno = 0;
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- L"", buffer, 1024, iniFileName.c_str()) == 0) {
- if (errno == 0x02) {
- QString errorMessage = tr("failed to parse ini file (%1): %2").arg(QDir::toNativeSeparators(getIniFileName())).arg(::GetLastError());
- throw windows_error(errorMessage.toUtf8().constData());
- } else {
- return;
- }
- }
- QStringList archives = ToQString(buffer).split(", ");
-
- for (int i = 0; i < archives.count();) {
- QString bsaName = archives.at(i).trimmed();
- if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) {
- archives.removeAt(i);
- } else {
- ++i;
- }
- }
-
- // just to be safe...
- ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL);
-
- if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) ||
- !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFileName.c_str()) ||
- !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFileName.c_str())) {
- QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName));
- throw windows_error(errorMessage.toUtf8().constData());
- }
- }
-}
-
-
-void Profile::activateInvalidation(const QString& dataDirectory) const
-{
- if (GameInfo::instance().requiresBSAInvalidation()) {
- wchar_t buffer[1024];
- std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName()));
- errno = 0;
- if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- L"", buffer, 1024, iniFileName.c_str()) == 0) {
- if (errno == 0x02) {
- throw windows_error("failed to parse ini file");
- } else {
- // ignore. shouldn't have gotten here anyway
- return;
- }
- }
- QStringList archives = ToQString(buffer).split(", ");
-
- QString invalidationBSA = ToQString(GameInfo::instance().getInvalidationBSA());
-
- if (!archives.contains(invalidationBSA)) {
- archives.insert(0, invalidationBSA);
- }
-
- // just to be safe...
- ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL);
-
- if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(),
- ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) ||
- !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFileName.c_str()) ||
- !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFileName.c_str())) {
- QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName));
- throw windows_error(errorMessage.toUtf8().constData());
- }
-
- QString bsaFile = dataDirectory + "/" + invalidationBSA;
- if (!QFile::exists(bsaFile)) {
- DummyBSA bsa;
- bsa.write(bsaFile);
- }
- }
-}
-
-
-bool Profile::localSavesEnabled() const
-{
- return m_Directory.exists("saves");
-}
-
-
-bool Profile::enableLocalSaves(bool enable)
-{
- if (enable) {
- if (m_Directory.exists("_saves")) {
- m_Directory.rename("_saves", "saves");
- } else {
- m_Directory.mkdir("saves");
- }
- } else {
- QMessageBox::StandardButton res = QMessageBox::question(QApplication::activeModalWidget(), tr("Delete savegames?"),
- tr("Do you want to delete local savegames? (If you select \"No\", the save games "
- "will show up again if you re-enable local savegames)"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel);
- if (res == QMessageBox::Yes) {
- shellDelete(QStringList(m_Directory.absoluteFilePath("saves")));
- } else if (res == QMessageBox::No) {
- m_Directory.rename("saves", "_saves");
- } else {
- return false;
- }
- }
-
- // default: assume success
- return true;
-}
-
-
-QString Profile::getModlistFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("modlist.txt"));
-}
-
-QString Profile::getPluginsFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("plugins.txt"));
-}
-
-QString Profile::getLoadOrderFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("loadorder.txt"));
-}
-
-QString Profile::getLockedOrderFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("lockedorder.txt"));
-}
-
-QString Profile::getArchivesFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("archives.txt"));
-}
-
-QString Profile::getDeleterFileName() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath("hide_plugins.txt"));
-}
-
-QString Profile::getIniFileName() const
-{
- std::wstring primaryIniFile = *(GameInfo::instance().getIniFileNames().begin());
- return m_Directory.absoluteFilePath(ToQString(primaryIniFile));
-}
-
-QString Profile::getProfileTweaks() const
-{
- return QDir::cleanPath(m_Directory.absoluteFilePath(ToQString(AppConfig::profileTweakIni())));
-}
-
-QString Profile::getPath() const
-{
- return QDir::cleanPath(m_Directory.absolutePath());
-}
-
-void Profile::rename(const QString &newName)
-{
- QDir profileDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())));
- profileDir.rename(getName(), newName);
- m_Directory = profileDir.absoluteFilePath(newName);
-}
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "profile.h" +#include "report.h" +#include "gameinfo.h" +#include "windows_error.h" +#include "dummybsa.h" +#include "modinfo.h" +#include "safewritefile.h" +#include <utility.h> +#include <util.h> +#include <error_report.h> +#include <appconfig.h> +#include <QMessageBox> +#include <QApplication> +#include <QSettings> +#include <QTemporaryFile> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <shlobj.h> +#include <stdexcept> + +using namespace MOBase; +using namespace MOShared; + +Profile::Profile() + : m_SaveTimer(NULL) +{ + initTimer(); +} + +void Profile::touchFile(QString fileName) +{ + QFile modList(m_Directory.filePath(fileName)); + if (!modList.open(QIODevice::ReadWrite)) { + throw std::runtime_error(QObject::tr("failed to create %1").arg(m_Directory.filePath(fileName)).toUtf8().constData()); + } +} + +Profile::Profile(const QString &name, bool useDefaultSettings) + : m_SaveTimer(NULL) +{ + initTimer(); + QString profilesDir = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())); + QDir profileBase(profilesDir); + + QString fixedName = name; + if (!fixDirectoryName(fixedName)) { + throw MyException(tr("invalid profile name %1").arg(name)); + } + + if (!profileBase.exists() || !profileBase.mkdir(fixedName)) { + throw MyException(tr("failed to create %1").arg(fixedName).toUtf8().constData()); + } + QString fullPath = profilesDir + "/" + fixedName; + m_Directory = QDir(fullPath); + + try { + // create files. Needs to happen after m_Directory was set! + touchFile("modlist.txt"); + touchFile("archives.txt"); + + GameInfo::instance().createProfile(ToWString(fullPath), useDefaultSettings); + } catch (...) { + // clean up in case of an error + shellDelete(QStringList(profileBase.absoluteFilePath(fixedName))); + throw; + } + refreshModStatus(); +} + + +Profile::Profile(const QDir& directory) + : m_Directory(directory), m_SaveTimer(NULL) +{ + initTimer(); + if (!QFile::exists(m_Directory.filePath("modlist.txt"))) { + qWarning("missing modlist.txt in %s", qPrintable(directory.path())); + } + + GameInfo::instance().repairProfile(ToWString(m_Directory.absolutePath())); + + if (!QFile::exists(getIniFileName())) { + reportError(QObject::tr("\"%1\" is missing or inaccessible").arg(getIniFileName())); + } + refreshModStatus(); +} + + +Profile::Profile(const Profile& reference) + : m_Directory(reference.m_Directory), m_SaveTimer(NULL) +{ + initTimer(); + refreshModStatus(); +} + + +Profile::~Profile() +{ + writeModlistNow(); +} + + +void Profile::initTimer() +{ + m_SaveTimer = new QTimer(this); + m_SaveTimer->setSingleShot(true); + connect(m_SaveTimer, SIGNAL(timeout()), this, SLOT(writeModlistNow())); +} + + +bool Profile::exists() const +{ + return m_Directory.exists(); +} + + +void Profile::writeModlist() const +{ + if (!m_SaveTimer->isActive()) { + m_SaveTimer->start(2000); + } +} + + +void Profile::cancelWriteModlist() const +{ + m_SaveTimer->stop(); +} + + +void Profile::writeModlistNow(bool onlyOnTimer) const +{ + if (onlyOnTimer && !m_SaveTimer->isActive()) return; + + m_SaveTimer->stop(); + if (!m_Directory.exists()) return; + + try { + QString fileName = getModlistFileName(); + SafeWriteFile file(fileName); + + file->write(QString("# This file was automatically generated by Mod Organizer.\r\n").toUtf8()); + if (m_ModStatus.empty()) { + return; + } + + for (int i = m_ModStatus.size() - 1; i >= 0; --i) { + // the priority order was inverted on load so it has to be inverted again + unsigned int index = m_ModIndexByPriority[i]; + if (index != UINT_MAX) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(index); + std::vector<ModInfo::EFlag> flags = modInfo->getFlags(); + if ((modInfo->getFixedPriority() == INT_MIN)) { + if (std::find(flags.begin(), flags.end(), ModInfo::FLAG_FOREIGN) != flags.end()) { + file->write("*"); + } else if (m_ModStatus[index].m_Enabled) { + file->write("+"); + } else { + file->write("-"); + } + file->write(modInfo->name().toUtf8()); + file->write("\r\n"); + } + } + } + + if (file.commitIfDifferent(m_LastModlistHash)) { + qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); + } + } catch (const std::exception &e) { + reportError(tr("failed to write mod list: %1").arg(e.what())); + return; + } +} + + +void Profile::createTweakedIniFile() +{ + QString tweakedIni = m_Directory.absoluteFilePath("initweaks.ini"); + + if (QFile::exists(tweakedIni) && !shellDeleteQuiet(tweakedIni)) { + reportError(tr("failed to update tweaked ini file, wrong settings may be used: %1").arg(windowsErrorString(::GetLastError()))); + return; + } + + for (unsigned int i = 0; i < m_ModStatus.size(); ++i) { + if (m_ModStatus[i].m_Enabled) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(i); + mergeTweaks(modInfo, tweakedIni); + } + } + + mergeTweak(getProfileTweaks(), tweakedIni); + + bool error = false; + if (!::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", ToWString(tweakedIni).c_str())) { + error = true; + } + + if (localSavesEnabled()) { + if (!::WritePrivateProfileStringW(L"General", L"bUseMyGamesDirectory", L"0", ToWString(tweakedIni).c_str())) { + error = true; + } + + if (!::WritePrivateProfileStringW(L"General", L"SLocalSavePath", + AppConfig::localSavePlaceholder(), + ToWString(tweakedIni).c_str())) { + error = true; + } + } + + if (error) { + reportError(tr("failed to create tweaked ini: %1").arg(getCurrentErrorStringA().c_str())); + } + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(tweakedIni))); +} + + +void Profile::refreshModStatus() +{ + QFile file(getModlistFileName()); + if (!file.open(QIODevice::ReadOnly)) { + throw MyException(tr("\"%1\" is missing or inaccessible").arg(getModlistFileName())); + } + + bool modStatusModified = false; + m_ModStatus.clear(); + m_ModStatus.resize(ModInfo::getNumMods()); + + std::set<QString> namesRead; + + // load mods from file and update enabled state and priority for them + int index = 0; + while (!file.atEnd()) { + QByteArray line = file.readLine().trimmed(); + bool enabled = true; + QString modName; + if (line.length() == 0) { + // empty line + continue; + } else if (line.at(0) == '#') { + // comment line + continue; + } else if (line.at(0) == '-') { + enabled = false; + modName = QString::fromUtf8(line.mid(1).trimmed().constData()); + } else if ((line.at(0) == '+') + || (line.at(0) == '*')) { + modName = QString::fromUtf8(line.mid(1).trimmed().constData()); + } else { + modName = QString::fromUtf8(line.trimmed().constData()); + } + if (modName.size() > 0) { + QString lookupName = modName + (line.at(0) == '*' ? ModInfoForeign::INT_IDENTIFIER : ""); + if (namesRead.find(lookupName) != namesRead.end()) { + continue; + } else { + namesRead.insert(lookupName); + } + unsigned int modIndex = ModInfo::getIndex(lookupName); + if (modIndex != UINT_MAX) { + ModInfo::Ptr info = ModInfo::getByIndex(modIndex); + if ((modIndex < m_ModStatus.size()) + && (info->getFixedPriority() == INT_MIN)) { + m_ModStatus[modIndex].m_Enabled = enabled || info->alwaysEnabled(); + if (m_ModStatus[modIndex].m_Priority == -1) { + if (static_cast<size_t>(index) >= m_ModStatus.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + m_ModStatus[modIndex].m_Priority = index++; + } + } else { + qDebug("mod \"%s\" (profile \"%s\") not found", + modName.toUtf8().constData(), m_Directory.path().toUtf8().constData()); + // need to rewrite the modlist to fix this + modStatusModified = true; + } + } + } else { + // line was empty after trimming + } + } + + int numKnownMods = index; + + int topInsert = 0; + + // invert priority order to match that of the pluginlist. Also + // give priorities to mods not referenced in the profile + for (size_t i = 0; i < m_ModStatus.size(); ++i) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(i); + if (modInfo->getFixedPriority() == INT_MAX) { + continue; + } + + if (m_ModStatus[i].m_Priority != -1) { + m_ModStatus[i].m_Priority = numKnownMods - m_ModStatus[i].m_Priority - 1; + } else { + if (static_cast<size_t>(index) >= m_ModStatus.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + if (modInfo->hasFlag(ModInfo::FLAG_FOREIGN)) { + m_ModStatus[i].m_Priority = --topInsert; + } else { + m_ModStatus[i].m_Priority = index++; + } + // also, mark the mod-list as changed + modStatusModified = true; + } + } + // to support insertion of new mods at the top we may now have mods with negative priority. shift them all up + // to align priority with 0 + if (topInsert < 0) { + int offset = topInsert * -1; + for (size_t i = 0; i < m_ModStatus.size(); ++i) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(i); + if (modInfo->getFixedPriority() == INT_MAX) { + continue; + } + + m_ModStatus[i].m_Priority += offset; + } + } + + file.close(); + updateIndices(); + if (modStatusModified) { + writeModlist(); + } +} + + +void Profile::dumpModStatus() const +{ + for (unsigned int i = 0; i < m_ModStatus.size(); ++i) { + ModInfo::Ptr info = ModInfo::getByIndex(i); + qWarning("%d: %s - %d (%s)", i, info->name().toUtf8().constData(), m_ModStatus[i].m_Priority, + m_ModStatus[i].m_Enabled ? "enabled" : "disabled"); + } +} + + +void Profile::updateIndices() +{ + m_NumRegularMods = 0; + m_ModIndexByPriority.clear(); + m_ModIndexByPriority.resize(m_ModStatus.size(), UINT_MAX); + for (unsigned int i = 0; i < m_ModStatus.size(); ++i) { + int priority = m_ModStatus[i].m_Priority; + if (priority < 0) { + // don't assign this to mapping at all, it's probably the overwrite mod + continue; + } else if (priority >= static_cast<int>(m_ModIndexByPriority.size())) { + qCritical("invalid priority %d for mod", priority); + continue; + } else { + ++m_NumRegularMods; + m_ModIndexByPriority.at(priority) = i; + } + } +} + + +std::vector<std::tuple<QString, QString, int> > Profile::getActiveMods() +{ + std::vector<std::tuple<QString, QString, int> > result; + for (std::vector<unsigned int>::const_iterator iter = m_ModIndexByPriority.begin(); + iter != m_ModIndexByPriority.end(); ++iter) { + if ((*iter != UINT_MAX) && m_ModStatus[*iter].m_Enabled) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(*iter); + result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[*iter].m_Priority)); + } + } + + unsigned int overwriteIndex = ModInfo::findMod([](ModInfo::Ptr mod) -> bool { + std::vector<ModInfo::EFlag> flags = mod->getFlags(); + return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); }); + + if (overwriteIndex != UINT_MAX) { + ModInfo::Ptr overwriteInfo = ModInfo::getByIndex(overwriteIndex); + result.push_back(std::make_tuple(overwriteInfo->name(), overwriteInfo->absolutePath(), UINT_MAX)); + } else { + reportError(tr("Overwrite directory couldn't be parsed")); + } + return result; +} + + +unsigned int Profile::modIndexByPriority(unsigned int priority) const +{ + if (priority >= m_ModStatus.size()) { + throw MyException(tr("invalid priority %1").arg(priority)); + } + + return m_ModIndexByPriority[priority]; +} + + +void Profile::setModEnabled(unsigned int index, bool enabled) +{ + if (index >= m_ModStatus.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + + ModInfo::Ptr modInfo = ModInfo::getByIndex(index); + // we could quit in the following case, this shouldn't be a change anyway, + // but at least this allows the situation to be fixed in case of an error + if (modInfo->alwaysEnabled()) { + enabled = true; + } + + if (enabled != m_ModStatus[index].m_Enabled) { + m_ModStatus[index].m_Enabled = enabled; + emit modStatusChanged(index); + } +} + + +bool Profile::modEnabled(unsigned int index) const +{ + if (index >= m_ModStatus.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + + return m_ModStatus[index].m_Enabled; +} + + +int Profile::getModPriority(unsigned int index) const +{ + if (index >= m_ModStatus.size()) { + throw MyException(tr("invalid index %1").arg(index)); + } + + return m_ModStatus[index].m_Priority; +} + + +void Profile::setModPriority(unsigned int index, int &newPriority) +{ + if (m_ModStatus.at(index).m_Overwrite) { + // can't change priority of the overwrite + return; + } + + int newPriorityTemp = (std::max)(0, (std::min<int>)(m_ModStatus.size() - 1, newPriority)); + + // don't try to place below overwrite + while ((m_ModIndexByPriority.at(newPriorityTemp) >= m_ModStatus.size()) || + m_ModStatus.at(m_ModIndexByPriority.at(newPriorityTemp)).m_Overwrite) { + --newPriorityTemp; + } + + int oldPriority = m_ModStatus.at(index).m_Priority; + if (newPriorityTemp > oldPriority) { + // priority is higher than the old, so the gap we left is in lower priorities + for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) { + --m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority; + } + } else { + for (int i = newPriorityTemp; i < oldPriority; ++i) { + ++m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority; + } + ++newPriority; + } + + m_ModStatus.at(index).m_Priority = newPriorityTemp; + + updateIndices(); + writeModlist(); +} + + +Profile Profile::createFrom(const QString &name, const Profile &reference) +{ + QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name); + reference.copyFilesTo(profileDirectory); + return Profile(QDir(profileDirectory)); +} + + +Profile *Profile::createPtrFrom(const QString &name, const Profile &reference) +{ + QString profileDirectory = QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir())).append("/").append(name); + reference.copyFilesTo(profileDirectory); + return new Profile(QDir(profileDirectory)); +} + + +void Profile::copyFilesTo(QString &target) const +{ + copyDir(m_Directory.absolutePath(), target, false); +} + + +std::vector<std::wstring> Profile::splitDZString(const wchar_t *buffer) const +{ + std::vector<std::wstring> result; + const wchar_t *pos = buffer; + size_t length = wcslen(pos); + while (length != 0U) { + result.push_back(pos); + pos += length + 1; + length = wcslen(pos); + } + return result; +} + + +void Profile::mergeTweak(const QString &tweakName, const QString &tweakedIni) const +{ + static const int bufferSize = 32768; + + std::wstring tweakNameW = ToWString(tweakName); + std::wstring tweakedIniW = ToWString(tweakedIni); + QScopedArrayPointer<wchar_t> buffer(new wchar_t[bufferSize]); + + // retrieve a list of sections + DWORD size = ::GetPrivateProfileSectionNamesW( + buffer.data(), bufferSize, tweakNameW.c_str()); + + if (size == bufferSize - 2) { + // unfortunately there is no good way to find the required size + // of the buffer + throw MyException(QString("Buffer too small. Please report this as a bug. " + "For now you might want to split up %1").arg(tweakName)); + } + + std::vector<std::wstring> sections = splitDZString(buffer.data()); + + // now iterate over all sections and retrieve a list of keys in each + for (std::vector<std::wstring>::iterator iter = sections.begin(); + iter != sections.end(); ++iter) { + // retrieve the names of all keys + size = ::GetPrivateProfileStringW(iter->c_str(), NULL, NULL, buffer.data(), + bufferSize, tweakNameW.c_str()); + if (size == bufferSize - 2) { + throw MyException(QString("Buffer too small. Please report this as a bug. " + "For now you might want to split up %1").arg(tweakName)); + } + + std::vector<std::wstring> keys = splitDZString(buffer.data()); + + for (std::vector<std::wstring>::iterator keyIter = keys.begin(); + keyIter != keys.end(); ++keyIter) { + //TODO this treats everything as strings but how could I differentiate the type? + ::GetPrivateProfileStringW(iter->c_str(), keyIter->c_str(), + NULL, buffer.data(), bufferSize, ToWString(tweakName).c_str()); + ::WritePrivateProfileStringW(iter->c_str(), keyIter->c_str(), + buffer.data(), tweakedIniW.c_str()); + } + } +} + +void Profile::mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const +{ + std::vector<QString> iniTweaks = modInfo->getIniTweaks(); + for (std::vector<QString>::iterator iter = iniTweaks.begin(); + iter != iniTweaks.end(); ++iter) { + mergeTweak(*iter, tweakedIni); + } +} + + +bool Profile::invalidationActive(bool *supported) const +{ + if (GameInfo::instance().requiresBSAInvalidation()) { + if (supported != NULL) { + *supported = true; + } + wchar_t buffer[1024]; + std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); + // epic ms fail: GetPrivateProfileString uses errno (for whatever reason) to signal a fail since the return value + // has a different meaning (number of bytes copied). HOWEVER, it will not set errno to 0 if NO error occured + errno = 0; + if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + L"", buffer, 1024, iniFileName.c_str()) == 0) { + if (errno != 0x02) { + if (supported != NULL) { + *supported = false; + } + return false; + } else { + QString errorMessage = tr("failed to parse ini file (%1)").arg(ToQString(iniFileName)); + throw windows_error(errorMessage.toUtf8().constData()); + } + } + QStringList archives = ToQString(buffer).split(','); + + for (int i = 0; i < archives.count(); ++i) { + QString bsaName = archives.at(i).trimmed(); + if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) { + return true; + } + } + } else { + *supported = false; + } + return false; +} + + +void Profile::deactivateInvalidation() const +{ + if (GameInfo::instance().requiresBSAInvalidation()) { + wchar_t buffer[1024]; + std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); + errno = 0; + if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + L"", buffer, 1024, iniFileName.c_str()) == 0) { + if (errno == 0x02) { + QString errorMessage = tr("failed to parse ini file (%1): %2").arg(QDir::toNativeSeparators(getIniFileName())).arg(::GetLastError()); + throw windows_error(errorMessage.toUtf8().constData()); + } else { + return; + } + } + QStringList archives = ToQString(buffer).split(", "); + + for (int i = 0; i < archives.count();) { + QString bsaName = archives.at(i).trimmed(); + if (GameInfo::instance().isInvalidationBSA(ToWString(bsaName))) { + archives.removeAt(i); + } else { + ++i; + } + } + + // just to be safe... + ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); + + if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"0", iniFileName.c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"ArchiveInvalidation.txt", iniFileName.c_str())) { + QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); + throw windows_error(errorMessage.toUtf8().constData()); + } + } +} + + +void Profile::activateInvalidation(const QString& dataDirectory) const +{ + if (GameInfo::instance().requiresBSAInvalidation()) { + wchar_t buffer[1024]; + std::wstring iniFileName = ToWString(QDir::toNativeSeparators(getIniFileName())); + errno = 0; + if (::GetPrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + L"", buffer, 1024, iniFileName.c_str()) == 0) { + if (errno == 0x02) { + throw windows_error("failed to parse ini file"); + } else { + // ignore. shouldn't have gotten here anyway + return; + } + } + QStringList archives = ToQString(buffer).split(", "); + + QString invalidationBSA = ToQString(GameInfo::instance().getInvalidationBSA()); + + if (!archives.contains(invalidationBSA)) { + archives.insert(0, invalidationBSA); + } + + // just to be safe... + ::SetFileAttributesW(iniFileName.c_str(), FILE_ATTRIBUTE_NORMAL); + + if (!::WritePrivateProfileStringW(L"Archive", GameInfo::instance().archiveListKey().c_str(), + ToWString(archives.join(", ").toUtf8()).c_str(), iniFileName.c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"bInvalidateOlderFiles", L"1", iniFileName.c_str()) || + !::WritePrivateProfileStringW(L"Archive", L"SInvalidationFile", L"", iniFileName.c_str())) { + QString errorMessage = tr("failed to modify \"%1\"").arg(ToQString(iniFileName)); + throw windows_error(errorMessage.toUtf8().constData()); + } + + QString bsaFile = dataDirectory + "/" + invalidationBSA; + if (!QFile::exists(bsaFile)) { + DummyBSA bsa; + bsa.write(bsaFile); + } + } +} + + +bool Profile::localSavesEnabled() const +{ + return m_Directory.exists("saves"); +} + + +bool Profile::enableLocalSaves(bool enable) +{ + if (enable) { + if (m_Directory.exists("_saves")) { + m_Directory.rename("_saves", "saves"); + } else { + m_Directory.mkdir("saves"); + } + } else { + QMessageBox::StandardButton res = QMessageBox::question(QApplication::activeModalWidget(), tr("Delete savegames?"), + tr("Do you want to delete local savegames? (If you select \"No\", the save games " + "will show up again if you re-enable local savegames)"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Cancel); + if (res == QMessageBox::Yes) { + shellDelete(QStringList(m_Directory.absoluteFilePath("saves"))); + } else if (res == QMessageBox::No) { + m_Directory.rename("saves", "_saves"); + } else { + return false; + } + } + + // default: assume success + return true; +} + + +QString Profile::getModlistFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("modlist.txt")); +} + +QString Profile::getPluginsFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("plugins.txt")); +} + +QString Profile::getLoadOrderFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("loadorder.txt")); +} + +QString Profile::getLockedOrderFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("lockedorder.txt")); +} + +QString Profile::getArchivesFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("archives.txt")); +} + +QString Profile::getDeleterFileName() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath("hide_plugins.txt")); +} + +QString Profile::getIniFileName() const +{ + std::wstring primaryIniFile = *(GameInfo::instance().getIniFileNames().begin()); + return m_Directory.absoluteFilePath(ToQString(primaryIniFile)); +} + +QString Profile::getProfileTweaks() const +{ + return QDir::cleanPath(m_Directory.absoluteFilePath(ToQString(AppConfig::profileTweakIni()))); +} + +QString Profile::getPath() const +{ + return QDir::cleanPath(m_Directory.absolutePath()); +} + +void Profile::rename(const QString &newName) +{ + QDir profileDir(QDir::fromNativeSeparators(ToQString(GameInfo::instance().getProfilesDir()))); + profileDir.rename(getName(), newName); + m_Directory = profileDir.absoluteFilePath(newName); +} diff --git a/src/profile.h b/src/profile.h index fa34ab9e..aa27d6e8 100644 --- a/src/profile.h +++ b/src/profile.h @@ -1,330 +1,331 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PROFILE_H
-#define PROFILE_H
-
-
-#include "modinfo.h"
-
-#include <QString>
-#include <QDir>
-#include <QMetaType>
-#include <QSettings>
-#include <vector>
-#include <tuple>
-
-
-/**
- * @brief represents a profile
- **/
-class Profile : public QObject
-{
-
- Q_OBJECT
-
-public:
-
- typedef boost::shared_ptr<Profile> Ptr;
-
-public:
-
- /**
- * @brief default constructor
- * @todo This constructor initialised nothing, the resulting object is not usable
- **/
- Profile();
-
- /**
- * @brief constructor
- *
- * This constructor is used to create a new profile so it is to be assumed a profile
- * by this name does not yet exist
- * @param name name of the new profile
- * @param filter save game filter. Defaults to <no filter>.
- **/
- Profile(const QString &name, bool useDefaultSettings);
- /**
- * @brief constructor
- *
- * This constructor is used to open an existing profile though it will also try to repair
- * the profile if important files are missing (including the directory itself) so technically,
- * invoking this should always produce a working profile
- * @param directory directory to read the profile from
- **/
- Profile(const QDir &directory);
-
- Profile(const Profile &reference);
-
- ~Profile();
-
- /**
- * @return true if this profile (still) exists on disc
- */
- bool exists() const;
-
- /**
- * @param name of the new profile
- * @param reference profile to copy from
- **/
- static Profile createFrom(const QString &name, const Profile &reference);
-
- /**
- * @param name of the new profile
- * @param reference profile to copy from
- **/
- static Profile *createPtrFrom(const QString &name, const Profile &reference);
-
- /**
- * @brief write out the modlist.txt
- **/
- void writeModlist() const;
-
- /**
- * cancel any potential request to write modlist.txt. This is used to ensure no invalid modlist is
- * saved while it's being modified
- */
- void cancelWriteModlist() const;
-
- /**
- * @brief test if this profile uses archive invalidation
- *
- * @param supported if this is not null, the parameter will be set to false if invalidation is not supported in this profile
- * @return true if archive invalidation is active
- * @note currently, invalidation is not supported if the relevant entry in the ini file does not exist
- **/
- bool invalidationActive(bool *supported) const;
-
- /**
- * @brief deactivate archive invalidation if it was active
- **/
- void deactivateInvalidation() const;
-
- /**
- * @brief activate archive invalidation
- *
- * @param dataDirectory data directory of the game
- * @todo passing the data directory as a parameter is useless, the function should
- * be able to query it from GameInfo
- **/
- void activateInvalidation(const QString &dataDirectory) const;
-
- /**
- * @return true if this profile uses local save games
- */
- bool localSavesEnabled() const;
-
- /**
- * @brief enables or disables the use of local save games for this profile
- * disabling this does not delete exising local saves but they will not be visible
- * in the game
- * @param enable if true, local saves are enabled, otherewise they are disabled
- */
- bool enableLocalSaves(bool enable);
-
- /**
- * @return name of the profile (this is identical to its directory name)
- **/
- QString getName() const { return m_Directory.dirName(); }
-
- /**
- * @return the path of the plugins file in this profile
- * @todo is this required? can the functionality using this function be moved to the Profile-class?
- **/
- QString getPluginsFileName() const;
-
- /**
- * @return the path of the loadorder file in this profile
- **/
- QString getLoadOrderFileName() const;
-
- /**
- * @return the path of the file containing locked mod indices
- */
- QString getLockedOrderFileName() const;
-
- /**
- * @return the path of the modlist file in this profile
- */
- QString getModlistFileName() const;
-
- /**
- * @return path of the archives file in this profile
- */
- QString getArchivesFileName() const;
-
- /**
- * @return the path of the delete file in this profile
- * @note the deleter file lists plugins that should be hidden from the game and other tools
- **/
- QString getDeleterFileName() const;
-
- /**
- * @return the path of the ini file in this profile
- * @todo since the game can contain multiple ini files (i.e. skyrim.ini skyrimprefs.ini)
- * the concept of this function is somewhat broken
- **/
- QString getIniFileName() const;
-
- /**
- * @return the path of the tweak ini in this profile
- */
- QString getProfileTweaks() const;
-
- /**
- * @return path to this profile
- **/
- QString getPath() const;
-
- void rename(const QString &newName);
-
- /**
- * @brief create the ini file to be used by the game
- *
- * the tweaked ini file constructed by this file is a merger
- * of the game-ini of this profile with ini tweaks applied */
- void createTweakedIniFile();
-
- /**
- * @brief re-read the modlist.txt and update the mod status from it
- **/
- void refreshModStatus();
-
- /**
- * @brief retrieve a list of mods that are enabled in this profile
- *
- * @return list of active mods sorted by priority (ascending). "first" is the mod name, "second" is its path
- **/
- std::vector<std::tuple<QString, QString, int> > getActiveMods();
-
- /**
- * retrieve the number of mods for which this object has status information.
- * This is usually the same as ModInfo::getNumMods() except between
- * calls to ModInfo::updateFromDisc() and the Profile::refreshModStatus()
- *
- * @return number of mods for which the profile has status information
- **/
- unsigned int numMods() const { return m_ModStatus.size(); }
-
- /**
- * @return the number of mods that can be enabled and where the priority can be modified
- */
- unsigned int numRegularMods() const { return m_NumRegularMods; }
-
- /**
- * @brief retrieve the mod index based on the priority
- *
- * @param priority priority to look up
- * @return the index of the mod
- * @throw std::exception an exception is thrown if there is no mod with the specified priority
- **/
- unsigned int modIndexByPriority(unsigned int priority) const;
-
- /**
- * @brief enable or disable a mod
- *
- * @param index index of the mod to enable/disable
- * @param enabled true if the mod is to be enabled, false if it is to be disabled
- **/
- void setModEnabled(unsigned int index, bool enabled);
-
- /**
- * change the priority of a mod. Of course this also changes the priority of other mods.
- * The priority of the mods in the range ]old, new priority] are shifted so that no gaps
- * are possible.
- *
- * @param index index of the mod to change
- * @param newPriority the new priority value
- *
- * @todo what happens if the new priority is outside the range?
- **/
- void setModPriority(unsigned int index, int &newPriority);
-
- /**
- * @brief determine if a mod is enabled
- *
- * @param index index of the mod to look up
- * @return true if the mod is enabled, false otherwise
- **/
- bool modEnabled(unsigned int index) const;
-
- /**
- * @brief query the priority of a mod
- *
- * @param index index of the mod to look up
- * @return priority of the specified mod
- **/
- int getModPriority(unsigned int index) const;
-
- void dumpModStatus() const;
-
-signals:
-
- /**
- * @brief emitted whenever the status (enabled/disabled) of a mod changed
- *
- * @param index index of the mod that changed
- **/
- void modStatusChanged(unsigned int index);
-
-public slots:
-
- void writeModlistNow(bool onlyOnTimer = false) const;
-
-private:
-
- class ModStatus {
- friend class Profile;
- public:
- ModStatus() : m_Overwrite(false), m_Enabled(false), m_Priority(-1) {}
- private:
- bool m_Overwrite;
- bool m_Enabled;
- int m_Priority;
- };
-
-private:
- Profile& operator=(const Profile &reference); // not implemented
-
- void initTimer();
-
- void updateIndices();
-
- void copyFilesTo(QString &target) const;
-
- std::vector<std::wstring> splitDZString(const wchar_t *buffer) const;
- void mergeTweak(const QString &tweakName, const QString &tweakedIni) const;
- void mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const;
-
-private:
-
- QDir m_Directory;
-
- mutable QByteArray m_LastModlistHash;
- std::vector<ModStatus> m_ModStatus;
- std::vector<unsigned int> m_ModIndexByPriority;
- unsigned int m_NumRegularMods;
-
- QTimer *m_SaveTimer;
-};
-
-Q_DECLARE_METATYPE(Profile)
-
-
-#endif // PROFILE_H
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef PROFILE_H +#define PROFILE_H + + +#include "modinfo.h" + +#include <QString> +#include <QDir> +#include <QMetaType> +#include <QSettings> +#include <vector> +#include <tuple> + + +/** + * @brief represents a profile + **/ +class Profile : public QObject +{ + + Q_OBJECT + +public: + + typedef boost::shared_ptr<Profile> Ptr; + +public: + + /** + * @brief default constructor + * @todo This constructor initialised nothing, the resulting object is not usable + **/ + Profile(); + + /** + * @brief constructor + * + * This constructor is used to create a new profile so it is to be assumed a profile + * by this name does not yet exist + * @param name name of the new profile + * @param filter save game filter. Defaults to <no filter>. + **/ + Profile(const QString &name, bool useDefaultSettings); + /** + * @brief constructor + * + * This constructor is used to open an existing profile though it will also try to repair + * the profile if important files are missing (including the directory itself) so technically, + * invoking this should always produce a working profile + * @param directory directory to read the profile from + **/ + Profile(const QDir &directory); + + Profile(const Profile &reference); + + ~Profile(); + + /** + * @return true if this profile (still) exists on disc + */ + bool exists() const; + + /** + * @param name of the new profile + * @param reference profile to copy from + **/ + static Profile createFrom(const QString &name, const Profile &reference); + + /** + * @param name of the new profile + * @param reference profile to copy from + **/ + static Profile *createPtrFrom(const QString &name, const Profile &reference); + + /** + * @brief write out the modlist.txt + **/ + void writeModlist() const; + + /** + * cancel any potential request to write modlist.txt. This is used to ensure no invalid modlist is + * saved while it's being modified + */ + void cancelWriteModlist() const; + + /** + * @brief test if this profile uses archive invalidation + * + * @param supported if this is not null, the parameter will be set to false if invalidation is not supported in this profile + * @return true if archive invalidation is active + * @note currently, invalidation is not supported if the relevant entry in the ini file does not exist + **/ + bool invalidationActive(bool *supported) const; + + /** + * @brief deactivate archive invalidation if it was active + **/ + void deactivateInvalidation() const; + + /** + * @brief activate archive invalidation + * + * @param dataDirectory data directory of the game + * @todo passing the data directory as a parameter is useless, the function should + * be able to query it from GameInfo + **/ + void activateInvalidation(const QString &dataDirectory) const; + + /** + * @return true if this profile uses local save games + */ + bool localSavesEnabled() const; + + /** + * @brief enables or disables the use of local save games for this profile + * disabling this does not delete exising local saves but they will not be visible + * in the game + * @param enable if true, local saves are enabled, otherewise they are disabled + */ + bool enableLocalSaves(bool enable); + + /** + * @return name of the profile (this is identical to its directory name) + **/ + QString getName() const { return m_Directory.dirName(); } + + /** + * @return the path of the plugins file in this profile + * @todo is this required? can the functionality using this function be moved to the Profile-class? + **/ + QString getPluginsFileName() const; + + /** + * @return the path of the loadorder file in this profile + **/ + QString getLoadOrderFileName() const; + + /** + * @return the path of the file containing locked mod indices + */ + QString getLockedOrderFileName() const; + + /** + * @return the path of the modlist file in this profile + */ + QString getModlistFileName() const; + + /** + * @return path of the archives file in this profile + */ + QString getArchivesFileName() const; + + /** + * @return the path of the delete file in this profile + * @note the deleter file lists plugins that should be hidden from the game and other tools + **/ + QString getDeleterFileName() const; + + /** + * @return the path of the ini file in this profile + * @todo since the game can contain multiple ini files (i.e. skyrim.ini skyrimprefs.ini) + * the concept of this function is somewhat broken + **/ + QString getIniFileName() const; + + /** + * @return the path of the tweak ini in this profile + */ + QString getProfileTweaks() const; + + /** + * @return path to this profile + **/ + QString getPath() const; + + void rename(const QString &newName); + + /** + * @brief create the ini file to be used by the game + * + * the tweaked ini file constructed by this file is a merger + * of the game-ini of this profile with ini tweaks applied */ + void createTweakedIniFile(); + + /** + * @brief re-read the modlist.txt and update the mod status from it + **/ + void refreshModStatus(); + + /** + * @brief retrieve a list of mods that are enabled in this profile + * + * @return list of active mods sorted by priority (ascending). "first" is the mod name, "second" is its path + **/ + std::vector<std::tuple<QString, QString, int> > getActiveMods(); + + /** + * retrieve the number of mods for which this object has status information. + * This is usually the same as ModInfo::getNumMods() except between + * calls to ModInfo::updateFromDisc() and the Profile::refreshModStatus() + * + * @return number of mods for which the profile has status information + **/ + unsigned int numMods() const { return m_ModStatus.size(); } + + /** + * @return the number of mods that can be enabled and where the priority can be modified + */ + unsigned int numRegularMods() const { return m_NumRegularMods; } + + /** + * @brief retrieve the mod index based on the priority + * + * @param priority priority to look up + * @return the index of the mod + * @throw std::exception an exception is thrown if there is no mod with the specified priority + **/ + unsigned int modIndexByPriority(unsigned int priority) const; + + /** + * @brief enable or disable a mod + * + * @param index index of the mod to enable/disable + * @param enabled true if the mod is to be enabled, false if it is to be disabled + **/ + void setModEnabled(unsigned int index, bool enabled); + + /** + * change the priority of a mod. Of course this also changes the priority of other mods. + * The priority of the mods in the range ]old, new priority] are shifted so that no gaps + * are possible. + * + * @param index index of the mod to change + * @param newPriority the new priority value + * + * @todo what happens if the new priority is outside the range? + **/ + void setModPriority(unsigned int index, int &newPriority); + + /** + * @brief determine if a mod is enabled + * + * @param index index of the mod to look up + * @return true if the mod is enabled, false otherwise + **/ + bool modEnabled(unsigned int index) const; + + /** + * @brief query the priority of a mod + * + * @param index index of the mod to look up + * @return priority of the specified mod + **/ + int getModPriority(unsigned int index) const; + + void dumpModStatus() const; + +signals: + + /** + * @brief emitted whenever the status (enabled/disabled) of a mod changed + * + * @param index index of the mod that changed + **/ + void modStatusChanged(unsigned int index); + +public slots: + + void writeModlistNow(bool onlyOnTimer = false) const; + +private: + + class ModStatus { + friend class Profile; + public: + ModStatus() : m_Overwrite(false), m_Enabled(false), m_Priority(-1) {} + private: + bool m_Overwrite; + bool m_Enabled; + int m_Priority; + }; + +private: + Profile& operator=(const Profile &reference); // not implemented + + void initTimer(); + + void updateIndices(); + + void copyFilesTo(QString &target) const; + + std::vector<std::wstring> splitDZString(const wchar_t *buffer) const; + void mergeTweak(const QString &tweakName, const QString &tweakedIni) const; + void mergeTweaks(ModInfo::Ptr modInfo, const QString &tweakedIni) const; + void touchFile(QString fileName); + +private: + + QDir m_Directory; + + mutable QByteArray m_LastModlistHash; + std::vector<ModStatus> m_ModStatus; + std::vector<unsigned int> m_ModIndexByPriority; + unsigned int m_NumRegularMods; + + QTimer *m_SaveTimer; +}; + +Q_DECLARE_METATYPE(Profile) + + +#endif // PROFILE_H diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp index 6037422c..803b2cfa 100644 --- a/src/selfupdater.cpp +++ b/src/selfupdater.cpp @@ -55,9 +55,9 @@ template <typename T> T resolveFunction(QLibrary &lib, const char *name) }
-SelfUpdater::SelfUpdater(NexusInterface *nexusInterface, QWidget *parent)
- : QObject(parent), m_Parent(parent), m_Interface(nexusInterface), m_UpdateRequestID(-1),
- m_Reply(NULL), m_Progress(parent), m_Attempts(3)
+SelfUpdater::SelfUpdater(NexusInterface *nexusInterface)
+ : m_Parent(nullptr), m_Interface(nexusInterface), m_UpdateRequestID(-1),
+ m_Reply(NULL), m_Progress(nullptr), m_Attempts(3)
{
m_Progress.setMaximum(100);
@@ -88,6 +88,11 @@ SelfUpdater::~SelfUpdater() delete m_CurrentArchive;
}
+void SelfUpdater::setUserInterface(QWidget *widget)
+{
+ m_Progress.setParent(widget);
+ m_Parent = widget;
+}
void SelfUpdater::testForUpdate()
{
diff --git a/src/selfupdater.h b/src/selfupdater.h index 9648f15a..3490b58a 100644 --- a/src/selfupdater.h +++ b/src/selfupdater.h @@ -64,8 +64,11 @@ public: * @param parent parent widget
* @todo passing the nexus interface is unneccessary
**/
- SelfUpdater(NexusInterface *nexusInterface, QWidget *parent);
- ~SelfUpdater();
+ SelfUpdater(NexusInterface *nexusInterface);
+
+ virtual ~SelfUpdater();
+
+ void setUserInterface(QWidget *widget);
/**
* @brief start the update process
diff --git a/src/settings.cpp b/src/settings.cpp index 6bf13ee0..274e5979 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,742 +1,745 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "settings.h"
-
-#include "settingsdialog.h"
-#include "utility.h"
-#include "helper.h"
-#include <gameinfo.h>
-#include <appconfig.h>
-#include <utility.h>
-#include <json.h>
-
-#include <QCheckBox>
-#include <QLineEdit>
-#include <QDirIterator>
-#include <QRegExp>
-#include <QCoreApplication>
-#include <QMessageBox>
-#include <QDesktopServices>
-
-
-using namespace MOBase;
-using namespace MOShared;
-
-
-template <typename T>
-class QListWidgetItemEx : public QListWidgetItem {
-public:
- QListWidgetItemEx(const QString &text, int sortRole = Qt::DisplayRole, QListWidget *parent = 0, int type = Type)
- : QListWidgetItem(text, parent, type), m_SortRole(sortRole) {}
-
- virtual bool operator< ( const QListWidgetItem & other ) const {
- return this->data(m_SortRole).value<T>() < other.data(m_SortRole).value<T>();
- }
-private:
- int m_SortRole;
-};
-
-
-static const unsigned char Key2[20] = { 0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60, 0xa4, 0x5b, 0x01,
- 0xdb, 0xf8, 0x43, 0x3a, 0xb7, 0xb6, 0x98, 0xd4, 0x7d, 0xa2 };
-
-Settings *Settings::s_Instance = NULL;
-
-
-Settings::Settings()
- : m_Settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat)
-{
- if (s_Instance != NULL) {
- throw std::runtime_error("second instance of \"Settings\" created");
- } else {
- s_Instance = this;
- }
-}
-
-
-Settings::~Settings()
-{
- s_Instance = NULL;
-}
-
-
-Settings &Settings::instance()
-{
- if (s_Instance == NULL) {
- throw std::runtime_error("no instance of \"Settings\"");
- }
- return *s_Instance;
-}
-
-void Settings::clearPlugins()
-{
- m_Plugins.clear();
- m_PluginSettings.clear();
-
- m_PluginBlacklist.clear();
- int count = m_Settings.beginReadArray("pluginBlacklist");
- for (int i = 0; i < count; ++i) {
- m_Settings.setArrayIndex(i);
- m_PluginBlacklist.insert(m_Settings.value("name").toString());
- }
- m_Settings.endArray();
-}
-
-bool Settings::pluginBlacklisted(const QString &fileName) const
-{
- return m_PluginBlacklist.contains(fileName);
-}
-
-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" " + GameInfo::instance().getGameShortName() + L" \"" + executable + L"\"";
- HINSTANCE res = ::ShellExecuteW(NULL, L"open", nxmPath.c_str(), parameters.c_str(), NULL, SW_SHOWNORMAL);
- if ((int)res <= 32) {
- QMessageBox::critical(NULL, tr("Failed"),
- tr("Sorry, failed to start the helper application"));
- }
-}
-
-void Settings::registerPlugin(IPlugin *plugin)
-{
- m_Plugins.push_back(plugin);
- m_PluginSettings.insert(plugin->name(), QMap<QString, QVariant>());
- foreach (const PluginSetting &setting, plugin->settings()) {
- QVariant temp = m_Settings.value("Plugins/" + plugin->name() + "/" + setting.key, setting.defaultValue);
- if (!temp.convert(setting.defaultValue.type())) {
- qWarning("failed to interpret \"%s\" as correct type for \"%s\" in plugin \"%s\", using default",
- qPrintable(temp.toString()), qPrintable(setting.key), qPrintable(plugin->name()));
- temp = setting.defaultValue;
- }
- m_PluginSettings[plugin->name()][setting.key] = temp;
- }
-}
-
-
-QString Settings::obfuscate(const QString &password) const
-{
- QByteArray temp = password.toUtf8();
-
- QByteArray buffer;
- for (int i = 0; i < temp.length(); ++i) {
- buffer.append(temp.at(i) ^ Key2[i % 20]);
- }
- return buffer.toBase64();
-}
-
-
-QString Settings::deObfuscate(const QString &password) const
-{
- QByteArray temp(QByteArray::fromBase64(password.toUtf8()));
-
- QByteArray buffer;
- for (int i = 0; i < temp.length(); ++i) {
- buffer.append(temp.at(i) ^ Key2[i % 20]);
- }
- return QString::fromUtf8(buffer.constData());
-}
-
-
-bool Settings::hideUncheckedPlugins() const
-{
- return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool();
-}
-
-bool Settings::forceEnableCoreFiles() const
-{
- return m_Settings.value("Settings/force_enable_core_files", true).toBool();
-}
-
-bool Settings::automaticLoginEnabled() const
-{
- return m_Settings.value("Settings/nexus_login", false).toBool();
-}
-
-QString Settings::getSteamAppID() const
-{
- return m_Settings.value("Settings/app_id", ToQString(GameInfo::instance().getSteamAPPId(m_Settings.value("game_edition", 0).toInt()))).toString();
-}
-
-QString Settings::getDownloadDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString());
-}
-
-
-void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
-{
- m_Settings.beginGroup("Servers");
-
- foreach (const QString &serverKey, m_Settings.childKeys()) {
- QVariantMap data = m_Settings.value(serverKey).toMap();
- if (serverKey == serverName) {
- data["downloadCount"] = data["downloadCount"].toInt() + 1;
- data["downloadSpeed"] = data["downloadSpeed"].toDouble() + static_cast<double>(bytesPerSecond);
- m_Settings.setValue(serverKey, data);
- }
- }
-
- m_Settings.endGroup();
- m_Settings.sync();
-}
-
-std::map<QString, int> Settings::getPreferredServers()
-{
- std::map<QString, int> result;
- m_Settings.beginGroup("Servers");
-
- foreach (const QString &serverKey, m_Settings.childKeys()) {
- QVariantMap data = m_Settings.value(serverKey).toMap();
- int preference = data["preferred"].toInt();
- if (preference > 0) {
- result[serverKey] = preference;
- }
- }
- m_Settings.endGroup();
-
- return result;
-}
-
-QString Settings::getCacheDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/cache_directory", ToQString(GameInfo::instance().getCacheDir())).toString());
-}
-
-QString Settings::getModDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/mod_directory", ToQString(GameInfo::instance().getModsDir())).toString());
-}
-
-QString Settings::getNMMVersion() const
-{
- static const QString MIN_NMM_VERSION = "0.47.0";
- QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString();
- if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) {
- result = MIN_NMM_VERSION;
- }
- return result;
-}
-
-bool Settings::getNexusLogin(QString &username, QString &password) const
-{
- if (m_Settings.value("Settings/nexus_login", false).toBool()) {
- username = m_Settings.value("Settings/nexus_username", "").toString();
- password = deObfuscate(m_Settings.value("Settings/nexus_password", "").toString());
- return true;
- } else {
- return false;
- }
-}
-
-bool Settings::compactDownloads() const
-{
- return m_Settings.value("Settings/compact_downloads", false).toBool();
-}
-
-bool Settings::metaDownloads() const
-{
- return m_Settings.value("Settings/meta_downloads", false).toBool();
-}
-
-bool Settings::offlineMode() const
-{
- return m_Settings.value("Settings/offline_mode", false).toBool();
-}
-
-int Settings::logLevel() const
-{
- return m_Settings.value("Settings/log_level", 0).toInt();
-}
-
-
-void Settings::setNexusLogin(QString username, QString password)
-{
- m_Settings.setValue("Settings/nexus_login", true);
- m_Settings.setValue("Settings/nexus_username", username);
- m_Settings.setValue("Settings/nexus_password", obfuscate(password));
-}
-
-
-LoadMechanism::EMechanism Settings::getLoadMechanism() const
-{
- switch (m_Settings.value("Settings/load_mechanism").toInt()) {
- case LoadMechanism::LOAD_MODORGANIZER: return LoadMechanism::LOAD_MODORGANIZER;
- case LoadMechanism::LOAD_SCRIPTEXTENDER: return LoadMechanism::LOAD_SCRIPTEXTENDER;
- case LoadMechanism::LOAD_PROXYDLL: return LoadMechanism::LOAD_PROXYDLL;
- }
- throw std::runtime_error("invalid load mechanism");
-}
-
-
-void Settings::setupLoadMechanism()
-{
- m_LoadMechanism.activate(getLoadMechanism());
-}
-
-
-bool Settings::useProxy()
-{
- return m_Settings.value("Settings/use_proxy", false).toBool();
-}
-
-bool Settings::displayForeign()
-{
- return m_Settings.value("Settings/display_foreign", true).toBool();
-}
-
-void Settings::setMotDHash(uint hash)
-{
- m_Settings.setValue("motd_hash", hash);
-}
-
-uint Settings::getMotDHash() const
-{
- return m_Settings.value("motd_hash", 0).toUInt();
-}
-
-QVariant Settings::pluginSetting(const QString &pluginName, const QString &key) const
-{
- auto iterPlugin = m_PluginSettings.find(pluginName);
- if (iterPlugin == m_PluginSettings.end()) {
- return QVariant();
- }
- auto iterSetting = iterPlugin->find(key);
- if (iterSetting == iterPlugin->end()) {
- return QVariant();
- }
-
- return *iterSetting;
-}
-
-void Settings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
-{
- auto iterPlugin = m_PluginSettings.find(pluginName);
- if (iterPlugin == m_PluginSettings.end()) {
- throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName));
- }
-
- // store the new setting both in memory and in the ini
- m_PluginSettings[pluginName][key] = value;
- m_Settings.setValue("Plugins/" + pluginName + "/" + key, value);
-}
-
-QVariant Settings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const
-{
- if (!m_PluginSettings.contains(pluginName)) {
- return def;
- }
- return m_Settings.value("PluginPersistance/" + pluginName + "/" + key, def);
-}
-
-void Settings::setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync)
-{
- if (!m_PluginSettings.contains(pluginName)) {
- throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName));
- }
- m_Settings.setValue("PluginPersistance/" + pluginName + "/" + key, value);
- if (sync) {
- m_Settings.sync();
- }
-}
-
-QString Settings::language()
-{
- QString result = m_Settings.value("Settings/language", "").toString();
- if (result.isEmpty()) {
- QStringList languagePreferences = QLocale::system().uiLanguages();
- if (languagePreferences.length() > 0) {
- // the users most favoritest language
- result = languagePreferences.at(0);
- } else {
- // fallback system locale
- result = QLocale::system().name();
- }
- }
- return result;
-}
-
-void Settings::updateServers(const QList<ServerInfo> &servers)
-{
- m_Settings.beginGroup("Servers");
- QStringList oldServerKeys = m_Settings.childKeys();
-
- foreach (const ServerInfo &server, servers) {
- if (!oldServerKeys.contains(server.name)) {
- // not yet known server
- QVariantMap newVal;
- newVal["premium"] = server.premium;
- newVal["preferred"] = server.preferred ? 1 : 0;
- newVal["lastSeen"] = server.lastSeen;
- newVal["downloadCount"] = 0;
- newVal["downloadSpeed"] = 0.0;
-
- m_Settings.setValue(server.name, newVal);
- } else {
- QVariantMap data = m_Settings.value(server.name).toMap();
- data["lastSeen"] = server.lastSeen;
- data["premium"] = server.premium;
-
- m_Settings.setValue(server.name, data);
- }
- }
-
- m_Settings.endGroup();
- m_Settings.sync();
-}
-
-void Settings::addBlacklistPlugin(const QString &fileName)
-{
- m_PluginBlacklist.insert(fileName);
- writePluginBlacklist();
-}
-
-void Settings::writePluginBlacklist()
-{
- m_Settings.beginWriteArray("pluginBlacklist");
- int idx = 0;
- foreach (const QString &plugin, m_PluginBlacklist) {
- m_Settings.setArrayIndex(idx++);
- m_Settings.setValue("name", plugin);
- }
-
- m_Settings.endArray();
-}
-
-void Settings::addLanguages(QComboBox *languageBox)
-{
- languageBox->addItem("English", "en_US");
-
- QDirIterator langIter(QCoreApplication::applicationDirPath() + "/translations", QDir::Files);
- QString pattern = ToQString(AppConfig::translationPrefix()) + "_([a-z]{2,3}(_[A-Z]{2,2})?).qm";
- QRegExp exp(pattern);
- while (langIter.hasNext()) {
- langIter.next();
- QString file = langIter.fileName();
- if (exp.exactMatch(file)) {
- QString languageCode = exp.cap(1);
- QLocale locale(languageCode);
- QString languageString = QLocale::languageToString(locale.language());
- if (locale.language() == QLocale::Chinese) {
- if (languageCode == "zh_TW") {
- languageString = "Chinese (traditional)";
- } else {
- languageString = "Chinese (simplified)";
- }
- }
- languageBox->addItem(QString("%1").arg(languageString), exp.cap(1));
- }
- }
-}
-
-void Settings::addStyles(QComboBox *styleBox)
-{
- styleBox->addItem("None", "");
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
- styleBox->addItem("Fusion", "Fusion");
-#else
- styleBox->addItem("Plastique", "Plastique");
- styleBox->addItem("Cleanlooks", "Cleanlooks");
-#endif
-
- QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), QStringList("*.qss"), QDir::Files);
- while (langIter.hasNext()) {
- langIter.next();
- QString style = langIter.fileName();
- styleBox->addItem(style, style);
- }
-}
-
-void Settings::resetDialogs()
-{
- m_Settings.beginGroup("DialogChoices");
- QStringList keys = m_Settings.childKeys();
- foreach (QString key, keys) {
- m_Settings.remove(key);
- }
-
- m_Settings.endGroup();
-}
-
-
-void Settings::query(QWidget *parent)
-{
- SettingsDialog dialog(parent);
-
- connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs()));
-
- // General Page
- QComboBox *languageBox = dialog.findChild<QComboBox*>("languageBox");
- QComboBox *styleBox = dialog.findChild<QComboBox*>("styleBox");
- QComboBox *logLevelBox = dialog.findChild<QComboBox*>("logLevelBox");
- QCheckBox *compactBox = dialog.findChild<QCheckBox*>("compactBox");
- QCheckBox *showMetaBox = dialog.findChild<QCheckBox*>("showMetaBox");
-
- QLineEdit *downloadDirEdit = dialog.findChild<QLineEdit*>("downloadDirEdit");
- QLineEdit *modDirEdit = dialog.findChild<QLineEdit*>("modDirEdit");
- QLineEdit *cacheDirEdit = dialog.findChild<QLineEdit*>("cacheDirEdit");
-
- // nexus page
- QCheckBox *loginCheckBox = dialog.findChild<QCheckBox*>("loginCheckBox");
- QLineEdit *usernameEdit = dialog.findChild<QLineEdit*>("usernameEdit");
- QLineEdit *passwordEdit = dialog.findChild<QLineEdit*>("passwordEdit");
- QCheckBox *offlineBox = dialog.findChild<QCheckBox*>("offlineBox");
- QCheckBox *proxyBox = dialog.findChild<QCheckBox*>("proxyBox");
-
- QListWidget *knownServersList = dialog.findChild<QListWidget*>("knownServersList");
- QListWidget *preferredServersList = dialog.findChild<QListWidget*>("preferredServersList");
-
- // plugis page
- QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList");
- QListWidget *pluginBlacklistList = dialog.findChild<QListWidget*>("pluginBlacklist");
-
- // workarounds page
- QCheckBox *forceEnableBox = dialog.findChild<QCheckBox*>("forceEnableBox");
- QComboBox *mechanismBox = dialog.findChild<QComboBox*>("mechanismBox");
- QLineEdit *appIDEdit = dialog.findChild<QLineEdit*>("appIDEdit");
- QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit");
- QCheckBox *hideUncheckedBox = dialog.findChild<QCheckBox*>("hideUncheckedBox");
- QCheckBox *displayForeignBox = dialog.findChild<QCheckBox*>("displayForeignBox");
-
-
- //
- // set up current settings
- //
- LoadMechanism::EMechanism mechanismID = getLoadMechanism();
- int index = 0;
-
- if (m_LoadMechanism.isDirectLoadingSupported()) {
- mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER);
- if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) {
- index = mechanismBox->count() - 1;
- }
- }
-
- if (m_LoadMechanism.isScriptExtenderSupported()) {
- mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER);
- if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) {
- index = mechanismBox->count() - 1;
- }
- }
-
- if (m_LoadMechanism.isProxyDLLSupported()) {
- mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL);
- if (mechanismID == LoadMechanism::LOAD_PROXYDLL) {
- index = mechanismBox->count() - 1;
- }
- }
-
- mechanismBox->setCurrentIndex(index);
-
- {
- addLanguages(languageBox);
- QString languageCode = language();
- int currentID = languageBox->findData(languageCode);
- // I made a mess. :( Most languages are stored with only the iso country code (2 characters like "de") but chinese
- // with the exact language variant (zh_TW) so I have to search for both variants
- if (currentID == -1) {
- currentID = languageBox->findData(languageCode.mid(0, 2));
- }
- if (currentID != -1) {
- languageBox->setCurrentIndex(currentID);
- }
- }
-
- {
- addStyles(styleBox);
- int currentID = styleBox->findData(m_Settings.value("Settings/style", "").toString());
- if (currentID != -1) {
- styleBox->setCurrentIndex(currentID);
- }
- }
-
- compactBox->setChecked(compactDownloads());
- showMetaBox->setChecked(metaDownloads());
-
- hideUncheckedBox->setChecked(hideUncheckedPlugins());
- displayForeignBox->setChecked(displayForeign());
- forceEnableBox->setChecked(forceEnableCoreFiles());
-
- appIDEdit->setText(getSteamAppID());
-
- if (automaticLoginEnabled()) {
- loginCheckBox->setChecked(true);
- usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString());
- passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()));
- }
-
- downloadDirEdit->setText(getDownloadDirectory());
- modDirEdit->setText(getModDirectory());
- cacheDirEdit->setText(getCacheDirectory());
- offlineBox->setChecked(offlineMode());
- proxyBox->setChecked(useProxy());
- nmmVersionEdit->setText(getNMMVersion());
- logLevelBox->setCurrentIndex(logLevel());
-
- // display plugin settings
- foreach (IPlugin *plugin, m_Plugins) {
- QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), pluginsList);
- listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin));
- listItem->setData(Qt::UserRole + 1, m_PluginSettings[plugin->name()]);
- pluginsList->addItem(listItem);
- }
-
- // display plugin blacklist
- foreach (const QString &pluginName, m_PluginBlacklist) {
- pluginBlacklistList->addItem(pluginName);
- }
-
- // display server preferences
- m_Settings.beginGroup("Servers");
- foreach (const QString &key, m_Settings.childKeys()) {
- QVariantMap val = m_Settings.value(key).toMap();
- QString type = val["premium"].toBool() ? "(premium)" : "(free)";
-
- QString descriptor = key + " " + type;
- if (val.contains("downloadSpeed") && val.contains("downloadCount") && (val["downloadCount"].toInt() > 0)) {
- int bps = static_cast<int>(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt());
- descriptor += QString(" (%1 kbps)").arg(bps / 1024);
- }
-
- QListWidgetItem *newItem = new QListWidgetItemEx<int>(descriptor, Qt::UserRole + 1);
-
- newItem->setData(Qt::UserRole, key);
- newItem->setData(Qt::UserRole + 1, val["preferred"].toInt());
- if (val["preferred"].toInt() > 0) {
- preferredServersList->addItem(newItem);
- } else {
- knownServersList->addItem(newItem);
- }
- preferredServersList->sortItems(Qt::DescendingOrder);
- }
- m_Settings.endGroup();
-
- if (dialog.exec() == QDialog::Accepted) {
- //
- // transfer modified settings to configuration file
- //
-
- m_Settings.setValue("Settings/hide_unchecked_plugins", hideUncheckedBox->checkState() ? true : false);
- m_Settings.setValue("Settings/force_enable_core_files", forceEnableBox->checkState() ? true : false);
- m_Settings.setValue("Settings/compact_downloads", compactBox->isChecked());
- m_Settings.setValue("Settings/meta_downloads", showMetaBox->isChecked());
- m_Settings.setValue("Settings/load_mechanism", mechanismBox->itemData(mechanismBox->currentIndex()).toInt());
-
-
- { // advanced settings
- if ((QDir::fromNativeSeparators(modDirEdit->text()) != QDir::fromNativeSeparators(getModDirectory())) &&
- (QMessageBox::question(NULL, tr("Confirm"), tr("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?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) {
- modDirEdit->setText(getModDirectory());
- }
-
- if (!QDir(downloadDirEdit->text()).exists()) {
- QDir().mkpath(downloadDirEdit->text());
- }
- if (!QDir(cacheDirEdit->text()).exists()) {
- QDir().mkpath(cacheDirEdit->text());
- }
- if (!QDir(modDirEdit->text()).exists()) {
- QDir().mkpath(modDirEdit->text());
- }
-
- m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text()));
- m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text()));
- m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text()));
- }
-
-
- QString oldLanguage = m_Settings.value("Settings/language", "en_US").toString();
- QString newLanguage = languageBox->itemData(languageBox->currentIndex()).toString();
- if (newLanguage != oldLanguage) {
- m_Settings.setValue("Settings/language", newLanguage);
- emit languageChanged(newLanguage);
- }
-
- QString oldStyle = m_Settings.value("Settings/style", "").toString();
- QString newStyle = styleBox->itemData(styleBox->currentIndex()).toString();
- if (oldStyle != newStyle) {
- m_Settings.setValue("Settings/style", newStyle);
- emit styleChanged(newStyle);
- }
-
- m_Settings.setValue("Settings/log_level", logLevelBox->currentIndex());
-
- if (appIDEdit->text() != ToQString(GameInfo::instance().getSteamAPPId())) {
- m_Settings.setValue("Settings/app_id", appIDEdit->text());
- } else {
- m_Settings.remove("Settings/app_id");
- }
- if (loginCheckBox->isChecked()) {
- m_Settings.setValue("Settings/nexus_login", true);
- m_Settings.setValue("Settings/nexus_username", usernameEdit->text());
- m_Settings.setValue("Settings/nexus_password", obfuscate(passwordEdit->text()));
- } else {
- m_Settings.setValue("Settings/nexus_login", false);
- m_Settings.remove("Settings/nexus_username");
- m_Settings.remove("Settings/nexus_password");
- }
- m_Settings.setValue("Settings/offline_mode", offlineBox->isChecked());
- m_Settings.setValue("Settings/use_proxy", proxyBox->isChecked());
- m_Settings.setValue("Settings/display_foreign", displayForeignBox->isChecked());
-
- m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text());
-
- // transfer plugin settings to in-memory structure
- for (int i = 0; i < pluginsList->count(); ++i) {
- QListWidgetItem *item = pluginsList->item(i);
- m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap();
- }
- // store plugin settings on disc
- for (auto iterPlugins = m_PluginSettings.begin(); iterPlugins != m_PluginSettings.end(); ++iterPlugins) {
- for (auto iterSettings = iterPlugins->begin(); iterSettings != iterPlugins->end(); ++iterSettings) {
- m_Settings.setValue("Plugins/" + iterPlugins.key() + "/" + iterSettings.key(), iterSettings.value());
- }
- }
-
- // store plugin blacklist
- m_PluginBlacklist.clear();
- foreach (QListWidgetItem *item, pluginBlacklistList->findItems("*", Qt::MatchWildcard)) {
- m_PluginBlacklist.insert(item->text());
- }
- writePluginBlacklist();
-
- // store server preference
- m_Settings.beginGroup("Servers");
- for (int i = 0; i < knownServersList->count(); ++i) {
- QString key = knownServersList->item(i)->data(Qt::UserRole).toString();
- QVariantMap val = m_Settings.value(key).toMap();
- val["preferred"] = 0;
- m_Settings.setValue(key, val);
- }
- int count = preferredServersList->count();
- for (int i = 0; i < count; ++i) {
- QString key = preferredServersList->item(i)->data(Qt::UserRole).toString();
- QVariantMap val = m_Settings.value(key).toMap();
- val["preferred"] = count - i;
- m_Settings.setValue(key, val);
- }
- m_Settings.endGroup();
- }
-}
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "settings.h" + +#include "settingsdialog.h" +#include "utility.h" +#include "helper.h" +#include <gameinfo.h> +#include <appconfig.h> +#include <utility.h> +#include "json.h" + +#include <QCheckBox> +#include <QLineEdit> +#include <QDirIterator> +#include <QRegExp> +#include <QCoreApplication> +#include <QMessageBox> +#include <QDesktopServices> + + +using namespace MOBase; +using namespace MOShared; + + +template <typename T> +class QListWidgetItemEx : public QListWidgetItem { +public: + QListWidgetItemEx(const QString &text, int sortRole = Qt::DisplayRole, QListWidget *parent = 0, int type = Type) + : QListWidgetItem(text, parent, type), m_SortRole(sortRole) {} + + virtual bool operator< ( const QListWidgetItem & other ) const { + return this->data(m_SortRole).value<T>() < other.data(m_SortRole).value<T>(); + } +private: + int m_SortRole; +}; + + +static const unsigned char Key2[20] = { 0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60, 0xa4, 0x5b, 0x01, + 0xdb, 0xf8, 0x43, 0x3a, 0xb7, 0xb6, 0x98, 0xd4, 0x7d, 0xa2 }; + +Settings *Settings::s_Instance = NULL; + + +Settings::Settings() + : m_Settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat) +{ + if (s_Instance != NULL) { + throw std::runtime_error("second instance of \"Settings\" created"); + } else { + s_Instance = this; + } +} + + +Settings::~Settings() +{ + s_Instance = NULL; +} + + +Settings &Settings::instance() +{ + if (s_Instance == NULL) { + throw std::runtime_error("no instance of \"Settings\""); + } + return *s_Instance; +} + +void Settings::clearPlugins() +{ + m_Plugins.clear(); + m_PluginSettings.clear(); + + m_PluginBlacklist.clear(); + int count = m_Settings.beginReadArray("pluginBlacklist"); + for (int i = 0; i < count; ++i) { + m_Settings.setArrayIndex(i); + m_PluginBlacklist.insert(m_Settings.value("name").toString()); + } + m_Settings.endArray(); +} + +bool Settings::pluginBlacklisted(const QString &fileName) const +{ + return m_PluginBlacklist.contains(fileName); +} + +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" " + GameInfo::instance().getGameShortName() + L" \"" + executable + L"\""; + HINSTANCE res = ::ShellExecuteW(NULL, L"open", nxmPath.c_str(), parameters.c_str(), NULL, SW_SHOWNORMAL); + if ((int)res <= 32) { + QMessageBox::critical(NULL, tr("Failed"), + tr("Sorry, failed to start the helper application")); + } +} + +void Settings::registerPlugin(IPlugin *plugin) +{ + m_Plugins.push_back(plugin); + m_PluginSettings.insert(plugin->name(), QMap<QString, QVariant>()); + m_PluginDescriptions.insert(plugin->name(), QMap<QString, QVariant>()); + foreach (const PluginSetting &setting, plugin->settings()) { + QVariant temp = m_Settings.value("Plugins/" + plugin->name() + "/" + setting.key, setting.defaultValue); + if (!temp.convert(setting.defaultValue.type())) { + qWarning("failed to interpret \"%s\" as correct type for \"%s\" in plugin \"%s\", using default", + qPrintable(temp.toString()), qPrintable(setting.key), qPrintable(plugin->name())); + temp = setting.defaultValue; + } + m_PluginSettings[plugin->name()][setting.key] = temp; + m_PluginDescriptions[plugin->name()][setting.key] = QString("%1 (default: %2)").arg(setting.description).arg(setting.defaultValue.toString()); + } +} + + +QString Settings::obfuscate(const QString &password) const +{ + QByteArray temp = password.toUtf8(); + + QByteArray buffer; + for (int i = 0; i < temp.length(); ++i) { + buffer.append(temp.at(i) ^ Key2[i % 20]); + } + return buffer.toBase64(); +} + + +QString Settings::deObfuscate(const QString &password) const +{ + QByteArray temp(QByteArray::fromBase64(password.toUtf8())); + + QByteArray buffer; + for (int i = 0; i < temp.length(); ++i) { + buffer.append(temp.at(i) ^ Key2[i % 20]); + } + return QString::fromUtf8(buffer.constData()); +} + + +bool Settings::hideUncheckedPlugins() const +{ + return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool(); +} + +bool Settings::forceEnableCoreFiles() const +{ + return m_Settings.value("Settings/force_enable_core_files", true).toBool(); +} + +bool Settings::automaticLoginEnabled() const +{ + return m_Settings.value("Settings/nexus_login", false).toBool(); +} + +QString Settings::getSteamAppID() const +{ + return m_Settings.value("Settings/app_id", ToQString(GameInfo::instance().getSteamAPPId(m_Settings.value("game_edition", 0).toInt()))).toString(); +} + +QString Settings::getDownloadDirectory() const +{ + return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString()); +} + + +void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond) +{ + m_Settings.beginGroup("Servers"); + + foreach (const QString &serverKey, m_Settings.childKeys()) { + QVariantMap data = m_Settings.value(serverKey).toMap(); + if (serverKey == serverName) { + data["downloadCount"] = data["downloadCount"].toInt() + 1; + data["downloadSpeed"] = data["downloadSpeed"].toDouble() + static_cast<double>(bytesPerSecond); + m_Settings.setValue(serverKey, data); + } + } + + m_Settings.endGroup(); + m_Settings.sync(); +} + +std::map<QString, int> Settings::getPreferredServers() +{ + std::map<QString, int> result; + m_Settings.beginGroup("Servers"); + + foreach (const QString &serverKey, m_Settings.childKeys()) { + QVariantMap data = m_Settings.value(serverKey).toMap(); + int preference = data["preferred"].toInt(); + if (preference > 0) { + result[serverKey] = preference; + } + } + m_Settings.endGroup(); + + return result; +} + +QString Settings::getCacheDirectory() const +{ + return QDir::toNativeSeparators(m_Settings.value("Settings/cache_directory", ToQString(GameInfo::instance().getCacheDir())).toString()); +} + +QString Settings::getModDirectory() const +{ + return QDir::toNativeSeparators(m_Settings.value("Settings/mod_directory", ToQString(GameInfo::instance().getModsDir())).toString()); +} + +QString Settings::getNMMVersion() const +{ + static const QString MIN_NMM_VERSION = "0.52.3"; + QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString(); + if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) { + result = MIN_NMM_VERSION; + } + return result; +} + +bool Settings::getNexusLogin(QString &username, QString &password) const +{ + if (m_Settings.value("Settings/nexus_login", false).toBool()) { + username = m_Settings.value("Settings/nexus_username", "").toString(); + password = deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()); + return true; + } else { + return false; + } +} + +bool Settings::compactDownloads() const +{ + return m_Settings.value("Settings/compact_downloads", false).toBool(); +} + +bool Settings::metaDownloads() const +{ + return m_Settings.value("Settings/meta_downloads", false).toBool(); +} + +bool Settings::offlineMode() const +{ + return m_Settings.value("Settings/offline_mode", false).toBool(); +} + +int Settings::logLevel() const +{ + return m_Settings.value("Settings/log_level", 0).toInt(); +} + + +void Settings::setNexusLogin(QString username, QString password) +{ + m_Settings.setValue("Settings/nexus_login", true); + m_Settings.setValue("Settings/nexus_username", username); + m_Settings.setValue("Settings/nexus_password", obfuscate(password)); +} + + +LoadMechanism::EMechanism Settings::getLoadMechanism() const +{ + switch (m_Settings.value("Settings/load_mechanism").toInt()) { + case LoadMechanism::LOAD_MODORGANIZER: return LoadMechanism::LOAD_MODORGANIZER; + case LoadMechanism::LOAD_SCRIPTEXTENDER: return LoadMechanism::LOAD_SCRIPTEXTENDER; + case LoadMechanism::LOAD_PROXYDLL: return LoadMechanism::LOAD_PROXYDLL; + } + throw std::runtime_error("invalid load mechanism"); +} + + +void Settings::setupLoadMechanism() +{ + m_LoadMechanism.activate(getLoadMechanism()); +} + + +bool Settings::useProxy() +{ + return m_Settings.value("Settings/use_proxy", false).toBool(); +} + +bool Settings::displayForeign() +{ + return m_Settings.value("Settings/display_foreign", true).toBool(); +} + +void Settings::setMotDHash(uint hash) +{ + m_Settings.setValue("motd_hash", hash); +} + +uint Settings::getMotDHash() const +{ + return m_Settings.value("motd_hash", 0).toUInt(); +} + +QVariant Settings::pluginSetting(const QString &pluginName, const QString &key) const +{ + auto iterPlugin = m_PluginSettings.find(pluginName); + if (iterPlugin == m_PluginSettings.end()) { + return QVariant(); + } + auto iterSetting = iterPlugin->find(key); + if (iterSetting == iterPlugin->end()) { + return QVariant(); + } + + return *iterSetting; +} + +void Settings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) +{ + auto iterPlugin = m_PluginSettings.find(pluginName); + if (iterPlugin == m_PluginSettings.end()) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } + + // store the new setting both in memory and in the ini + m_PluginSettings[pluginName][key] = value; + m_Settings.setValue("Plugins/" + pluginName + "/" + key, value); +} + +QVariant Settings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const +{ + if (!m_PluginSettings.contains(pluginName)) { + return def; + } + return m_Settings.value("PluginPersistance/" + pluginName + "/" + key, def); +} + +void Settings::setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) +{ + if (!m_PluginSettings.contains(pluginName)) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } + m_Settings.setValue("PluginPersistance/" + pluginName + "/" + key, value); + if (sync) { + m_Settings.sync(); + } +} + +QString Settings::language() +{ + QString result = m_Settings.value("Settings/language", "").toString(); + if (result.isEmpty()) { + QStringList languagePreferences = QLocale::system().uiLanguages(); + if (languagePreferences.length() > 0) { + // the users most favoritest language + result = languagePreferences.at(0); + } else { + // fallback system locale + result = QLocale::system().name(); + } + } + return result; +} + +void Settings::updateServers(const QList<ServerInfo> &servers) +{ + m_Settings.beginGroup("Servers"); + QStringList oldServerKeys = m_Settings.childKeys(); + + foreach (const ServerInfo &server, servers) { + if (!oldServerKeys.contains(server.name)) { + // not yet known server + QVariantMap newVal; + newVal["premium"] = server.premium; + newVal["preferred"] = server.preferred ? 1 : 0; + newVal["lastSeen"] = server.lastSeen; + newVal["downloadCount"] = 0; + newVal["downloadSpeed"] = 0.0; + + m_Settings.setValue(server.name, newVal); + } else { + QVariantMap data = m_Settings.value(server.name).toMap(); + data["lastSeen"] = server.lastSeen; + data["premium"] = server.premium; + + m_Settings.setValue(server.name, data); + } + } + + m_Settings.endGroup(); + m_Settings.sync(); +} + +void Settings::addBlacklistPlugin(const QString &fileName) +{ + m_PluginBlacklist.insert(fileName); + writePluginBlacklist(); +} + +void Settings::writePluginBlacklist() +{ + m_Settings.beginWriteArray("pluginBlacklist"); + int idx = 0; + foreach (const QString &plugin, m_PluginBlacklist) { + m_Settings.setArrayIndex(idx++); + m_Settings.setValue("name", plugin); + } + + m_Settings.endArray(); +} + +void Settings::addLanguages(QComboBox *languageBox) +{ + languageBox->addItem("English", "en_US"); + + QDirIterator langIter(QCoreApplication::applicationDirPath() + "/translations", QDir::Files); + QString pattern = ToQString(AppConfig::translationPrefix()) + "_([a-z]{2,3}(_[A-Z]{2,2})?).qm"; + QRegExp exp(pattern); + while (langIter.hasNext()) { + langIter.next(); + QString file = langIter.fileName(); + if (exp.exactMatch(file)) { + QString languageCode = exp.cap(1); + QLocale locale(languageCode); + QString languageString = QLocale::languageToString(locale.language()); + if (locale.language() == QLocale::Chinese) { + if (languageCode == "zh_TW") { + languageString = "Chinese (traditional)"; + } else { + languageString = "Chinese (simplified)"; + } + } + languageBox->addItem(QString("%1").arg(languageString), exp.cap(1)); + } + } +} + +void Settings::addStyles(QComboBox *styleBox) +{ + styleBox->addItem("None", ""); +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + styleBox->addItem("Fusion", "Fusion"); +#else + styleBox->addItem("Plastique", "Plastique"); + styleBox->addItem("Cleanlooks", "Cleanlooks"); +#endif + + QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), QStringList("*.qss"), QDir::Files); + while (langIter.hasNext()) { + langIter.next(); + QString style = langIter.fileName(); + styleBox->addItem(style, style); + } +} + +void Settings::resetDialogs() +{ + m_Settings.beginGroup("DialogChoices"); + QStringList keys = m_Settings.childKeys(); + foreach (QString key, keys) { + m_Settings.remove(key); + } + + m_Settings.endGroup(); +} + + +void Settings::query(QWidget *parent) +{ + SettingsDialog dialog(parent); + + connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs())); + + // General Page + QComboBox *languageBox = dialog.findChild<QComboBox*>("languageBox"); + QComboBox *styleBox = dialog.findChild<QComboBox*>("styleBox"); + QComboBox *logLevelBox = dialog.findChild<QComboBox*>("logLevelBox"); + QCheckBox *compactBox = dialog.findChild<QCheckBox*>("compactBox"); + QCheckBox *showMetaBox = dialog.findChild<QCheckBox*>("showMetaBox"); + + QLineEdit *downloadDirEdit = dialog.findChild<QLineEdit*>("downloadDirEdit"); + QLineEdit *modDirEdit = dialog.findChild<QLineEdit*>("modDirEdit"); + QLineEdit *cacheDirEdit = dialog.findChild<QLineEdit*>("cacheDirEdit"); + + // nexus page + QCheckBox *loginCheckBox = dialog.findChild<QCheckBox*>("loginCheckBox"); + QLineEdit *usernameEdit = dialog.findChild<QLineEdit*>("usernameEdit"); + QLineEdit *passwordEdit = dialog.findChild<QLineEdit*>("passwordEdit"); + QCheckBox *offlineBox = dialog.findChild<QCheckBox*>("offlineBox"); + QCheckBox *proxyBox = dialog.findChild<QCheckBox*>("proxyBox"); + + QListWidget *knownServersList = dialog.findChild<QListWidget*>("knownServersList"); + QListWidget *preferredServersList = dialog.findChild<QListWidget*>("preferredServersList"); + + // plugis page + QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList"); + QListWidget *pluginBlacklistList = dialog.findChild<QListWidget*>("pluginBlacklist"); + + // workarounds page + QCheckBox *forceEnableBox = dialog.findChild<QCheckBox*>("forceEnableBox"); + QComboBox *mechanismBox = dialog.findChild<QComboBox*>("mechanismBox"); + QLineEdit *appIDEdit = dialog.findChild<QLineEdit*>("appIDEdit"); + QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit"); + QCheckBox *hideUncheckedBox = dialog.findChild<QCheckBox*>("hideUncheckedBox"); + QCheckBox *displayForeignBox = dialog.findChild<QCheckBox*>("displayForeignBox"); + + + // + // set up current settings + // + LoadMechanism::EMechanism mechanismID = getLoadMechanism(); + int index = 0; + + if (m_LoadMechanism.isDirectLoadingSupported()) { + mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER); + if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) { + index = mechanismBox->count() - 1; + } + } + + if (m_LoadMechanism.isScriptExtenderSupported()) { + mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER); + if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) { + index = mechanismBox->count() - 1; + } + } + + if (m_LoadMechanism.isProxyDLLSupported()) { + mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL); + if (mechanismID == LoadMechanism::LOAD_PROXYDLL) { + index = mechanismBox->count() - 1; + } + } + + mechanismBox->setCurrentIndex(index); + + { + addLanguages(languageBox); + QString languageCode = language(); + int currentID = languageBox->findData(languageCode); + // I made a mess. :( Most languages are stored with only the iso country code (2 characters like "de") but chinese + // with the exact language variant (zh_TW) so I have to search for both variants + if (currentID == -1) { + currentID = languageBox->findData(languageCode.mid(0, 2)); + } + if (currentID != -1) { + languageBox->setCurrentIndex(currentID); + } + } + + { + addStyles(styleBox); + int currentID = styleBox->findData(m_Settings.value("Settings/style", "").toString()); + if (currentID != -1) { + styleBox->setCurrentIndex(currentID); + } + } + + compactBox->setChecked(compactDownloads()); + showMetaBox->setChecked(metaDownloads()); + + hideUncheckedBox->setChecked(hideUncheckedPlugins()); + displayForeignBox->setChecked(displayForeign()); + forceEnableBox->setChecked(forceEnableCoreFiles()); + + appIDEdit->setText(getSteamAppID()); + + if (automaticLoginEnabled()) { + loginCheckBox->setChecked(true); + usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString()); + passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString())); + } + + downloadDirEdit->setText(getDownloadDirectory()); + modDirEdit->setText(getModDirectory()); + cacheDirEdit->setText(getCacheDirectory()); + offlineBox->setChecked(offlineMode()); + proxyBox->setChecked(useProxy()); + nmmVersionEdit->setText(getNMMVersion()); + logLevelBox->setCurrentIndex(logLevel()); + + // display plugin settings + foreach (IPlugin *plugin, m_Plugins) { + QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), pluginsList); + listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin)); + listItem->setData(Qt::UserRole + 1, m_PluginSettings[plugin->name()]); + listItem->setData(Qt::UserRole + 2, m_PluginDescriptions[plugin->name()]); + pluginsList->addItem(listItem); + } + + // display plugin blacklist + foreach (const QString &pluginName, m_PluginBlacklist) { + pluginBlacklistList->addItem(pluginName); + } + + // display server preferences + m_Settings.beginGroup("Servers"); + foreach (const QString &key, m_Settings.childKeys()) { + QVariantMap val = m_Settings.value(key).toMap(); + QString type = val["premium"].toBool() ? "(premium)" : "(free)"; + + QString descriptor = key + " " + type; + if (val.contains("downloadSpeed") && val.contains("downloadCount") && (val["downloadCount"].toInt() > 0)) { + int bps = static_cast<int>(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt()); + descriptor += QString(" (%1 kbps)").arg(bps / 1024); + } + + QListWidgetItem *newItem = new QListWidgetItemEx<int>(descriptor, Qt::UserRole + 1); + + newItem->setData(Qt::UserRole, key); + newItem->setData(Qt::UserRole + 1, val["preferred"].toInt()); + if (val["preferred"].toInt() > 0) { + preferredServersList->addItem(newItem); + } else { + knownServersList->addItem(newItem); + } + preferredServersList->sortItems(Qt::DescendingOrder); + } + m_Settings.endGroup(); + + if (dialog.exec() == QDialog::Accepted) { + // + // transfer modified settings to configuration file + // + + m_Settings.setValue("Settings/hide_unchecked_plugins", hideUncheckedBox->checkState() ? true : false); + m_Settings.setValue("Settings/force_enable_core_files", forceEnableBox->checkState() ? true : false); + m_Settings.setValue("Settings/compact_downloads", compactBox->isChecked()); + m_Settings.setValue("Settings/meta_downloads", showMetaBox->isChecked()); + m_Settings.setValue("Settings/load_mechanism", mechanismBox->itemData(mechanismBox->currentIndex()).toInt()); + + + { // advanced settings + if ((QDir::fromNativeSeparators(modDirEdit->text()) != QDir::fromNativeSeparators(getModDirectory())) && + (QMessageBox::question(NULL, tr("Confirm"), tr("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?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)) { + modDirEdit->setText(getModDirectory()); + } + + if (!QDir(downloadDirEdit->text()).exists()) { + QDir().mkpath(downloadDirEdit->text()); + } + if (!QDir(cacheDirEdit->text()).exists()) { + QDir().mkpath(cacheDirEdit->text()); + } + if (!QDir(modDirEdit->text()).exists()) { + QDir().mkpath(modDirEdit->text()); + } + + m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text())); + m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text())); + m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text())); + } + + + QString oldLanguage = m_Settings.value("Settings/language", "en_US").toString(); + QString newLanguage = languageBox->itemData(languageBox->currentIndex()).toString(); + if (newLanguage != oldLanguage) { + m_Settings.setValue("Settings/language", newLanguage); + emit languageChanged(newLanguage); + } + + QString oldStyle = m_Settings.value("Settings/style", "").toString(); + QString newStyle = styleBox->itemData(styleBox->currentIndex()).toString(); + if (oldStyle != newStyle) { + m_Settings.setValue("Settings/style", newStyle); + emit styleChanged(newStyle); + } + + m_Settings.setValue("Settings/log_level", logLevelBox->currentIndex()); + + if (appIDEdit->text() != ToQString(GameInfo::instance().getSteamAPPId())) { + m_Settings.setValue("Settings/app_id", appIDEdit->text()); + } else { + m_Settings.remove("Settings/app_id"); + } + if (loginCheckBox->isChecked()) { + m_Settings.setValue("Settings/nexus_login", true); + m_Settings.setValue("Settings/nexus_username", usernameEdit->text()); + m_Settings.setValue("Settings/nexus_password", obfuscate(passwordEdit->text())); + } else { + m_Settings.setValue("Settings/nexus_login", false); + m_Settings.remove("Settings/nexus_username"); + m_Settings.remove("Settings/nexus_password"); + } + m_Settings.setValue("Settings/offline_mode", offlineBox->isChecked()); + m_Settings.setValue("Settings/use_proxy", proxyBox->isChecked()); + m_Settings.setValue("Settings/display_foreign", displayForeignBox->isChecked()); + + m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text()); + + // transfer plugin settings to in-memory structure + for (int i = 0; i < pluginsList->count(); ++i) { + QListWidgetItem *item = pluginsList->item(i); + m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap(); + } + // store plugin settings on disc + for (auto iterPlugins = m_PluginSettings.begin(); iterPlugins != m_PluginSettings.end(); ++iterPlugins) { + for (auto iterSettings = iterPlugins->begin(); iterSettings != iterPlugins->end(); ++iterSettings) { + m_Settings.setValue("Plugins/" + iterPlugins.key() + "/" + iterSettings.key(), iterSettings.value()); + } + } + + // store plugin blacklist + m_PluginBlacklist.clear(); + foreach (QListWidgetItem *item, pluginBlacklistList->findItems("*", Qt::MatchWildcard)) { + m_PluginBlacklist.insert(item->text()); + } + writePluginBlacklist(); + + // store server preference + m_Settings.beginGroup("Servers"); + for (int i = 0; i < knownServersList->count(); ++i) { + QString key = knownServersList->item(i)->data(Qt::UserRole).toString(); + QVariantMap val = m_Settings.value(key).toMap(); + val["preferred"] = 0; + m_Settings.setValue(key, val); + } + int count = preferredServersList->count(); + for (int i = 0; i < count; ++i) { + QString key = preferredServersList->item(i)->data(Qt::UserRole).toString(); + QVariantMap val = m_Settings.value(key).toMap(); + val["preferred"] = count - i; + m_Settings.setValue(key, val); + } + m_Settings.endGroup(); + } +} diff --git a/src/settings.h b/src/settings.h index 40fd2c5a..5d398f49 100644 --- a/src/settings.h +++ b/src/settings.h @@ -1,310 +1,311 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef WORKAROUNDS_H
-#define WORKAROUNDS_H
-
-#include "loadmechanism.h"
-#include "serverinfo.h"
-#include <iplugin.h>
-
-#include <QSettings>
-#include <QListWidget>
-#include <QComboBox>
-
-
-/**
- * manages the settings for Mod Organizer. The settings are not cached
- * inside the class but read/written directly from/to disc
- **/
-class Settings : public QObject
-{
-
- Q_OBJECT
-
-public:
-
- /**
- * @brief constructor
- **/
- Settings();
-
- virtual ~Settings();
-
- static Settings &instance();
-
- /**
- * unregister all plugins from settings
- */
- void clearPlugins();
-
- /**
- * @brief register plugin to be configurable
- * @param plugin the plugin to register
- * @return true if the plugin may be registered, false if it is blacklisted
- */
- void registerPlugin(MOBase::IPlugin *plugin);
-
- /**
- * 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);
-
- /**
- * set up the settings for the specified plugins
- **/
- void addPluginSettings(const std::vector<MOBase::IPlugin*> &plugins);
-
- /**
- * @return true if the user wants unchecked plugins (esp, esm) should be hidden from
- * the virtual dat adirectory
- **/
- bool hideUncheckedPlugins() const;
-
- /**
- * @return true if files of the core game are forced-enabled so the user can't accidentally disable them
- */
- bool forceEnableCoreFiles() const;
-
- /**
- * @brief register download speed
- * @param url complete download url
- * @param bytesPerSecond download size in bytes per second
- */
- void setDownloadSpeed(const QString &serverName, int bytesPerSecond);
-
- /**
- * the steam appid is assigned by the steam platform to each product sold there.
- * The appid may differ between different versions of a game so it may be impossible
- * for Mod Organizer to automatically recognize it, though usually it does
- * @return the steam appid for the game
- **/
- QString getSteamAppID() const;
-
- /**
- * retrieve the directory where downloads are stored (with native separators)
- **/
- QString getDownloadDirectory() const;
-
- /**
- * retrieve a sorted list of preferred servers
- */
- std::map<QString, int> getPreferredServers();
-
- /**
- * retrieve the directory where mods are stored (with native separators)
- **/
- QString getModDirectory() const;
-
- /**
- * returns the version of nmm to impersonate when connecting to nexus
- **/
- QString getNMMVersion() const;
-
- /**
- * retrieve the directory where the web cache is stored (with native separators)
- **/
- QString getCacheDirectory() const;
-
- /**
- * @return true if the user has set up automatic login to nexus
- **/
- bool automaticLoginEnabled() const;
-
- /**
- * @brief retrieve the login information for nexus
- *
- * @param username (out) receives the user name for nexus
- * @param password (out) received the password for nexus
- * @return true if automatic login is active, false otherwise
- **/
- bool getNexusLogin(QString &username, QString &password) const;
-
- /**
- * @return true if the user disabled internet features
- */
- bool offlineMode() const;
-
- /**
- * @return true if the user chose compact downloads
- */
- bool compactDownloads() const;
-
- /**
- * @return true if the user chose meta downloads
- */
- bool metaDownloads() const;
-
- /**
- * @return the configured log level
- */
- int logLevel() const;
-
- /**
- * @brief set the nexus login information
- *
- * @param username username
- * @param password password
- */
- void setNexusLogin(QString username, QString password);
-
- /**
- * @return the load mechanism to be used
- **/
- LoadMechanism::EMechanism getLoadMechanism() const;
-
- /**
- * @brief activate the load mechanism selected by the user
- **/
- void setupLoadMechanism();
-
- /**
- * @return true if the user configured the use of a network proxy
- */
- bool useProxy();
-
- /**
- * @return true if the user wants to see non-official plugins installed outside MO in his mod list
- */
- bool displayForeign();
-
- /**
- * @brief sets the new motd hash
- **/
- void setMotDHash(uint hash);
-
- /**
- * @return hash of the last displayed message of the day
- **/
- uint getMotDHash() const;
-
- /**
- * @brief allows direct access to the wrapped QSettings object
- * @return the wrapped QSettings object
- */
- QSettings &directInterface() { return m_Settings; }
-
- /**
- * @brief retrieve a setting for one of the installed plugins
- * @param pluginName name of the plugin
- * @param key name of the setting to retrieve
- * @return the requested value as a QVariant
- * @note an invalid QVariant is returned if the the plugin/setting is not declared
- */
- QVariant pluginSetting(const QString &pluginName, const QString &key) const;
-
- /**
- * @brief set a setting for one of the installed mods
- * @param pluginName name of the plugin
- * @param key name of the setting to change
- * @param value the new value to set
- * @throw an exception is thrown if pluginName is invalid
- */
- void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
-
- /**
- * @brief retrieve a persistent value for a plugin
- * @param pluginName name of the plugin to store data for
- * @param key id of the value to retrieve
- * @param def default value to return if the value is not set
- * @return the requested value
- */
- QVariant pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const;
-
- /**
- * @brief set a persistent value for a plugin
- * @param pluginName name of the plugin to store data for
- * @param key id of the value to retrieve
- * @param value value to set
- * @throw an exception is thrown if pluginName is invalid
- */
- void setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
-
- /**
- * @return short code of the configured language (corresponding to the translation files)
- */
- QString language();
-
- /**
- * @brief updates the list of known servers
- * @param list of servers from a recent query
- */
- void updateServers(const QList<ServerInfo> &servers);
-
- /**
- * @brief add a plugin that is to be blacklisted
- * @param fileName name of the plugin to blacklist
- */
- void addBlacklistPlugin(const QString &fileName);
-
- /**
- * @brief test if a plugin is blacklisted and shouldn't be loaded
- * @param fileName name of the plugin
- * @return true if the file is blacklisted
- */
- bool pluginBlacklisted(const QString &fileName) const;
-
- /**
- * @return all loaded MO plugins
- */
- std::vector<MOBase::IPlugin*> plugins() const { return m_Plugins; }
-
- /**
- * @brief register MO as the handler for nxm links
- * @param force set to true to enforce the registration dialog to show up,
- * even if the user said earlier not to
- */
- void registerAsNXMHandler(bool force);
-private:
-
- QString obfuscate(const QString &password) const;
- QString deObfuscate(const QString &password) const;
-
- void addLanguages(QComboBox *languageBox);
- void addStyles(QComboBox *styleBox);
- void readPluginBlacklist();
- void writePluginBlacklist();
-
-private slots:
-
- void resetDialogs();
-
-signals:
-
- void languageChanged(const QString &newLanguage);
- void styleChanged(const QString &newStyle);
-
-private:
-
- static Settings *s_Instance;
-
- QSettings m_Settings;
-
- LoadMechanism m_LoadMechanism;
-
- std::vector<MOBase::IPlugin*> m_Plugins;
-
- QMap<QString, QMap<QString, QVariant> > m_PluginSettings;
-
- QSet<QString> m_PluginBlacklist;
-
-};
-
-#endif // WORKAROUNDS_H
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef WORKAROUNDS_H +#define WORKAROUNDS_H + +#include "loadmechanism.h" +#include "serverinfo.h" +#include <iplugin.h> + +#include <QSettings> +#include <QListWidget> +#include <QComboBox> + + +/** + * manages the settings for Mod Organizer. The settings are not cached + * inside the class but read/written directly from/to disc + **/ +class Settings : public QObject +{ + + Q_OBJECT + +public: + + /** + * @brief constructor + **/ + Settings(); + + virtual ~Settings(); + + static Settings &instance(); + + /** + * unregister all plugins from settings + */ + void clearPlugins(); + + /** + * @brief register plugin to be configurable + * @param plugin the plugin to register + * @return true if the plugin may be registered, false if it is blacklisted + */ + void registerPlugin(MOBase::IPlugin *plugin); + + /** + * 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); + + /** + * set up the settings for the specified plugins + **/ + void addPluginSettings(const std::vector<MOBase::IPlugin*> &plugins); + + /** + * @return true if the user wants unchecked plugins (esp, esm) should be hidden from + * the virtual dat adirectory + **/ + bool hideUncheckedPlugins() const; + + /** + * @return true if files of the core game are forced-enabled so the user can't accidentally disable them + */ + bool forceEnableCoreFiles() const; + + /** + * @brief register download speed + * @param url complete download url + * @param bytesPerSecond download size in bytes per second + */ + void setDownloadSpeed(const QString &serverName, int bytesPerSecond); + + /** + * the steam appid is assigned by the steam platform to each product sold there. + * The appid may differ between different versions of a game so it may be impossible + * for Mod Organizer to automatically recognize it, though usually it does + * @return the steam appid for the game + **/ + QString getSteamAppID() const; + + /** + * retrieve the directory where downloads are stored (with native separators) + **/ + QString getDownloadDirectory() const; + + /** + * retrieve a sorted list of preferred servers + */ + std::map<QString, int> getPreferredServers(); + + /** + * retrieve the directory where mods are stored (with native separators) + **/ + QString getModDirectory() const; + + /** + * returns the version of nmm to impersonate when connecting to nexus + **/ + QString getNMMVersion() const; + + /** + * retrieve the directory where the web cache is stored (with native separators) + **/ + QString getCacheDirectory() const; + + /** + * @return true if the user has set up automatic login to nexus + **/ + bool automaticLoginEnabled() const; + + /** + * @brief retrieve the login information for nexus + * + * @param username (out) receives the user name for nexus + * @param password (out) received the password for nexus + * @return true if automatic login is active, false otherwise + **/ + bool getNexusLogin(QString &username, QString &password) const; + + /** + * @return true if the user disabled internet features + */ + bool offlineMode() const; + + /** + * @return true if the user chose compact downloads + */ + bool compactDownloads() const; + + /** + * @return true if the user chose meta downloads + */ + bool metaDownloads() const; + + /** + * @return the configured log level + */ + int logLevel() const; + + /** + * @brief set the nexus login information + * + * @param username username + * @param password password + */ + void setNexusLogin(QString username, QString password); + + /** + * @return the load mechanism to be used + **/ + LoadMechanism::EMechanism getLoadMechanism() const; + + /** + * @brief activate the load mechanism selected by the user + **/ + void setupLoadMechanism(); + + /** + * @return true if the user configured the use of a network proxy + */ + bool useProxy(); + + /** + * @return true if the user wants to see non-official plugins installed outside MO in his mod list + */ + bool displayForeign(); + + /** + * @brief sets the new motd hash + **/ + void setMotDHash(uint hash); + + /** + * @return hash of the last displayed message of the day + **/ + uint getMotDHash() const; + + /** + * @brief allows direct access to the wrapped QSettings object + * @return the wrapped QSettings object + */ + QSettings &directInterface() { return m_Settings; } + + /** + * @brief retrieve a setting for one of the installed plugins + * @param pluginName name of the plugin + * @param key name of the setting to retrieve + * @return the requested value as a QVariant + * @note an invalid QVariant is returned if the the plugin/setting is not declared + */ + QVariant pluginSetting(const QString &pluginName, const QString &key) const; + + /** + * @brief set a setting for one of the installed mods + * @param pluginName name of the plugin + * @param key name of the setting to change + * @param value the new value to set + * @throw an exception is thrown if pluginName is invalid + */ + void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value); + + /** + * @brief retrieve a persistent value for a plugin + * @param pluginName name of the plugin to store data for + * @param key id of the value to retrieve + * @param def default value to return if the value is not set + * @return the requested value + */ + QVariant pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const; + + /** + * @brief set a persistent value for a plugin + * @param pluginName name of the plugin to store data for + * @param key id of the value to retrieve + * @param value value to set + * @throw an exception is thrown if pluginName is invalid + */ + void setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync); + + /** + * @return short code of the configured language (corresponding to the translation files) + */ + QString language(); + + /** + * @brief updates the list of known servers + * @param list of servers from a recent query + */ + void updateServers(const QList<ServerInfo> &servers); + + /** + * @brief add a plugin that is to be blacklisted + * @param fileName name of the plugin to blacklist + */ + void addBlacklistPlugin(const QString &fileName); + + /** + * @brief test if a plugin is blacklisted and shouldn't be loaded + * @param fileName name of the plugin + * @return true if the file is blacklisted + */ + bool pluginBlacklisted(const QString &fileName) const; + + /** + * @return all loaded MO plugins + */ + std::vector<MOBase::IPlugin*> plugins() const { return m_Plugins; } + + /** + * @brief register MO as the handler for nxm links + * @param force set to true to enforce the registration dialog to show up, + * even if the user said earlier not to + */ + void registerAsNXMHandler(bool force); +private: + + QString obfuscate(const QString &password) const; + QString deObfuscate(const QString &password) const; + + void addLanguages(QComboBox *languageBox); + void addStyles(QComboBox *styleBox); + void readPluginBlacklist(); + void writePluginBlacklist(); + +private slots: + + void resetDialogs(); + +signals: + + void languageChanged(const QString &newLanguage); + void styleChanged(const QString &newStyle); + +private: + + static Settings *s_Instance; + + QSettings m_Settings; + + LoadMechanism m_LoadMechanism; + + std::vector<MOBase::IPlugin*> m_Plugins; + + QMap<QString, QMap<QString, QVariant> > m_PluginSettings; + QMap<QString, QMap<QString, QVariant> > m_PluginDescriptions; + + QSet<QString> m_PluginBlacklist; + +}; + +#endif // WORKAROUNDS_H diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index a7d44d72..d1947b5a 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -1,173 +1,182 @@ -/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer 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. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "settingsdialog.h"
-#include "ui_settingsdialog.h"
-#include "categoriesdialog.h"
-#include "helper.h"
-#include "noeditdelegate.h"
-#include <gameinfo.h>
-#include <QDirIterator>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QShortcut>
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include "settings.h"
-
-
-using namespace MOBase;
-using namespace MOShared;
-
-
-SettingsDialog::SettingsDialog(QWidget *parent)
- : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog)
-{
- ui->setupUi(this);
-
- QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist);
- connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem()));
-}
-
-SettingsDialog::~SettingsDialog()
-{
- delete ui;
-}
-
-void SettingsDialog::addPlugins(const std::vector<IPlugin*> &plugins)
-{
- foreach (IPlugin *plugin, plugins) {
- ui->pluginsList->addItem(plugin->name());
- }
-}
-
-void SettingsDialog::accept()
-{
- storeSettings(ui->pluginsList->currentItem());
- TutorableDialog::accept();
-}
-
-
-void SettingsDialog::on_loginCheckBox_toggled(bool checked)
-{
- QLineEdit *usernameEdit = findChild<QLineEdit*>("usernameEdit");
- QLineEdit *passwordEdit = findChild<QLineEdit*>("passwordEdit");
- if (checked) {
- passwordEdit->setEnabled(true);
- usernameEdit->setEnabled(true);
- } else {
- passwordEdit->setEnabled(false);
- usernameEdit->setEnabled(false);
- }
-}
-
-void SettingsDialog::on_categoriesBtn_clicked()
-{
- CategoriesDialog dialog(this);
- if (dialog.exec() == QDialog::Accepted) {
- dialog.commitChanges();
- }
-}
-
-void SettingsDialog::on_bsaDateBtn_clicked()
-{
- Helper::backdateBSAs(GameInfo::instance().getOrganizerDirectory(), GameInfo::instance().getGameDirectory().append(L"\\data"));
-}
-
-void SettingsDialog::on_browseDownloadDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text());
- if (!temp.isEmpty()) {
- ui->downloadDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_browseModDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), ui->downloadDirEdit->text());
- if (!temp.isEmpty()) {
- ui->modDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_browseCacheDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), ui->cacheDirEdit->text());
- if (!temp.isEmpty()) {
- ui->cacheDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_resetDialogsButton_clicked()
-{
- if (QMessageBox::question(this, tr("Confirm?"),
- tr("This will make all dialogs show up again where you checked the \"Remember selection\"-box. Continue?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- emit resetDialogs();
- }
-}
-
-void SettingsDialog::storeSettings(QListWidgetItem *pluginItem)
-{
- if (pluginItem != NULL) {
- QMap<QString, QVariant> settings = pluginItem->data(Qt::UserRole + 1).toMap();
-
- for (int i = 0; i < ui->pluginSettingsList->topLevelItemCount(); ++i) {
- const QTreeWidgetItem *item = ui->pluginSettingsList->topLevelItem(i);
- settings[item->text(0)] = item->data(1, Qt::DisplayRole);
- }
-
- pluginItem->setData(Qt::UserRole + 1, settings);
- }
-}
-
-void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
-{
- storeSettings(previous);
-
- ui->pluginSettingsList->clear();
- IPlugin *plugin = static_cast<IPlugin*>(current->data(Qt::UserRole).value<void*>());
- ui->authorLabel->setText(plugin->author());
- ui->versionLabel->setText(plugin->version().canonicalString());
- ui->descriptionLabel->setText(plugin->description());
-
- QMap<QString, QVariant> settings = current->data(Qt::UserRole + 1).toMap();
- ui->pluginSettingsList->setEnabled(settings.count() != 0);
- for (auto iter = settings.begin(); iter != settings.end(); ++iter) {
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key()));
- QVariant value = *iter;
-
- ui->pluginSettingsList->setItemDelegateForColumn(0, new NoEditDelegate());
- newItem->setData(1, Qt::DisplayRole, value);
- newItem->setData(1, Qt::EditRole, value);
-
- newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
- ui->pluginSettingsList->addTopLevelItem(newItem);
- }
-}
-
-void SettingsDialog::deleteBlacklistItem()
-{
- ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row());
-}
-
-void SettingsDialog::on_associateButton_clicked()
-{
- Settings::instance().registerAsNXMHandler(true);
-}
+/* +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer 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. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "settingsdialog.h" +#include "ui_settingsdialog.h" +#include "categoriesdialog.h" +#include "helper.h" +#include "noeditdelegate.h" +#include <gameinfo.h> +#include <QDirIterator> +#include <QFileDialog> +#include <QMessageBox> +#include <QShortcut> +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> +#include "settings.h" + + +using namespace MOBase; +using namespace MOShared; + + +SettingsDialog::SettingsDialog(QWidget *parent) + : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog) +{ + ui->setupUi(this); + + QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist); + connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem())); +} + +SettingsDialog::~SettingsDialog() +{ + delete ui; +} + +void SettingsDialog::addPlugins(const std::vector<IPlugin*> &plugins) +{ + foreach (IPlugin *plugin, plugins) { + ui->pluginsList->addItem(plugin->name()); + } +} + +void SettingsDialog::accept() +{ + storeSettings(ui->pluginsList->currentItem()); + TutorableDialog::accept(); +} + + +void SettingsDialog::on_loginCheckBox_toggled(bool checked) +{ + QLineEdit *usernameEdit = findChild<QLineEdit*>("usernameEdit"); + QLineEdit *passwordEdit = findChild<QLineEdit*>("passwordEdit"); + if (checked) { + passwordEdit->setEnabled(true); + usernameEdit->setEnabled(true); + } else { + passwordEdit->setEnabled(false); + usernameEdit->setEnabled(false); + } +} + +void SettingsDialog::on_categoriesBtn_clicked() +{ + CategoriesDialog dialog(this); + if (dialog.exec() == QDialog::Accepted) { + dialog.commitChanges(); + } +} + +void SettingsDialog::on_bsaDateBtn_clicked() +{ + Helper::backdateBSAs(GameInfo::instance().getOrganizerDirectory(), GameInfo::instance().getGameDirectory().append(L"\\data")); +} + +void SettingsDialog::on_browseDownloadDirBtn_clicked() +{ + QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text()); + if (!temp.isEmpty()) { + ui->downloadDirEdit->setText(temp); + } +} + +void SettingsDialog::on_browseModDirBtn_clicked() +{ + QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), ui->downloadDirEdit->text()); + if (!temp.isEmpty()) { + ui->modDirEdit->setText(temp); + } +} + +void SettingsDialog::on_browseCacheDirBtn_clicked() +{ + QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), ui->cacheDirEdit->text()); + if (!temp.isEmpty()) { + ui->cacheDirEdit->setText(temp); + } +} + +void SettingsDialog::on_resetDialogsButton_clicked() +{ + if (QMessageBox::question(this, tr("Confirm?"), + tr("This will make all dialogs show up again where you checked the \"Remember selection\"-box. Continue?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + emit resetDialogs(); + } +} + +void SettingsDialog::storeSettings(QListWidgetItem *pluginItem) +{ + if (pluginItem != NULL) { + QMap<QString, QVariant> settings = pluginItem->data(Qt::UserRole + 1).toMap(); + + for (int i = 0; i < ui->pluginSettingsList->topLevelItemCount(); ++i) { + const QTreeWidgetItem *item = ui->pluginSettingsList->topLevelItem(i); + settings[item->text(0)] = item->data(1, Qt::DisplayRole); + } + + pluginItem->setData(Qt::UserRole + 1, settings); + } +} + +void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) +{ + storeSettings(previous); + + ui->pluginSettingsList->clear(); + IPlugin *plugin = static_cast<IPlugin*>(current->data(Qt::UserRole).value<void*>()); + ui->authorLabel->setText(plugin->author()); + ui->versionLabel->setText(plugin->version().canonicalString()); + ui->descriptionLabel->setText(plugin->description()); + + QMap<QString, QVariant> settings = current->data(Qt::UserRole + 1).toMap(); + QMap<QString, QVariant> descriptions = current->data(Qt::UserRole + 2).toMap(); + ui->pluginSettingsList->setEnabled(settings.count() != 0); + for (auto iter = settings.begin(); iter != settings.end(); ++iter) { + QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key())); + QVariant value = *iter; + QString description; + { + auto descriptionIter = descriptions.find(iter.key()); + if (descriptionIter != descriptions.end()) { + description = descriptionIter->toString(); + } + } + + ui->pluginSettingsList->setItemDelegateForColumn(0, new NoEditDelegate()); + newItem->setData(1, Qt::DisplayRole, value); + newItem->setData(1, Qt::EditRole, value); + newItem->setToolTip(1, description); + + newItem->setFlags(newItem->flags() | Qt::ItemIsEditable); + ui->pluginSettingsList->addTopLevelItem(newItem); + } +} + +void SettingsDialog::deleteBlacklistItem() +{ + ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row()); +} + +void SettingsDialog::on_associateButton_clicked() +{ + Settings::instance().registerAsNXMHandler(true); +} diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index e0914870..0adf0812 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -72,8 +72,7 @@ public: }
bool exists(const std::wstring &name) {
- std::map<std::wstring, int>::iterator iter = m_OriginsNameMap.find(name);
- return iter != m_OriginsNameMap.end();
+ return m_OriginsNameMap.find(name) != m_OriginsNameMap.end();
}
FilesOrigin &getByID(Index ID) {
@@ -325,13 +324,13 @@ static bool ByOriginPriority(DirectoryEntry *entry, int LHS, int RHS) FileEntry::FileEntry()
- : m_Index(UINT_MAX), m_Name(), m_Parent(NULL), m_LastAccessed(time(NULL))
+ : m_Index(UINT_MAX), m_Name(), m_Origin(-1), m_Parent(NULL), m_LastAccessed(time(NULL))
{
LEAK_TRACE;
}
FileEntry::FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent)
- : m_Index(index), m_Name(name), m_Parent(parent), m_Origin(-1), m_Archive(L""), m_LastAccessed(time(NULL))
+ : m_Index(index), m_Name(name), m_Origin(-1), m_Parent(parent), m_Archive(L""), m_LastAccessed(time(NULL))
{
LEAK_TRACE;
}
@@ -369,16 +368,14 @@ std::wstring FileEntry::getFullPath() const bool ignore = false;
result = m_Parent->getOriginByID(getOrigin(ignore)).getPath(); //base directory for origin
recurseParents(result, m_Parent); // all intermediate directories
- result.append(L"\\").append(m_Name); // the actual filename
- return result;
+ return result + L"\\" + m_Name;
}
std::wstring FileEntry::getRelativePath() const
{
std::wstring result;
recurseParents(result, m_Parent); // all intermediate directories
- result.append(L"\\").append(m_Name); // the actual filename
- return result;
+ return result + L"\\" + m_Name;
}
@@ -446,6 +443,7 @@ void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::ws boost::scoped_array<wchar_t> buffer(new wchar_t[MAXPATH_UNICODE + 1]);
memset(buffer.get(), L'\0', MAXPATH_UNICODE + 1);
int offset = _snwprintf(buffer.get(), MAXPATH_UNICODE, L"%ls", directory.c_str());
+ buffer.get()[offset] = L'\0';
addFiles(origin, buffer.get(), offset);
}
m_Populated = true;
@@ -636,7 +634,7 @@ void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origi void DirectoryEntry::removeFile(FileEntry::Index index)
{
- if (m_Files.size() != 0) {
+ if (!m_Files.empty()) {
auto iter = std::find_if(m_Files.begin(), m_Files.end(),
[&index](const std::pair<std::wstring, FileEntry::Index> &iter) -> bool {
return iter.second == index; } );
@@ -936,10 +934,6 @@ void FileRegister::removeOriginMulti(std::set<FileEntry::Index> indices, int ori }
}
- if (removedFiles.size() > 0) {
- log("%d files actually removed", removedFiles.size());
- }
-
// optimization: this is only called when disabling an origin and in this case we don't have
// to remove the file from the origin
diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 7836d719..d588ab02 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -29,8 +29,10 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #define WIN32_MEAN_AND_LEAN
#include <Windows.h>
#include <bsatk.h>
+#ifndef Q_MOC_RUN
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
+#endif
#include "util.h"
@@ -217,7 +219,7 @@ public: void clear();
bool isPopulated() const { return m_Populated; }
- bool isEmpty() const { return (m_Files.size() == 0) && (m_SubDirectories.size() == 0); }
+ bool isEmpty() const { return m_Files.empty() && m_SubDirectories.empty(); }
const DirectoryEntry *getParent() const { return m_Parent; }
diff --git a/src/shared/fallout3info.cpp b/src/shared/fallout3info.cpp index 9487d2de..82b285b7 100644 --- a/src/shared/fallout3info.cpp +++ b/src/shared/fallout3info.cpp @@ -54,15 +54,17 @@ std::wstring Fallout3Info::getRegPathStatic() 0, KEY_QUERY_VALUE, &key);
if (errorcode != ERROR_SUCCESS) {
- return L"";
+ return std::wstring();
}
WCHAR temp[MAX_PATH];
DWORD bufferSize = MAX_PATH;
- errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize);
-
- return std::wstring(temp);
+ if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
+ return std::wstring(temp);
+ } else {
+ return std::wstring();
+ }
}
std::wstring Fallout3Info::getInvalidationBSA()
@@ -233,15 +235,12 @@ void Fallout3Info::createProfile(const std::wstring &directory, bool useDefaults }
}
{ // copy falloutprefs.ini-file
- std::wstring target = directory.substr().append(L"\\falloutprefs.ini");
+ std::wstring target = directory + L"\\falloutprefs.ini";
if (!FileExists(target)) {
- std::wostringstream source;
- source << getMyGamesDirectory() << L"\\Fallout3\\falloutprefs.ini";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+ std::wstring source = getMyGamesDirectory() + L"\\Fallout3\\falloutprefs.ini";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
+ throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false));
}
}
}
@@ -268,7 +267,7 @@ bool Fallout3Info::rerouteToProfile(const wchar_t *fileName, const wchar_t*) }
-std::vector<ExecutableInfo> Fallout3Info::getExecutables()
+/*std::vector<ExecutableInfo> Fallout3Info::getExecutables()
{
std::vector<ExecutableInfo> result;
result.push_back(ExecutableInfo(L"FOSE", L"fose_loader.exe", L"", L"", DEFAULT_CLOSE));
@@ -279,5 +278,5 @@ std::vector<ExecutableInfo> Fallout3Info::getExecutables() result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE));
return result;
-}
+}*/
} // namespace MOShared
diff --git a/src/shared/fallout3info.h b/src/shared/fallout3info.h index 8e4c260d..7e39cce4 100644 --- a/src/shared/fallout3info.h +++ b/src/shared/fallout3info.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion();
static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() { return Fallout3Info::getRegPathStatic(); }
+ virtual std::wstring getRegPath() { return getRegPathStatic(); }
virtual std::wstring getBinaryName() { return L"Fallout3.exe"; }
virtual GameInfo::Type getType() { return TYPE_FALLOUT3; }
@@ -75,9 +75,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
- virtual std::wstring getNexusInfoUrl() { return Fallout3Info::getNexusInfoUrlStatic(); }
+ virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
- virtual int getNexusModID() { return Fallout3Info::getNexusModIDStatic(); }
+ virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 120; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
@@ -87,7 +87,7 @@ public: // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
// the game directory
- virtual std::vector<ExecutableInfo> getExecutables();
+ //virtual std::vector<ExecutableInfo> getExecutables();
virtual std::wstring archiveListKey() { return L"SArchiveList"; }
diff --git a/src/shared/falloutnvinfo.cpp b/src/shared/falloutnvinfo.cpp index 9bba7fe4..178ce8b4 100644 --- a/src/shared/falloutnvinfo.cpp +++ b/src/shared/falloutnvinfo.cpp @@ -55,15 +55,17 @@ std::wstring FalloutNVInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key);
if (errorcode != ERROR_SUCCESS) {
- return L"";
+ return std::wstring();
}
WCHAR temp[MAX_PATH];
DWORD bufferSize = MAX_PATH;
- errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize);
-
- return std::wstring(temp);
+ if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
+ return std::wstring(temp);
+ } else {
+ return std::wstring();
+ }
}
std::wstring FalloutNVInfo::getInvalidationBSA()
@@ -162,56 +164,46 @@ std::wstring FalloutNVInfo::getSteamAPPId(int) const void FalloutNVInfo::createProfile(const std::wstring &directory, bool useDefaults)
{
- std::wostringstream target;
+ std::wstring target = directory + L"\\plugins.txt";
// copy plugins.txt
- target << directory << "\\plugins.txt";
-
- if (!FileExists(target.str())) {
- std::wostringstream source;
- source << getLocalAppFolder() << "\\FalloutNV\\plugins.txt";
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
- HANDLE file = ::CreateFileW(target.str().c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (!FileExists(target)) {
+ std::wstring source = getLocalAppFolder() + L"\\FalloutNV\\plugins.txt";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
+ HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
::CloseHandle(file);
}
}
// copy ini-file
- target.str(L""); target.clear();
- target << directory << L"\\fallout.ini";
+ target = directory + L"\\fallout.ini";
- if (!FileExists(target.str())) {
- std::wostringstream source;
+ if (!FileExists(target)) {
+ std::wstring source;
if (useDefaults) {
- source << getGameDirectory() << L"\\fallout_default.ini";
+ source = getGameDirectory() + L"\\fallout_default.ini";
} else {
- source << getMyGamesDirectory() << L"\\FalloutNV";
- if (FileExists(source.str(), L"fallout.ini")) {
- source << L"\\fallout.ini";
+ source = getMyGamesDirectory() + L"\\FalloutNV";
+ if (FileExists(source, L"fallout.ini")) {
+ source += L"\\fallout.ini";
} else {
- source.str(L"");
- source << getGameDirectory() << L"\\fallout_default.ini";
+ source = getGameDirectory() + L"\\fallout_default.ini";
}
}
- if (!::CopyFileW(source.str().c_str(), target.str().c_str(), true)) {
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
+ throw windows_error("failed to copy ini file: " + ToString(source, false));
}
}
}
{ // copy falloutprefs.ini-file
- std::wstring target = directory.substr().append(L"\\falloutprefs.ini");
+ std::wstring target = directory + L"\\falloutprefs.ini";
if (!FileExists(target)) {
- std::wostringstream source;
- source << getMyGamesDirectory() << L"\\FalloutNV\\falloutprefs.ini";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+ std::wstring source = getMyGamesDirectory() + L"\\FalloutNV\\falloutprefs.ini";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
+ throw windows_error("failed to copy ini file: " + ToString(source, false));
}
}
}
@@ -265,7 +257,7 @@ bool FalloutNVInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t*) return false;
}
-
+/*
std::vector<ExecutableInfo> FalloutNVInfo::getExecutables()
{
std::vector<ExecutableInfo> result;
@@ -277,5 +269,5 @@ std::vector<ExecutableInfo> FalloutNVInfo::getExecutables() result.push_back(ExecutableInfo(L"BOSS", L"BOSS/BOSS.exe", L"", L"", NEVER_CLOSE));
return result;
-}
+}*/
} // namespace MOShared
diff --git a/src/shared/falloutnvinfo.h b/src/shared/falloutnvinfo.h index cfd373c7..231311de 100644 --- a/src/shared/falloutnvinfo.h +++ b/src/shared/falloutnvinfo.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion();
static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() { return FalloutNVInfo::getRegPathStatic(); }
+ virtual std::wstring getRegPath() { return getRegPathStatic(); }
virtual std::wstring getBinaryName() { return L"FalloutNV.exe"; }
virtual GameInfo::Type getType() { return TYPE_FALLOUTNV; }
@@ -76,9 +76,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
- virtual std::wstring getNexusInfoUrl() { return FalloutNVInfo::getNexusInfoUrlStatic(); }
+ virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
- virtual int getNexusModID() { return FalloutNVInfo::getNexusModIDStatic(); }
+ virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 130; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
@@ -88,7 +88,7 @@ public: // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
// the game directory
- virtual std::vector<ExecutableInfo> getExecutables();
+ //virtual std::vector<ExecutableInfo> getExecutables();
virtual std::wstring archiveListKey() { return L"SArchiveList"; }
diff --git a/src/shared/gameinfo.cpp b/src/shared/gameinfo.cpp index 21e9a586..5439efff 100644 --- a/src/shared/gameinfo.cpp +++ b/src/shared/gameinfo.cpp @@ -57,7 +57,7 @@ void GameInfo::identifyMyGamesDirectory(const std::wstring &file) {
// this function attempts 3 (three!) ways to determine the correct "My Games" folder.
wchar_t myDocuments[MAX_PATH];
- memset(myDocuments, '\0', MAX_PATH);
+ memset(myDocuments, '\0', MAX_PATH * sizeof(wchar_t));
m_MyGamesDirectory.clear();
@@ -137,71 +137,53 @@ std::wstring GameInfo::getGameDirectory() const std::wstring GameInfo::getModsDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << L"\\mods";
- return temp.str();
+ return m_OrganizerDirectory + L"\\mods";
}
std::wstring GameInfo::getProfilesDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << L"\\profiles";
- return temp.str();
+ return m_OrganizerDirectory + L"\\profiles";
}
std::wstring GameInfo::getIniFilename() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << L"\\ModOrganizer.ini";
- return temp.str();
+ return m_OrganizerDirectory + L"\\ModOrganizer.ini";
}
std::wstring GameInfo::getDownloadDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << L"\\downloads";
- return temp.str();
+ return m_OrganizerDirectory + L"\\downloads";
}
std::wstring GameInfo::getCacheDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << L"\\webcache";
- return temp.str();
+ return m_OrganizerDirectory + L"\\webcache";
}
std::wstring GameInfo::getOverwriteDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << "\\overwrite";
- return temp.str();
+ return m_OrganizerDirectory + L"\\overwrite";
}
std::wstring GameInfo::getLogDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDataDirectory << "\\logs";
- return temp.str();
+ return m_OrganizerDirectory + L"\\logs";
}
std::wstring GameInfo::getLootDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDirectory << "\\loot";
- return temp.str();
+ return m_OrganizerDirectory + L"\\loot";
}
std::wstring GameInfo::getTutorialDir() const
{
- std::wostringstream temp;
- temp << m_OrganizerDirectory << "\\tutorials";
- return temp.str();
+ return m_OrganizerDirectory + L"\\tutorials";
}
@@ -219,7 +201,7 @@ std::vector<std::wstring> GameInfo::getSteamVariants() const std::wstring GameInfo::getLocalAppFolder() const
{
wchar_t localAppFolder[MAX_PATH];
- memset(localAppFolder, '\0', MAX_PATH);
+ memset(localAppFolder, '\0', MAX_PATH * sizeof(wchar_t));
if (::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, localAppFolder) == S_OK) {
return localAppFolder;
diff --git a/src/shared/gameinfo.h b/src/shared/gameinfo.h index d719a073..c11679f3 100644 --- a/src/shared/gameinfo.h +++ b/src/shared/gameinfo.h @@ -28,7 +28,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <Windows.h>
namespace MOShared {
-
+/*
enum CloseMOStyle {
DEFAULT_CLOSE,
DEFAULT_STAY,
@@ -53,7 +53,7 @@ struct ExecutableInfo { CloseMOStyle closeMO;
std::wstring steamAppID;
};
-
+*/
/**
Class to manage information that depends on the used game type. The intention is to keep
@@ -160,13 +160,9 @@ public: virtual bool rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPath) = 0;
- // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
- // the game directory. the boolean says whether omo should be closed when the executable is started
- virtual std::vector<ExecutableInfo> getExecutables() = 0;
-
public:
- // initialise with the path to the omo directory (needs to be where hook.dll is stored). This
+ // initialise with the path to the mo directory (needs to be where hook.dll is stored). This
// needs to be called before the instance can be retrieved
static bool init(const std::wstring &moDirectory, const std::wstring &moDataDirectory, const std::wstring &gamePath = L"");
diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index 68e57609..729eb42e 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -36,7 +36,7 @@ class StackData { public:
StackData()
- : m_FunctionName("Dummy"), m_CodeLine(0)
+ : m_Count(0), m_Hash(0UL), m_FunctionName("Dummy"), m_CodeLine(0)
{}
StackData(const char *functionName, int line) {
m_Count = ::CaptureStackBackTrace(FRAMES_TO_SKIP, FRAMES_TO_CAPTURE, m_Stack, &m_Hash);
diff --git a/src/shared/oblivioninfo.cpp b/src/shared/oblivioninfo.cpp index f317812f..89a795a5 100644 --- a/src/shared/oblivioninfo.cpp +++ b/src/shared/oblivioninfo.cpp @@ -55,15 +55,17 @@ std::wstring OblivionInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key);
if (errorcode != ERROR_SUCCESS) {
- return L"";
+ return std::wstring();
}
WCHAR temp[MAX_PATH];
DWORD bufferSize = MAX_PATH;
- errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize);
-
- return std::wstring(temp);
+ if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
+ return std::wstring(temp);
+ } else {
+ return std::wstring();
+ }
}
std::wstring OblivionInfo::getInvalidationBSA()
@@ -188,16 +190,13 @@ void OblivionInfo::createProfile(const std::wstring &directory, bool useDefaults }
{ // copy oblivionprefs.ini-file
- std::wstring target = directory.substr().append(L"\\oblivionprefs.ini");
+ std::wstring target = directory + L"\\oblivionprefs.ini";
if (!FileExists(target)) {
- std::wostringstream source;
- source << getMyGamesDirectory() << L"\\Oblivion\\oblivionprefs.ini";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+ std::wstring source = getMyGamesDirectory() + L"\\Oblivion\\oblivionprefs.ini";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
if ((::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL) == INVALID_HANDLE_VALUE) &&
(::GetLastError() != ERROR_FILE_EXISTS)) {
- std::ostringstream stream;
- stream << "failed to create ini file: " << ToString(target.c_str(), false);
- throw windows_error(stream.str());
+ throw windows_error(std::string("failed to create ini file: ") + ToString(target, false));
}
}
}
@@ -274,7 +273,7 @@ std::wstring OblivionInfo::getSteamAPPId(int) const return L"22330";
}
-
+/*
std::vector<ExecutableInfo> OblivionInfo::getExecutables()
{
std::vector<ExecutableInfo> result;
@@ -287,5 +286,5 @@ std::vector<ExecutableInfo> OblivionInfo::getExecutables() result.push_back(ExecutableInfo(L"BOSS (old)", L"Data/BOSS.exe", L"", L"", NEVER_CLOSE));
return result;
-}
+}*/
} // namespace MOShared
diff --git a/src/shared/oblivioninfo.h b/src/shared/oblivioninfo.h index 02fd90b4..cb506c01 100644 --- a/src/shared/oblivioninfo.h +++ b/src/shared/oblivioninfo.h @@ -36,7 +36,7 @@ public: virtual unsigned long getBSAVersion();
static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() { return OblivionInfo::getRegPathStatic(); }
+ virtual std::wstring getRegPath() { return getRegPathStatic(); }
virtual std::wstring getBinaryName() { return L"Oblivion.exe"; }
virtual GameInfo::Type getType() { return TYPE_OBLIVION; }
@@ -72,9 +72,9 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
- virtual std::wstring getNexusInfoUrl() { return OblivionInfo::getNexusInfoUrlStatic(); }
+ virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
- virtual int getNexusModID() { return OblivionInfo::getNexusModIDStatic(); }
+ virtual int getNexusModID() { return getNexusModIDStatic(); }
virtual int getNexusGameID() { return 101; }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
@@ -84,7 +84,7 @@ public: // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
// the game directory
- virtual std::vector<ExecutableInfo> getExecutables();
+ //virtual std::vector<ExecutableInfo> getExecutables();
virtual std::wstring archiveListKey() { return L"SArchiveList"; }
diff --git a/src/shared/shared.pro b/src/shared/shared.pro index 84a9c274..69f6f2e6 100644 --- a/src/shared/shared.pro +++ b/src/shared/shared.pro @@ -11,33 +11,11 @@ TARGET = mo_shared TEMPLATE = lib
CONFIG += staticlib
-INCLUDEPATH += ../bsatk "$(BOOSTPATH)"
-
-# only for custom leak detection
-DEFINES += TRACE_LEAKS
-LIBS += -lDbgHelp
-
-
-CONFIG(debug, debug|release) {
- LIBS += -L$$OUT_PWD/../bsatk/debug
- LIBS += -lDbgHelp
- QMAKE_CXXFLAGS_DEBUG -= -Zi
- QMAKE_CXXFLAGS += -Z7
- PRE_TARGETDEPS += $$OUT_PWD/../bsatk/debug/bsatk.lib
-} else {
- LIBS += -L$$OUT_PWD/../bsatk/release
- PRE_TARGETDEPS += $$OUT_PWD/../bsatk/release/bsatk.lib
+!include(../LocalPaths.pri) {
+ message("paths to required libraries need to be set up in LocalPaths.pri")
}
-LIBS += -lbsatk
-
-DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS
-
-DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
-
-# QMAKE_CXXFLAGS += /analyze
-
SOURCES += \
inject.cpp \
windows_error.cpp \
@@ -66,3 +44,30 @@ HEADERS += \ appconfig.h \
appconfig.inc \
leaktrace.h
+
+
+# only for custom leak detection
+DEFINES += TRACE_LEAKS
+LIBS += -lDbgHelp
+
+
+CONFIG(debug, debug|release) {
+ LIBS += -L$$OUT_PWD/../bsatk/debug
+ LIBS += -lDbgHelp
+ QMAKE_CXXFLAGS_DEBUG -= -Zi
+ QMAKE_CXXFLAGS += -Z7
+ PRE_TARGETDEPS += $$OUT_PWD/../bsatk/debug/bsatk.lib
+} else {
+ LIBS += -L$$OUT_PWD/../bsatk/release
+ PRE_TARGETDEPS += $$OUT_PWD/../bsatk/release/bsatk.lib
+}
+
+LIBS += -lbsatk
+
+DEFINES += UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS
+
+DEFINES += BOOST_DISABLE_ASSERTS NDEBUG
+
+# QMAKE_CXXFLAGS += /analyze
+
+INCLUDEPATH += ../bsatk "$${BOOSTPATH}"
diff --git a/src/shared/skyriminfo.cpp b/src/shared/skyriminfo.cpp index c985fe9f..1203e3ed 100644 --- a/src/shared/skyriminfo.cpp +++ b/src/shared/skyriminfo.cpp @@ -63,15 +63,17 @@ std::wstring SkyrimInfo::getRegPathStatic() 0, KEY_QUERY_VALUE, &key);
if (errorcode != ERROR_SUCCESS) {
- return L"";
+ return std::wstring();
}
WCHAR temp[MAX_PATH];
DWORD bufferSize = MAX_PATH;
- errorcode = ::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize);
-
- return std::wstring(temp);
+ if (::RegQueryValueExW(key, L"Installed Path", NULL, NULL, (LPBYTE)temp, &bufferSize) == ERROR_SUCCESS) {
+ return std::wstring(temp);
+ } else {
+ return std::wstring();
+ }
}
@@ -222,7 +224,7 @@ int SkyrimInfo::getNexusModIDStatic() void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults)
{
{ // copy plugins.txt
- std::wstring target = directory.substr().append(L"\\plugins.txt");
+ std::wstring target = directory + L"\\plugins.txt";
if (!FileExists(target)) {
std::wostringstream source;
source << getLocalAppFolder() << "\\Skyrim\\plugins.txt";
@@ -231,11 +233,10 @@ void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults) ::CloseHandle(file);
}
}
- target = directory.substr().append(L"\\loadorder.txt");
+ target = directory + L"\\loadorder.txt";
if (!FileExists(target)) {
- std::wostringstream source;
- source << getLocalAppFolder() << "\\Skyrim\\loadorder.txt";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+ std::wstring source = getLocalAppFolder() + L"\\Skyrim\\loadorder.txt";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
HANDLE file = ::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
::CloseHandle(file);
}
@@ -243,42 +244,36 @@ void SkyrimInfo::createProfile(const std::wstring &directory, bool useDefaults) }
{ // copy skyrim.ini-file
- std::wstring target = directory.substr().append(L"\\skyrim.ini");
+ std::wstring target = directory + L"\\skyrim.ini";
if (!FileExists(target)) {
- std::wostringstream source;
+ std::wstring source;
if (useDefaults) {
- source << getGameDirectory() << L"\\skyrim_default.ini";
+ source = getGameDirectory() + L"\\skyrim_default.ini";
} else {
- source << getMyGamesDirectory() << L"\\Skyrim";
- if (FileExists(source.str(), L"skyrim.ini")) {
- source << L"\\skyrim.ini";
+ source = getMyGamesDirectory() + L"\\Skyrim";
+ if (FileExists(source, L"skyrim.ini")) {
+ source += L"\\skyrim.ini";
} else {
- source.str(L"");
- source << getGameDirectory() << L"\\skyrim_default.ini";
+ source = getGameDirectory() + L"\\skyrim_default.ini";
}
}
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
if (::GetLastError() != ERROR_FILE_EXISTS) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
+ throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false));
}
}
}
}
{ // copy skyrimprefs.ini-file
- std::wstring target = directory.substr().append(L"\\skyrimprefs.ini");
+ std::wstring target = directory + L"\\skyrimprefs.ini";
if (!FileExists(target)) {
- std::wostringstream source;
- source << getMyGamesDirectory() << L"\\Skyrim\\skyrimprefs.ini";
- if (!::CopyFileW(source.str().c_str(), target.c_str(), true)) {
- log("failed to copy ini file %ls", source.str().c_str());
+ std::wstring source = getMyGamesDirectory() + L"\\Skyrim\\skyrimprefs.ini";
+ if (!::CopyFileW(source.c_str(), target.c_str(), true)) {
+ log("failed to copy ini file %ls", source.c_str());
// create empty
if (::CreateFileW(target.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) == INVALID_HANDLE_VALUE) {
- std::ostringstream stream;
- stream << "failed to copy ini file: " << ToString(source.str(), false);
- throw windows_error(stream.str());
+ throw windows_error(std::string("failed to copy ini file: ") + ToString(source, false));
}
}
}
@@ -311,7 +306,7 @@ bool SkyrimInfo::rerouteToProfile(const wchar_t *fileName, const wchar_t *fullPa }
-std::vector<ExecutableInfo> SkyrimInfo::getExecutables()
+/*std::vector<ExecutableInfo> SkyrimInfo::getExecutables()
{
std::vector<ExecutableInfo> result;
result.push_back(ExecutableInfo(L"SKSE", L"skse_loader.exe", L"", L"", DEFAULT_CLOSE));
@@ -322,6 +317,6 @@ std::vector<ExecutableInfo> SkyrimInfo::getExecutables() result.push_back(ExecutableInfo(L"Creation Kit", L"CreationKit.exe", L"", L"", DEFAULT_STAY, L"202480"));
return result;
-}
+}*/
} // namespace MOShared
diff --git a/src/shared/skyriminfo.h b/src/shared/skyriminfo.h index 132f2aee..ad6ab95d 100644 --- a/src/shared/skyriminfo.h +++ b/src/shared/skyriminfo.h @@ -38,7 +38,7 @@ public: virtual unsigned long getBSAVersion();
static std::wstring getRegPathStatic();
- virtual std::wstring getRegPath() { return SkyrimInfo::getRegPathStatic(); }
+ virtual std::wstring getRegPath() { return getRegPathStatic(); }
virtual std::wstring getBinaryName() { return L"TESV.exe"; }
virtual GameInfo::Type getType() { return TYPE_SKYRIM; }
@@ -81,11 +81,11 @@ public: virtual std::wstring getNexusPage(bool nmmScheme = true);
static std::wstring getNexusInfoUrlStatic();
- virtual std::wstring getNexusInfoUrl() { return SkyrimInfo::getNexusInfoUrlStatic(); }
+ virtual std::wstring getNexusInfoUrl() { return getNexusInfoUrlStatic(); }
static int getNexusModIDStatic();
- virtual int getNexusModID() { return SkyrimInfo::getNexusModIDStatic(); }
+ virtual int getNexusModID() { return getNexusModIDStatic(); }
static int getNexusGameIDStatic() { return 110; }
- virtual int getNexusGameID() { return SkyrimInfo::getNexusGameIDStatic(); }
+ virtual int getNexusGameID() { return getNexusGameIDStatic(); }
virtual void createProfile(const std::wstring &directory, bool useDefaults);
virtual void repairProfile(const std::wstring &directory);
@@ -94,7 +94,7 @@ public: // get a list of executables (game binary and known-to-work 3rd party tools). All of these are relative to
// the game directory
- virtual std::vector<ExecutableInfo> getExecutables();
+ //virtual std::vector<ExecutableInfo> getExecutables();
virtual std::wstring archiveListKey() { return L"SResourceArchiveList"; }
diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 61ca9cdc..d4a77929 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -25,6 +25,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <algorithm>
#include <DbgHelp.h>
#include <set>
+#include <boost/scoped_array.hpp>
namespace MOShared {
@@ -64,24 +65,30 @@ bool FileExists(const std::wstring &searchPath, const std::wstring &filename) std::string ToString(const std::wstring &source, bool utf8)
{
- char buffer[MAX_PATH];
- if (utf8) {
- ::WideCharToMultiByte(CP_UTF8, 0, source.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
- } else {
- ::WideCharToMultiByte(GetACP(), 0, source.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
+ std::string result;
+ UINT codepage = utf8 ? CP_UTF8 : GetACP();
+ int sizeRequired = ::WideCharToMultiByte(codepage, 0, &source[0], -1, NULL, 0, NULL, NULL);
+ if (sizeRequired == 0) {
+ throw windows_error("failed to convert string to multibyte");
}
- return std::string(buffer);
+ // the size returned by WideCharToMultiByte contains zero termination IF -1 is specified for the length.
+ // we don't want that \0 in the string because then the length field would be wrong. Because madness
+ result.resize(sizeRequired - 1, '\0');
+ ::WideCharToMultiByte(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired, NULL, NULL);
+ return result;
}
std::wstring ToWString(const std::string &source, bool utf8)
{
- wchar_t buffer[MAX_PATH];
- if (utf8) {
- ::MultiByteToWideChar(CP_UTF8, 0, source.c_str(), -1, buffer, MAX_PATH);
- } else {
- ::MultiByteToWideChar(GetACP(), 0, source.c_str(), -1, buffer, MAX_PATH);
+ std::wstring result;
+ UINT codepage = utf8 ? CP_UTF8 : GetACP();
+ int sizeRequired = ::MultiByteToWideChar(codepage, 0, &source[0], (int)source.size(), NULL, 0);
+ if (sizeRequired == 0) {
+ throw windows_error("failed to convert string to wide character");
}
- return std::wstring(buffer);
+ result.resize(sizeRequired, L'\0');
+ ::MultiByteToWideChar(codepage, 0, &source[0], (int)source.size(), &result[0], sizeRequired);
+ return result;
}
std::string &ToLower(std::string &text)
@@ -112,14 +119,15 @@ std::wstring ToLower(const std::wstring &text) VS_FIXEDFILEINFO GetFileVersion(const std::wstring &fileName)
{
- DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), NULL);
+ DWORD handle;
+ DWORD size = ::GetFileVersionInfoSizeW(fileName.c_str(), &handle);
if (size == 0) {
throw windows_error("failed to determine file version info size");
}
void *buffer = new char[size];
try {
- if (!::GetFileVersionInfoW(fileName.c_str(), 0UL, size, buffer)) {
+ if (!::GetFileVersionInfoW(fileName.c_str(), handle, size, buffer)) {
throw windows_error("failed to determine file version info");
}
diff --git a/src/singleinstance.cpp b/src/singleinstance.cpp index a1928523..dcb0fc78 100644 --- a/src/singleinstance.cpp +++ b/src/singleinstance.cpp @@ -54,6 +54,8 @@ SingleInstance::SingleInstance(bool forcePrimary, QObject *parent) : }
if (m_PrimaryInstance) {
connect(&m_Server, SIGNAL(newConnection()), this, SLOT(receiveMessage()));
+ // has to be called before listen
+ m_Server.setSocketOptions(QLocalServer::WorldAccessOption);
m_Server.listen(s_Key);
}
}
diff --git a/src/spawn.cpp b/src/spawn.cpp index ddcf573e..cd7e202e 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -120,7 +120,7 @@ HANDLE startBinary(const QFileInfo &binary, JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;
::QueryInformationJobObject(NULL, JobObjectExtendedLimitInformation, &jobInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION), NULL);
- jobInfo.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_BREAKAWAY_OK;
+ jobInfo.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
HANDLE jobObject = ::CreateJobObject(NULL, NULL);
diff --git a/src/tutorials/TutorialOverlay.qml b/src/tutorials/TutorialOverlay.qml index 34959d7d..f2aad027 100644 --- a/src/tutorials/TutorialOverlay.qml +++ b/src/tutorials/TutorialOverlay.qml @@ -1,4 +1,3 @@ -// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
import "tutorials.js" as Logic
@@ -21,10 +20,11 @@ Rectangle { function enableBackground(enabled) {
disabledBackground.visible = enabled
}
-
+/*
signal nextStep
- onNextStep: {
+ onNextStep: {*/
+ function nextStep() {
if (step == 0) {
Logic.init()
}
diff --git a/src/tutorials/tutorial_firststeps_main.js b/src/tutorials/tutorial_firststeps_main.js index 4f9c1a74..5ee4e790 100644 --- a/src/tutorials/tutorial_firststeps_main.js +++ b/src/tutorials/tutorial_firststeps_main.js @@ -15,19 +15,24 @@ function getTutorialSteps() function() {
tutorial.text = qsTr("The highlighted button provides hints on solving problems MO recognized automatically.")
- if (!tutorialControl.waitForAction("actionProblems")) {
- highlightAction("actionProblems", false)
- waitForClick()
- } else {
+ if (tutorialControl.waitForAction("actionProblems")) {
tutorial.text += qsTr("\nThere IS a problem now but you may want to hold off on fixing it until after completing the tutorial.")
highlightAction("actionProblems", true)
+ } else {
+ highlightAction("actionProblems", false)
+ waitForClick()
}
},
function() {
+ console.log("next")
tutorial.text = qsTr("This button provides multiple sources of information and further tutorials.")
- highlightItem("actionHelp", true)
- tutorialControl.waitForButton("actionHelp")
+ if (tutorialControl.waitForButton("actionHelp")) {
+ highlightItem("actionHelp", true)
+ } else {
+ console.error("help button broken")
+ waitForClick()
+ }
},
function() {
@@ -47,12 +52,16 @@ function getTutorialSteps() function() {
tutorial.text = qsTr("Before we start installing mods, let's have a quick look at the settings.")
manager.activateTutorial("SettingsDialog", "tutorial_firststeps_settings.js")
- highlightAction("actionSettings", true)
- tutorialControl.waitForAction("actionSettings")
+ if (tutorialControl.waitForAction("actionSettings")) {
+ highlightAction("actionSettings", true)
+ } else {
+ console.error("settings action broken")
+ waitForClick()
+ }
},
function() {
- tutorial.text = qsTr("Now it's time to install a few mods!"
+ tutorial.text = qsTr("Now it's time to install a few mods!"
+ "Please go along with this because we need a few mods installed to demonstrate other features")
waitForClick()
},
@@ -61,8 +70,12 @@ function getTutorialSteps() tutorial.text = qsTr("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 \"Nexus\" to open nexus, find a mod and click the green download buttons on Nexus saying \"Download with Manager\".")
- highlightAction("actionNexus", true)
- tutorialControl.waitForAction("actionNexus")
+ if (tutorialControl.waitForAction("actionNexus")) {
+ highlightAction("actionNexus", true)
+ } else {
+ console.error("browser action broken")
+ waitForClick()
+ }
},
function() {
|
