mirror of
https://github.com/ModOrganizer2/modorganizer-diagnose_basic.git
synced 2026-07-27 14:03:10 -07:00
Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
043f45ab70 | ||
|
|
fb294651c3 | ||
|
|
f4e1b296ad | ||
|
|
bd55424d8e | ||
|
|
d56a520815 | ||
|
|
fe8966e279 | ||
|
|
98bd1d4780 | ||
|
|
c345cacbc9 | ||
|
|
b78ae57ed4 | ||
|
|
d983c908ee | ||
|
|
0cc077b8c4 | ||
|
|
b245bc2ce3 | ||
|
|
0a1707fa9c | ||
|
|
b10b1f28ff | ||
|
|
59c10d78cd | ||
|
|
7dd29a68e2 | ||
|
|
ce0dc685ca | ||
|
|
e426d8efb4 | ||
|
|
bf00944706 | ||
|
|
97c8769334 | ||
|
|
05d1782cf1 | ||
|
|
f114b3ee60 | ||
|
|
0320bd719a | ||
|
|
943689d5c3 | ||
|
|
ecf0ff0d02 | ||
|
|
2632e79de7 | ||
|
|
863233e1ab | ||
|
|
8529da255f | ||
|
|
123d291dc1 | ||
|
|
0cc55698f7 | ||
|
|
2cf83c7681 | ||
|
|
366b3854b8 | ||
|
|
016a2efb88 | ||
|
|
4531207250 | ||
|
|
266b597e4c | ||
|
|
06487c2653 | ||
|
|
9b0637fa66 |
@@ -0,0 +1,24 @@
|
||||
Import('qt_env')
|
||||
|
||||
env = qt_env.Clone()
|
||||
|
||||
env.AppendUnique(CPPDEFINES = [
|
||||
'DIAGNOSEBASIC_LIBRARY',
|
||||
'NOMINMAX',
|
||||
# suppress a few warnings caused by boost vs vc++ paranoia
|
||||
'_SCL_SECURE_NO_WARNINGS'
|
||||
])
|
||||
|
||||
# Boost produces very long names with msvc truncates. Doesn't seem to cause
|
||||
# problems.
|
||||
env.AppendUnique(CPPFLAGS = [ '-wd4503' ])
|
||||
|
||||
env.AppendUnique(CPPPATH = [
|
||||
'${BOOSTPATH}'
|
||||
])
|
||||
|
||||
lib = env.SharedLibrary('diagnoseBasic', env.Glob('*.cpp'))
|
||||
env.InstallModule(lib)
|
||||
|
||||
res = env['QT_USED_MODULES']
|
||||
Return('res')
|
||||
@@ -31,4 +31,5 @@ INCLUDEPATH += "$${BOOSTPATH}"
|
||||
#DEFINES += INIEDITOR_LIBRARY
|
||||
|
||||
OTHER_FILES += \
|
||||
diagnosebasic.json
|
||||
diagnosebasic.json\
|
||||
SConscript
|
||||
|
||||
+79
-31
@@ -18,11 +18,17 @@
|
||||
*/
|
||||
|
||||
#include "diagnosebasic.h"
|
||||
|
||||
#include "filenamestring.h"
|
||||
#include <report.h>
|
||||
#include <utility.h>
|
||||
#include <imodlist.h>
|
||||
#include <ipluginlist.h>
|
||||
#include <igameinfo.h>
|
||||
#include <QtPlugin>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
#include <QMessageBox>
|
||||
@@ -45,7 +51,7 @@ using namespace MOBase;
|
||||
|
||||
|
||||
DiagnoseBasic::DiagnoseBasic()
|
||||
: m_MOInfo(NULL)
|
||||
: m_MOInfo(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -64,7 +70,10 @@ bool DiagnoseBasic::init(IOrganizer *moInfo)
|
||||
m_MOInfo->pluginList()->onPluginMoved([&] (const QString&, int, int) {
|
||||
invalidate();
|
||||
});
|
||||
m_MOInfo->pluginList()->onRefreshed([&] () { this->invalidate(); });
|
||||
m_MOInfo->pluginList()->onRefreshed([&] () { invalidate(); });
|
||||
m_MOInfo->pluginList()->onPluginStateChanged([&] (const QString &, IPluginList::PluginStates) {
|
||||
invalidate();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -102,13 +111,16 @@ QList<PluginSetting> DiagnoseBasic::settings() const
|
||||
<< 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);
|
||||
<< PluginSetting("check_missingmasters", tr("Warn when there are esps with missing masters"), true)
|
||||
<< PluginSetting("ow_ignore_empty", tr("Ignore empty directories when checking overwrite directory"), false)
|
||||
<< PluginSetting("ow_ignore_log", tr("Ignore .log files and empty directories when checking overwrite directory"), false)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
bool DiagnoseBasic::errorReported() const
|
||||
{
|
||||
QDir dir(QCoreApplication::applicationDirPath() + "/logs");
|
||||
QDir dir(qApp->property("dataPath").toString() + "/logs");
|
||||
QFileInfoList files = dir.entryInfoList(QStringList("ModOrganizer_??_??_??_??_??.log"),
|
||||
QDir::Files, QDir::Name | QDir::Reversed);
|
||||
|
||||
@@ -154,11 +166,39 @@ bool DiagnoseBasic::errorReported() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DiagnoseBasic::checkEmpty(QString const &path) const
|
||||
{
|
||||
QDir dir(path);
|
||||
dir.setFilter(QDir::Files | QDir::Hidden | QDir::System);
|
||||
|
||||
//Search files first
|
||||
for (QString const &f : dir.entryList()) {
|
||||
FileNameString file(f);
|
||||
if (! m_MOInfo->pluginSetting(name(), "ow_ignore_log").toBool() ||
|
||||
! file.endsWith(".log")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Then directories
|
||||
dir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
|
||||
for (QFileInfo const &subdir : dir.entryInfoList()) {
|
||||
if (!checkEmpty(subdir.absoluteFilePath())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DiagnoseBasic::overwriteFiles() const
|
||||
{
|
||||
QDir dir(QCoreApplication::applicationDirPath() + "/overwrite");
|
||||
|
||||
QString dirname(qApp->property("dataPath").toString() + "/overwrite");
|
||||
if (m_MOInfo->pluginSetting(name(), "ow_ignore_empty").toBool() ||
|
||||
m_MOInfo->pluginSetting(name(), "ow_ignore_log").toBool()) {
|
||||
return !checkEmpty(dirname);
|
||||
}
|
||||
QDir dir(dirname);
|
||||
return dir.count() != 2; // account for . and ..
|
||||
}
|
||||
|
||||
@@ -335,12 +375,16 @@ bool DiagnoseBasic::assetOrder() const
|
||||
|
||||
// list of mods containing conflicted scripts. We care only for those
|
||||
std::map<QString, QSet<QString>> scriptMods;
|
||||
foreach (const IOrganizer::FileInfo & pex, m_MOInfo->findFileInfos("scripts",
|
||||
[] (const IOrganizer::FileInfo &file) -> bool { return file.filePath.endsWith(".pex", Qt::CaseInsensitive); })) {
|
||||
auto filter = [] (const IOrganizer::FileInfo &file) -> bool {
|
||||
return file.filePath.endsWith(".pex", Qt::CaseInsensitive); };
|
||||
|
||||
for (const IOrganizer::FileInfo &pex : m_MOInfo->findFileInfos("scripts", filter)) {
|
||||
QStringList origins = pex.origins;
|
||||
origins.removeAll("data"); // ignore files in base directory
|
||||
// ignore files in base directories
|
||||
origins.removeAll("data");
|
||||
origins.removeAll("Overwrite");
|
||||
if (origins.size() > 1) {
|
||||
foreach(const QString &origin, origins) {
|
||||
for(const QString &origin : origins) {
|
||||
scriptMods[origin].insert(pex.filePath);
|
||||
}
|
||||
}
|
||||
@@ -348,10 +392,12 @@ bool DiagnoseBasic::assetOrder() const
|
||||
|
||||
// produce a list with the information we need: plugin, mod and the priority for each
|
||||
QStringList esps = m_MOInfo->findFiles("",
|
||||
[] (const QString &fileName) -> bool { return fileName.endsWith(".esp", Qt::CaseInsensitive)
|
||||
|| fileName.endsWith(".esm", Qt::CaseInsensitive); });
|
||||
foreach (const QString &esp, esps) {
|
||||
foreach (const QString origin, m_MOInfo->getFileOrigins(esp)) {
|
||||
[] (const QString &fileName) -> bool {
|
||||
return fileName.endsWith(".esp", Qt::CaseInsensitive)
|
||||
|| fileName.endsWith(".esm", Qt::CaseInsensitive);
|
||||
});
|
||||
for (const QString &esp : esps) {
|
||||
for (const QString origin : m_MOInfo->getFileOrigins(esp)) {
|
||||
ListElement ele;
|
||||
|
||||
ele.espName = QFileInfo(esp).fileName();
|
||||
@@ -368,7 +414,6 @@ bool DiagnoseBasic::assetOrder() const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate a copy of list that contains each mod only once, otherwise
|
||||
// strange things happen if a mod contains multiple esps that are mixed
|
||||
// with esps from other mods
|
||||
@@ -376,17 +421,18 @@ bool DiagnoseBasic::assetOrder() const
|
||||
{
|
||||
// sort the input list so we get predictable results
|
||||
std::sort(modList.begin(), modList.end(),
|
||||
[] (const ListElement &lhs, const ListElement &rhs) -> bool { return lhs.pluginPriority < rhs.pluginPriority; });
|
||||
[] (const ListElement &lhs, const ListElement &rhs) -> bool {
|
||||
return lhs.pluginPriority < rhs.pluginPriority;
|
||||
});
|
||||
|
||||
std::set<QString> includedMods;
|
||||
foreach(const ListElement &ele, modList) {
|
||||
for (const ListElement &ele : modList) {
|
||||
if (includedMods.find(ele.modName) == includedMods.end()) {
|
||||
distinctModList.push_back(ele);
|
||||
includedMods.insert(ele.modName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distinctModList.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -395,13 +441,16 @@ bool DiagnoseBasic::assetOrder() const
|
||||
std::sort(distinctModList.begin(), distinctModList.end(),
|
||||
[] (const ListElement &lhs, const ListElement &rhs) -> bool { return lhs.pluginPriority < rhs.pluginPriority; });
|
||||
|
||||
topoSort(distinctModList);
|
||||
if (distinctModList.size() > 0) {
|
||||
topoSort(distinctModList);
|
||||
|
||||
// now determine the moves necessary to bring the mod list into this order
|
||||
minSorter(distinctModList);
|
||||
m_SuggestedMoves = minSorter.moves;
|
||||
|
||||
return m_SuggestedMoves.size() > 0;
|
||||
// now determine the moves necessary to bring the mod list into this order
|
||||
minSorter(distinctModList);
|
||||
m_SuggestedMoves = minSorter.moves;
|
||||
return m_SuggestedMoves.size() > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DiagnoseBasic::missingMasters() const
|
||||
@@ -549,12 +598,11 @@ QString DiagnoseBasic::fullDescription(unsigned int key) const
|
||||
return tr("You have the nitpick skse plugin installed. This plugin is not needed with Mod Organizer because MO already offers the same functionality. "
|
||||
"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. <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 res = tr("The conflict resolution order for some mods with scripts differs from that of the corresponding esp.<br>"
|
||||
"This may lead to subtle, hard to locate bugs.<br>"
|
||||
"<b>Please first ensure your load order is correct!</b><br>"
|
||||
"If it is you should re-order the affected mods (<b><font color=\"red\">left list!</font></b>) like this:") + "<br><ul>";
|
||||
for (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) {
|
||||
@@ -595,7 +643,7 @@ void DiagnoseBasic::startGuidedFix(unsigned int key) const
|
||||
{
|
||||
switch (key) {
|
||||
case PROBLEM_ASSETORDER: {
|
||||
if (QMessageBox::warning(NULL, tr("Continue?"), tr("This <b>BETA</b> feature will rearrange your mods to eliminate all "
|
||||
if (QMessageBox::warning(nullptr, tr("Continue?"), tr("This <b>BETA</b> feature will rearrange your mods to eliminate all "
|
||||
"possible ordering conflicts. Proceed?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
foreach (const Move &op, m_SuggestedMoves) {
|
||||
int oldPriority = m_MOInfo->modList()->priority(op.item.modName);
|
||||
|
||||
+2
-1
@@ -29,7 +29,7 @@ along with this plugin. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <QSet>
|
||||
|
||||
|
||||
class DiagnoseBasic : public QObject, MOBase::IPlugin, MOBase::IPluginDiagnose
|
||||
class DiagnoseBasic : public QObject, public MOBase::IPlugin, public MOBase::IPluginDiagnose
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginDiagnose)
|
||||
@@ -124,6 +124,7 @@ private:
|
||||
private:
|
||||
|
||||
void topoSort(std::vector<ListElement> &list) const;
|
||||
bool checkEmpty(const QString &path) const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user