Compare commits

...
Author SHA1 Message Date
Tannin 043f45ab70 Merge 2015-08-31 21:26:47 +02:00
Tom Tanner fb294651c3 Merge 2015-08-28 20:04:15 +01:00
Tannin f4e1b296ad Merge 2015-08-27 20:59:37 +02:00
Tom Tanner bd55424d8e Small fix to shut up messages about long boost names 2015-08-20 19:53:39 +01:00
Tannin d56a520815 Simplified the PMOP message 2015-08-19 19:05:15 +02:00
Tannin fe8966e279 small code beautification 2015-07-07 20:53:38 +02:00
Tom Tanner 98bd1d4780 And now I find the place I should have altered.
Added some options to the diagnosis plugin to ignore .log files and empty
directories in overwrite folder
2015-06-24 20:46:31 +01:00
Tom Tanner c345cacbc9 and now I find out I don't need to do it at all 2015-06-23 20:27:38 +01:00
Tom Tanner b78ae57ed4 Factor out general, nexis, plugins tab code into individual classes
Add some code and page to control what is/isn't significant in overwrite
2015-06-20 15:37:32 +01:00
Tannin d983c908ee minor stuff 2015-05-11 21:41:00 +02:00
Tannin 0cc077b8c4 Merge 2015-05-09 21:46:40 +02:00
Tannin b245bc2ce3 enabling/disabling a plugin should now immediately cause a check for problems 2015-04-08 18:53:43 +02:00
Tannin 0a1707fa9c Merge in changes by Tom Tanner 2015-03-27 18:24:37 +01:00
Tom Tanner b10b1f28ff Fixed Scons build for existing bits.
Changed pynedit.pro to fetch from 'standard' install location
Changed saveas code to use organizer report rather than uibase - this way it's
not dependant on the vagaries of the include path, and works the same as the
rest of the organiser directory
2015-03-20 10:34:30 +00:00
Tom Tanner 59c10d78cd Merge 2015-03-19 16:48:21 +00:00
Tannin 7dd29a68e2 overwrite is now ignored when determining potential mod order conflicts 2015-03-18 19:38:24 +01:00
Tom Tanner ce0dc685ca Merge with branch1.2 2015-03-18 17:40:29 +00:00
Tom Tanner e426d8efb4 Refactoring and cleanup. 2015-03-18 14:16:04 +00:00
Tom Tanner bf00944706 Every plugin now built 2015-03-17 16:31:15 +00:00
Tannin 97c8769334 Merge with branch1.2 2015-01-24 19:34:12 +01:00
Tannin 05d1782cf1 cleanup (mostly removing unused includes) 2015-01-22 19:44:38 +01:00
Tannin f114b3ee60 bugfix: translations for some plugins weren't loaded 2015-01-11 11:14:58 +01:00
Tannin 0320bd719a Merge 2015-01-04 10:33:37 +01:00
Tannin 943689d5c3 - fixes after merge 2015-01-04 10:13:12 +01:00
Tannin ecf0ff0d02 Merge with branch1.2 2015-01-03 15:58:52 +01:00
Tannin 2632e79de7 replaced all uses of NULL with nullptr
fixed a few placed where NULL was used as a number or boolean
2014-11-28 11:19:20 +01:00
Tannin 863233e1ab - fixed manifest for qt5
- download messages can now be sent from different user accounts
2014-11-14 23:33:49 +01:00
Tannin 8529da255f - 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 123d291dc1 bugfix: search for missing masters wasn't case-insensitive 2014-09-10 20:33:23 +02:00
Tannin 0cc55698f7 - added an additional diagnosis check that warns if there are any missing masters 2014-09-10 20:32:25 +02:00
Tannin 2cf83c7681 - 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 366b3854b8 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 016a2efb88 - 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 4531207250 Merge 2014-07-15 20:45:29 +02:00
Tannin 266b597e4c merged changes by TheBloke 2014-07-15 17:48:43 +02:00
Tannin 06487c2653 - qt 5 compatibility fixes
- detection for support of optimized find no longer depends on deprecated api
2014-07-15 17:31:44 +02:00
Tannin 9b0637fa66 - when highlighting a mod the overwritten and overwriting mods are now highlighted in the list
- when starting an external application MO now wraps the process in a job and waits on that instead. This way MO is not unlocked early when skyrim is started through skse
- mod info dialog no longer offers the esp tab for foreign mods because that caused confusion
- updated translation files
- download directory and mod directory are now created if necessary
- bugfix: staging script created unnecessary copies of translation files
- bugfix: potential invalid array access when trying to determine best mod order
- bugfix: deleter file wasn't removed after esp hiding was disabled
- bugfix: potential access to to un-initialized login reply
- bugfix: changed the initialization order to allow more ui controls to be localized
2014-07-14 21:22:44 +02:00
4 changed files with 107 additions and 33 deletions
+24
View File
@@ -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')
+2 -1
View File
@@ -31,4 +31,5 @@ INCLUDEPATH += "$${BOOSTPATH}"
#DEFINES += INIEDITOR_LIBRARY
OTHER_FILES += \
diagnosebasic.json
diagnosebasic.json\
SConscript
+79 -31
View File
@@ -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
View File
@@ -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: