1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-20 23:11:36 +00:00

Content selector: Cut down on unnecessary dataChanged calls (#8478)

setData shouldn't do dataChanged calls setCheckState already does
setCheckState should emit dataChanged for downstream dependencies unconditionally
setCheckState shouldn't emit dataChanged for upstream dependencies that weren't enabled
This commit is contained in:
Alexei Kotov 2025-05-15 23:20:34 +03:00
parent b7a48e1d78
commit 5ffcd21eee

View file

@ -251,9 +251,6 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const
return false; return false;
EsmFile* file = item(index.row()); EsmFile* file = item(index.row());
QString fileName = file->fileName();
bool success = false;
switch (role) switch (role)
{ {
case Qt::EditRole: case Qt::EditRole:
@ -267,65 +264,23 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const
file->setFileProperty(EsmFile::FileProperty_GameFile, list.at(i)); file->setFileProperty(EsmFile::FileProperty_GameFile, list.at(i));
emit dataChanged(index, index); emit dataChanged(index, index);
return true;
success = true;
} }
break;
case Qt::UserRole + 1: case Qt::UserRole + 1:
{ {
success = (flags(index) & Qt::ItemIsEnabled); return isEnabled(index) && setCheckState(file, value.toBool());
if (success)
{
success = setCheckState(file, value.toBool());
emit dataChanged(index, index);
}
} }
break;
case Qt::CheckStateRole: case Qt::CheckStateRole:
{ {
int checkValue = value.toInt(); int checkValue = value.toInt();
bool setState = false; if (checkValue == Qt::Checked)
if (file->builtIn() || file->fromAnotherConfigFile()) return mCheckedFiles.contains(file) || setCheckState(file, true);
{ if (checkValue == Qt::Unchecked)
setState = false; return !mCheckedFiles.contains(file) || setCheckState(file, false);
success = false;
}
else if (checkValue == Qt::Checked && !mCheckedFiles.contains(file))
{
setState = true;
success = true;
}
else if (checkValue == Qt::Checked && mCheckedFiles.contains(file))
setState = true;
else if (checkValue == Qt::Unchecked)
setState = true;
if (setState)
{
setCheckState(file, success);
emit dataChanged(index, index);
}
else
return success;
for (EsmFile* file2 : mFiles)
{
if (file2->gameFiles().contains(fileName, Qt::CaseInsensitive))
{
QModelIndex idx = indexFromItem(file2);
emit dataChanged(idx, idx);
}
}
success = true;
} }
break;
} }
return success; return false;
} }
bool ContentSelectorModel::ContentModel::insertRows(int position, int rows, const QModelIndex& parent) bool ContentSelectorModel::ContentModel::insertRows(int position, int rows, const QModelIndex& parent)
@ -715,6 +670,7 @@ void ContentSelectorModel::ContentModel::setContentList(const QStringList& fileL
{ {
// setCheckState already gracefully handles builtIn and fromAnotherConfigFile // 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
// FIXME: setCheckState also does tons of other things which we don't want to happen
int filePosition = indexFromItem(file).row(); int filePosition = indexFromItem(file).row();
if (filePosition < previousPosition) if (filePosition < previousPosition)
{ {
@ -805,38 +761,37 @@ bool ContentSelectorModel::ContentModel::setCheckState(const EsmFile* file, bool
else else
mCheckedFiles.erase(file); mCheckedFiles.erase(file);
emit dataChanged(indexFromItem(file), indexFromItem(file)); QModelIndex fileIndex = indexFromItem(file);
emit dataChanged(fileIndex, fileIndex);
// FIXME: this should not happen per-file.
// Consider not hiding files if their game is disabled so that this is completely unnecessary.
if (file->isGameFile()) if (file->isGameFile())
refreshModel(); refreshModel();
// if we're checking an item, ensure all "upstream" files (dependencies) are checked as well. // Check "upstream" files (dependencies) if the file is checked,
// uncheck downstream files if the file is unchecked.
// Update the data for downstream files unconditionally (load order warnings).
// FIXME: downstream files of toggled upstream/downstream files should be updated, but that would be slow.
if (checkState) if (checkState)
{ {
for (const QString& upstreamName : file->gameFiles()) for (const QString& upstreamName : file->gameFiles())
{ {
const EsmFile* upstreamFile = item(upstreamName); const EsmFile* upstreamFile = item(upstreamName);
if (upstreamFile == nullptr || !mCheckedFiles.insert(upstreamFile).second)
if (!upstreamFile)
continue; continue;
QModelIndex upstreamIndex = indexFromItem(upstreamFile);
mCheckedFiles.insert(upstreamFile); emit dataChanged(upstreamIndex, upstreamIndex);
emit dataChanged(indexFromItem(upstreamFile), indexFromItem(upstreamFile));
} }
} }
// otherwise, if we're unchecking an item (or the file is a game file) ensure all downstream files are unchecked. for (const EsmFile* otherFile : mFiles)
else
{ {
for (const EsmFile* downstreamFile : mFiles) if (!otherFile->gameFiles().contains(file->fileName(), Qt::CaseInsensitive))
{ continue;
if (downstreamFile->gameFiles().contains(file->fileName(), Qt::CaseInsensitive)) if (!checkState)
{ mCheckedFiles.erase(otherFile);
mCheckedFiles.erase(downstreamFile); QModelIndex otherIndex = indexFromItem(otherFile);
emit dataChanged(otherIndex, otherIndex);
emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile));
}
}
} }
// Need to manually let Bloodmoon entry know if Tribunal is checked/unchecked // Need to manually let Bloodmoon entry know if Tribunal is checked/unchecked