Compare commits

..
Author SHA1 Message Date
Tannin 182ec5f85d bugfix: potential mod order problem reported when there were no mods at all 2014-12-20 17:06:48 +01:00
Tannin 41eb0d50d4 undid some changes that accidentally made it to this branch 2014-11-26 20:19:07 +01:00
Tannin 9cb9c2cc56 - fixed manifest for qt5
- download messages can now be sent from different user accounts
2014-11-14 23:33:49 +01:00
Tannin dd2203f647 - several style fixes suggested by static analysis
- will now support up to 4 levels of version numbers (major.minor.subminor.subsubminor
2014-09-24 19:51:51 +02:00
Tannin 926cdedf8c bugfix: search for missing masters wasn't case-insensitive 2014-09-10 20:33:23 +02:00
Tannin 7ea85f751e - added an additional diagnosis check that warns if there are any missing masters 2014-09-10 20:32:25 +02:00
Tannin fb4eacabed - re-enabled building of loot_cli and started developing against the new api
- extended set of default categories
- more tolerand bbcode parser
- added a few colors for the bbcode parser
- more fixes to qt5 compatibility
- started work on ability to unloading (and thus re-loading) of plugins
- names of plugins are no longer localizable (because those names are also used to store settings)
- added settings to disable individual diagnosis settings
- path of dependencies is now configured in a .pri file instead of environment variablees
- bugfix: if the modid-input is canceled, the id was saved as -1 and wasn't re-requested from the user
- bugfix: moving files with the SHFileOperation-Api didn't update the vfs correctly (still not perfect but better)
- bugfix: attempt to remove the deleter-file seems to have caused error messages for some users
- bugfix: fixed a couple of cases that might have caused the tutorial to hang
2014-09-08 20:37:23 +02:00
Tannin 4bf94e9fda load order suggestion now picks the first esp for each mod for its suggested
order, even if it's not the origin of that esp. This should fix some dubious
suggestions
2014-08-18 23:03:31 +02:00
Tannin 6f73fe05a4 - download-list will no longer show a file as having incomplete data if there is no file version
- added a new mod column with icons displaying the content of the mod
- MO now differentiates between mods using an internal name that disambiguates between foreign and regular mods
2014-07-21 19:14:24 +02:00
Tannin 41bd8cc0cd - qt 5 compatibility fixes
- detection for support of optimized find no longer depends on deprecated api
2014-07-15 17:31:44 +02:00
TheBloke f0957919a5 .pro files - formatting/consistency fixes
Many small formatting changes to the majority of .pro files
 Consistent style for Qt version checking, using greaterThan(QT_MAJOR_VERSION, 4)
  This seems safest, as would continue to work for a future Qt 6 etc.
  Note that this makes redudundant the commit before this one, to organizer.pro
 Consistent indenting
 Moved some file configuration sections to be together with related sections
 Moved some installation-related sections (e.g. OUTDIR/DSTDIR) to be at the bottom,
  immediately before the related POST_LINK install lines.
 Similarly, in some cases separated out CONFIG(debug,.. checks into separate
  LIB/INCLUDE sections (high in file) and installation directory sections (low
   in file)
2014-07-07 23:32:18 +01:00
3 changed files with 90 additions and 30 deletions
+2 -4
View File
@@ -10,9 +10,7 @@ TEMPLATE = lib
CONFIG += plugins
CONFIG += dll
contains(QT_VERSION, "^5.*") {
QT += widgets
}
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
DEFINES += DIAGNOSEBASIC_LIBRARY
DEFINES += NOMINMAX
@@ -26,7 +24,7 @@ HEADERS += diagnosebasic.h
include(../plugin_template.pri)
INCLUDEPATH += "$(BOOSTPATH)"
INCLUDEPATH += "$${BOOSTPATH}"
#CONFIG += dll
+85 -26
View File
@@ -45,6 +45,7 @@ using namespace MOBase;
DiagnoseBasic::DiagnoseBasic()
: m_MOInfo(NULL)
{
}
@@ -70,7 +71,7 @@ bool DiagnoseBasic::init(IOrganizer *moInfo)
QString DiagnoseBasic::name() const
{
return tr("Basic diagnosis plugin");
return "Basic diagnosis plugin";
}
QString DiagnoseBasic::author() const
@@ -85,7 +86,7 @@ QString DiagnoseBasic::description() const
VersionInfo DiagnoseBasic::version() const
{
return VersionInfo(1, 1, 0, VersionInfo::RELEASE_FINAL);
return VersionInfo(1, 1, 2, VersionInfo::RELEASE_FINAL);
}
bool DiagnoseBasic::isActive() const
@@ -95,7 +96,13 @@ bool DiagnoseBasic::isActive() const
QList<PluginSetting> DiagnoseBasic::settings() const
{
return QList<PluginSetting>();
return QList<PluginSetting>()
<< PluginSetting("check_errorlog", tr("Warn when an error occured last time an application was run"), true)
<< PluginSetting("check_overwrite", tr("Warn when there are files in the overwrite directory"), true)
<< PluginSetting("check_font", tr("Warn when the font configuration refers to files that aren't installed"), true)
<< PluginSetting("check_conflict", tr("Warn when mods are installed that conflict with MO functionality"), true)
<< PluginSetting("check_modorder", tr("Warn when MO determins the mod order may cause problems"), true)
<< PluginSetting("check_missingmasters", tr("Warn when there are esps with missing masters"), true);
}
@@ -213,6 +220,9 @@ void DiagnoseBasic::topoSort(std::vector<DiagnoseBasic::ListElement> &list) cons
// figure out disconnected components of the graph
std::vector<int> component(num_vertices(graph));
if (component.size() == 0) {
throw MyException(tr("failed to sort"));
}
connected_components(graph, &component[0]);
for (int i = 0; i != component.size(); ++i) {
list[i].sortGroup = component[i];
@@ -242,7 +252,8 @@ void DiagnoseBasic::Sorter::sortGroup(std::vector<ListElement> modList)
auto iter = modList.begin() + 1;
for (; iter != modList.end(); ++iter) {
if (iter->modPriority < curSeqEnd->modPriority) {
if ((iter->pluginPriority != curSeqEnd->pluginPriority)
&& (iter->modPriority < curSeqEnd->modPriority)) {
// sequence ends
// use this sequence of correctly sorted mods if it is longer than the previously longest
// sequence and doesn't have fewer mods that don't want to move. Thus the need for mods to
@@ -284,7 +295,8 @@ void DiagnoseBasic::Sorter::sortGroup(std::vector<ListElement> modList)
break;
}
}
if (!found) {
if (!found
&& (iter->pluginPriority != (*sorted.rbegin()).pluginPriority)) {
// add to end!
moves.push_back(Move(*iter, *sorted.rbegin(), Move::AFTER));
}
@@ -339,19 +351,21 @@ bool DiagnoseBasic::assetOrder() const
[] (const QString &fileName) -> bool { return fileName.endsWith(".esp", Qt::CaseInsensitive)
|| fileName.endsWith(".esm", Qt::CaseInsensitive); });
foreach (const QString &esp, esps) {
ListElement ele;
foreach (const QString origin, m_MOInfo->getFileOrigins(esp)) {
ListElement ele;
ele.espName = QFileInfo(esp).fileName();
ele.modName = m_MOInfo->pluginList()->origin(ele.espName);
ele.pluginPriority = m_MOInfo->pluginList()->priority(ele.espName);
ele.modPriority = m_MOInfo->modList()->priority(ele.modName);
IModList::ModStates state = m_MOInfo->modList()->state(ele.modName);
ele.avoidMove = state.testFlag(IModList::STATE_ESSENTIAL);
auto iter = scriptMods.find(ele.modName);
if (state.testFlag(IModList::STATE_EXISTS)
&& (iter != scriptMods.end())) {
ele.relevantScripts = iter->second;
modList.push_back(ele);
ele.espName = QFileInfo(esp).fileName();
ele.modName = origin;
ele.pluginPriority = m_MOInfo->pluginList()->priority(ele.espName);
ele.modPriority = m_MOInfo->modList()->priority(ele.modName);
IModList::ModStates state = m_MOInfo->modList()->state(ele.modName);
ele.avoidMove = state.testFlag(IModList::STATE_ESSENTIAL);
auto iter = scriptMods.find(ele.modName);
if (state.testFlag(IModList::STATE_EXISTS)
&& (iter != scriptMods.end())) {
ele.relevantScripts = iter->second;
modList.push_back(ele);
}
}
}
@@ -373,6 +387,10 @@ bool DiagnoseBasic::assetOrder() const
}
}
if (distinctModList.size() == 0) {
return false;
}
// sort the list by plugin priority. This step is probably unnecessary as the list was already sorted when we removed duplicates
std::sort(distinctModList.begin(), distinctModList.end(),
[] (const ListElement &lhs, const ListElement &rhs) -> bool { return lhs.pluginPriority < rhs.pluginPriority; });
@@ -386,6 +404,36 @@ bool DiagnoseBasic::assetOrder() const
return m_SuggestedMoves.size() > 0;
}
bool DiagnoseBasic::missingMasters() const
{
std::set<QString> enabledPlugins;
QStringList esps = m_MOInfo->findFiles("",
[] (const QString &fileName) -> bool { return fileName.endsWith(".esp", Qt::CaseInsensitive)
|| fileName.endsWith(".esm", Qt::CaseInsensitive); });
// gather enabled masters first
foreach (const QString &esp, esps) {
QString baseName = QFileInfo(esp).fileName();
if (m_MOInfo->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE) {
enabledPlugins.insert(baseName.toLower());
}
}
m_MissingMasters.clear();
// for each required master in each esp, test if it's in the list of enabled masters.
foreach (const QString &esp, esps) {
QString baseName = QFileInfo(esp).fileName();
if (m_MOInfo->pluginList()->state(baseName) == IPluginList::STATE_ACTIVE) {
foreach (const QString master, m_MOInfo->pluginList()->masters(baseName)) {
if (enabledPlugins.find(master.toLower()) == enabledPlugins.end()) {
m_MissingMasters.insert(master);
}
}
}
}
return !m_MissingMasters.empty();
}
bool DiagnoseBasic::invalidFontConfig() const
{
if (m_MOInfo->gameInfo().type() != IGameInfo::TYPE_SKYRIM) {
@@ -430,26 +478,28 @@ bool DiagnoseBasic::invalidFontConfig() const
return false;
}
std::vector<unsigned int> DiagnoseBasic::activeProblems() const
{
std::vector<unsigned int> result;
if (errorReported()) {
if (m_MOInfo->pluginSetting(name(), "check_errorlog").toBool() && errorReported()) {
result.push_back(PROBLEM_ERRORLOG);
}
if (overwriteFiles()) {
if (m_MOInfo->pluginSetting(name(), "check_overwrite").toBool() && overwriteFiles()) {
result.push_back(PROBLEM_OVERWRITE);
}
if (invalidFontConfig()) {
if (m_MOInfo->pluginSetting(name(), "check_font").toBool() && invalidFontConfig()) {
result.push_back(PROBLEM_INVALIDFONT);
}
if (nitpickInstalled()) {
if (m_MOInfo->pluginSetting(name(), "check_conflict").toBool() && nitpickInstalled()) {
result.push_back(PROBLEM_NITPICKINSTALLED);
}
if (assetOrder()) {
if (m_MOInfo->pluginSetting(name(), "check_modorder").toBool() && assetOrder()) {
result.push_back(PROBLEM_ASSETORDER);
}
if (m_MOInfo->pluginSetting(name(), "check_missingmasters").toBool() && missingMasters()) {
result.push_back(PROBLEM_MISSINGMASTERS);
}
if (QFile::exists(m_MOInfo->profilePath() + "/profile_tweaks.ini")) {
result.push_back(PROBLEM_PROFILETWEAKS);
}
@@ -472,6 +522,8 @@ QString DiagnoseBasic::shortDescription(unsigned int key) const
return tr("Potential Mod order problem");
case PROBLEM_PROFILETWEAKS:
return tr("Ini Tweaks overwritten");
case PROBLEM_MISSINGMASTERS:
return tr("Missing Masters");
default:
throw MyException(tr("invalid problem key %1").arg(key));
}
@@ -498,15 +550,17 @@ QString DiagnoseBasic::fullDescription(unsigned int key) const
"Worse: The two solutions may conflict so it's strongly suggested you remove this plugin.");
case PROBLEM_ASSETORDER: {
QString res = tr("The conflict resolution order for some mods containing scripts differs from that of the corresponding esp.<br>"
"This may lead to subtle, hard to locate bugs. You should re-order the affected mods (left list!).<br>"
"This may lead to subtle, hard to locate bugs. <b>You should re-order the affected mods (<font color=\"red\">left list!</font>).</b><br>"
"There is no way to reliably know if each of these changes is absolutely necessary but its definitively safer.<br>"
"If someone suggested you ignore this message, please give them a proper slapping from me. <b>Do not ignore this warning</b><br>"
"The following changes should prevent these kinds of errors:") + "<ul>";
foreach(const Move &op, m_SuggestedMoves) {
QString itemName = m_MOInfo->modList()->displayName(op.item.modName);
QString referenceName = m_MOInfo->modList()->displayName(op.reference.modName);
if (op.type == Move::BEFORE) {
res += "<li>" + tr("Move %1 before %2").arg(op.item.modName).arg(op.reference.modName) + "</li>";
res += "<li>" + tr("Move %1 before %2").arg(itemName).arg(referenceName) + "</li>";
} else {
res += "<li>" + tr("Move %1 after %2").arg(op.item.modName).arg(op.reference.modName) + "</li>";
res += "<li>" + tr("Move %1 after %2").arg(itemName).arg(referenceName) + "</li>";
}
}
res += "</ul>";
@@ -522,6 +576,11 @@ QString DiagnoseBasic::fullDescription(unsigned int key) const
"Hitting the <i>Fix</i> button will delete that file")
+ "<hr><i>profile_tweaks.ini:</i><pre>" + fileContent + "</pre>";
} break;
case PROBLEM_MISSINGMASTERS: {
return tr("The masters for some plugins (esp/esm) are not enabled.<br>"
"The game will crash unless you install and enable the following plugins: ")
+ "<ul><li>" + SetJoin(m_MissingMasters, "</li><li>") + "</li></ul>";
} break;
default:
throw MyException(tr("invalid problem key %1").arg(key));
}
+3
View File
@@ -66,6 +66,7 @@ private:
bool invalidFontConfig() const;
bool nitpickInstalled() const;
bool assetOrder() const;
bool missingMasters() const;
private:
@@ -75,6 +76,7 @@ private:
static const unsigned int PROBLEM_NITPICKINSTALLED = 4;
static const unsigned int PROBLEM_ASSETORDER = 5;
static const unsigned int PROBLEM_PROFILETWEAKS = 7;
static const unsigned int PROBLEM_MISSINGMASTERS = 8;
static const unsigned int NUM_CONTEXT_ROWS = 5;
@@ -129,6 +131,7 @@ private:
mutable QString m_ErrorMessage;
mutable std::vector <Move> m_SuggestedMoves;
mutable QString m_NewestModlistBackup;
mutable std::set<QString> m_MissingMasters;
};