Handle built-in content files in content model

There's also handling for files declared as originating from a lower-priority openmw.cfg, e.g. anything in the local config or any intermediate ones, as they can't be disabled or reordered.
There's no way to mark such files yet, but the logic's the same as built-in files, so everything will be fine once that's set up.
pull/3235/head
AnyOldName3 10 months ago
parent 322a378907
commit d111b4bbd9

@ -109,6 +109,9 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex& index
if (!file) if (!file)
return Qt::NoItemFlags; return Qt::NoItemFlags;
if (file->builtIn() || file->fromAnotherConfigFile())
return Qt::NoItemFlags;
// game files can always be checked // game files can always be checked
if (file == mGameFile) if (file == mGameFile)
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable; return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
@ -130,7 +133,7 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex& index
continue; continue;
noGameFiles = false; noGameFiles = false;
if (mCheckedFiles.contains(depFile)) if (depFile->builtIn() || depFile->fromAnotherConfigFile() || mCheckedFiles.contains(depFile))
{ {
gamefileChecked = true; gamefileChecked = true;
break; break;
@ -217,14 +220,14 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
if (file == mGameFile) if (file == mGameFile)
return QVariant(); return QVariant();
return mCheckedFiles.contains(file) ? Qt::Checked : Qt::Unchecked; return (file->builtIn() || file->fromAnotherConfigFile() || mCheckedFiles.contains(file)) ? Qt::Checked : Qt::Unchecked;
} }
case Qt::UserRole: case Qt::UserRole:
{ {
if (file == mGameFile) if (file == mGameFile)
return ContentType_GameFile; return ContentType_GameFile;
else if (flags(index)) else
return ContentType_Addon; return ContentType_Addon;
break; break;
@ -279,7 +282,12 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const
{ {
int checkValue = value.toInt(); int checkValue = value.toInt();
bool setState = false; bool setState = false;
if (checkValue == Qt::Checked && !mCheckedFiles.contains(file)) if (file->builtIn() || file->fromAnotherConfigFile())
{
setState = false;
success = false;
}
else if (checkValue == Qt::Checked && !mCheckedFiles.contains(file))
{ {
setState = true; setState = true;
success = true; success = true;
@ -374,6 +382,13 @@ bool ContentSelectorModel::ContentModel::dropMimeData(
else if (parent.isValid()) else if (parent.isValid())
beginRow = parent.row(); beginRow = parent.row();
int firstModifiable = 0;
while (item(firstModifiable)->builtIn() || item(firstModifiable)->fromAnotherConfigFile())
++firstModifiable;
if (beginRow < firstModifiable)
return false;
QByteArray encodedData = data->data(mMimeType); QByteArray encodedData = data->data(mMimeType);
QDataStream stream(&encodedData, QIODevice::ReadOnly); QDataStream stream(&encodedData, QIODevice::ReadOnly);
@ -449,6 +464,9 @@ void ContentSelectorModel::ContentModel::addFiles(const QString& path, bool newf
file->setGameFiles({}); file->setGameFiles({});
} }
if (info.fileName().compare("builtin.omwscripts", Qt::CaseInsensitive) == 0)
file->setBuiltIn(true);
if (info.fileName().endsWith(".omwscripts", Qt::CaseInsensitive)) if (info.fileName().endsWith(".omwscripts", Qt::CaseInsensitive))
{ {
file->setDate(info.lastModified()); file->setDate(info.lastModified());
@ -579,15 +597,20 @@ void ContentSelectorModel::ContentModel::setCurrentGameFile(const EsmFile* file)
void ContentSelectorModel::ContentModel::sortFiles() void ContentSelectorModel::ContentModel::sortFiles()
{ {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
int firstModifiable = 0;
while (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile())
++firstModifiable;
// Dependency sort // Dependency sort
std::unordered_set<const EsmFile*> moved; std::unordered_set<const EsmFile*> moved;
for (int i = mFiles.size() - 1; i > 0;) for (int i = mFiles.size() - 1; i > firstModifiable;)
{ {
const auto file = mFiles.at(i); const auto file = mFiles.at(i);
if (moved.find(file) == moved.end()) if (moved.find(file) == moved.end())
{ {
int index = -1; int index = -1;
for (int j = 0; j < i; ++j) for (int j = firstModifiable; j < i; ++j)
{ {
const QStringList& gameFiles = mFiles.at(j)->gameFiles(); const QStringList& gameFiles = mFiles.at(j)->gameFiles();
// All addon files are implicitly dependent on the game file // All addon files are implicitly dependent on the game file
@ -650,6 +673,7 @@ void ContentSelectorModel::ContentModel::setContentList(const QStringList& fileL
{ {
if (setCheckState(filepath, true)) if (setCheckState(filepath, true))
{ {
// setCheckState already gracefully handles builtIn and fromAnotherConfigFile
// as necessary, move plug-ins in visible list to match sequence of supplied filelist // as necessary, move plug-ins in visible list to match sequence of supplied filelist
const EsmFile* file = item(filepath); const EsmFile* file = item(filepath);
int filePosition = indexFromItem(file).row(); int filePosition = indexFromItem(file).row();
@ -747,7 +771,7 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath,
const EsmFile* file = item(filepath); const EsmFile* file = item(filepath);
if (!file) if (!file || file->builtIn() || file->fromAnotherConfigFile())
return false; return false;
if (checkState) if (checkState)

@ -41,6 +41,16 @@ void ContentSelectorModel::EsmFile::setDescription(const QString& description)
mDescription = description; mDescription = description;
} }
void ContentSelectorModel::EsmFile::setBuiltIn(bool builtIn)
{
mBuiltIn = builtIn;
}
void ContentSelectorModel::EsmFile::setFromAnotherConfigFile(bool fromAnotherConfigFile)
{
mFromAnotherConfigFile = fromAnotherConfigFile;
}
bool ContentSelectorModel::EsmFile::isGameFile() const bool ContentSelectorModel::EsmFile::isGameFile() const
{ {
return (mGameFiles.size() == 0) return (mGameFiles.size() == 0)
@ -76,6 +86,14 @@ QVariant ContentSelectorModel::EsmFile::fileProperty(const FileProperty prop) co
return mDescription; return mDescription;
break; break;
case FileProperty_BuiltIn:
return mBuiltIn;
break;
case FileProperty_FromAnotherConfigFile:
return mFromAnotherConfigFile;
break;
case FileProperty_GameFile: case FileProperty_GameFile:
return mGameFiles; return mGameFiles;
break; break;
@ -113,6 +131,15 @@ void ContentSelectorModel::EsmFile::setFileProperty(const FileProperty prop, con
mDescription = value; mDescription = value;
break; break;
// todo: check these work
case FileProperty_BuiltIn:
mBuiltIn = value == "true";
break;
case FileProperty_FromAnotherConfigFile:
mFromAnotherConfigFile = value == "true";
break;
case FileProperty_GameFile: case FileProperty_GameFile:
mGameFiles << value; mGameFiles << value;
break; break;

@ -26,7 +26,9 @@ namespace ContentSelectorModel
FileProperty_DateModified = 3, FileProperty_DateModified = 3,
FileProperty_FilePath = 4, FileProperty_FilePath = 4,
FileProperty_Description = 5, FileProperty_Description = 5,
FileProperty_GameFile = 6 FileProperty_BuiltIn = 6,
FileProperty_FromAnotherConfigFile = 7,
FileProperty_GameFile = 8,
}; };
EsmFile(const QString& fileName = QString(), ModelItem* parent = nullptr); EsmFile(const QString& fileName = QString(), ModelItem* parent = nullptr);
@ -40,6 +42,8 @@ namespace ContentSelectorModel
void setFilePath(const QString& path); void setFilePath(const QString& path);
void setGameFiles(const QStringList& gameFiles); void setGameFiles(const QStringList& gameFiles);
void setDescription(const QString& description); void setDescription(const QString& description);
void setBuiltIn(bool builtIn);
void setFromAnotherConfigFile(bool fromAnotherConfigFile);
void addGameFile(const QString& name) { mGameFiles.append(name); } void addGameFile(const QString& name) { mGameFiles.append(name); }
QVariant fileProperty(const FileProperty prop) const; QVariant fileProperty(const FileProperty prop) const;
@ -49,18 +53,27 @@ namespace ContentSelectorModel
QDateTime modified() const { return mModified; } QDateTime modified() const { return mModified; }
QString formatVersion() const { return mVersion; } QString formatVersion() const { return mVersion; }
QString filePath() const { return mPath; } QString filePath() const { return mPath; }
bool builtIn() const { return mBuiltIn; }
bool fromAnotherConfigFile() const { return mFromAnotherConfigFile; }
/// @note Contains file names, not paths. /// @note Contains file names, not paths.
const QStringList& gameFiles() const { return mGameFiles; } const QStringList& gameFiles() const { return mGameFiles; }
QString description() const { return mDescription; } QString description() const { return mDescription; }
QString toolTip() const QString toolTip() const
{ {
return mTooltipTemlate.arg(mAuthor) QString tooltip = mTooltipTemlate.arg(mAuthor)
.arg(mVersion) .arg(mVersion)
.arg(mModified.toString(Qt::ISODate)) .arg(mModified.toString(Qt::ISODate))
.arg(mPath) .arg(mPath)
.arg(mDescription) .arg(mDescription)
.arg(mGameFiles.join(", ")); .arg(mGameFiles.join(", "));
if (mBuiltIn)
tooltip += tr("<br/><b>This content file cannot be disabled because it is part of OpenMW.</b><br/>");
else if (mFromAnotherConfigFile)
tooltip += tr("<br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/>");
return tooltip;
} }
bool isGameFile() const; bool isGameFile() const;
@ -82,6 +95,8 @@ namespace ContentSelectorModel
QStringList mGameFiles; QStringList mGameFiles;
QString mDescription; QString mDescription;
QString mToolTip; QString mToolTip;
bool mBuiltIn = false;
bool mFromAnotherConfigFile = false;
}; };
} }

Loading…
Cancel
Save