mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-16 17:42:31 +00:00
Merge branch 'some-launcher-fixes' into 'master'
Some launcher fixes Closes #8080 See merge request OpenMW/openmw!4287
This commit is contained in:
commit
566e5b5588
@ -40,9 +40,8 @@ namespace Config
|
|||||||
|
|
||||||
inline void setValue(const QString& key, const SettingValue& value)
|
inline void setValue(const QString& key, const SettingValue& value)
|
||||||
{
|
{
|
||||||
mSettings.remove(key);
|
remove(key);
|
||||||
mSettings.insert(key, value);
|
mSettings.insert(key, value);
|
||||||
mUserSettings.remove(key);
|
|
||||||
if (isUserSetting(value))
|
if (isUserSetting(value))
|
||||||
mUserSettings.insert(key, value);
|
mUserSettings.insert(key, value);
|
||||||
}
|
}
|
||||||
@ -63,7 +62,14 @@ namespace Config
|
|||||||
|
|
||||||
inline void remove(const QString& key)
|
inline void remove(const QString& key)
|
||||||
{
|
{
|
||||||
mSettings.remove(key);
|
// simplify to removeIf when Qt5 goes
|
||||||
|
for (auto itr = mSettings.lowerBound(key); itr != mSettings.upperBound(key);)
|
||||||
|
{
|
||||||
|
if (isUserSetting(*itr))
|
||||||
|
itr = mSettings.erase(itr);
|
||||||
|
else
|
||||||
|
++itr;
|
||||||
|
}
|
||||||
mUserSettings.remove(key);
|
mUserSettings.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,9 +19,11 @@
|
|||||||
#include <components/files/openfile.hpp>
|
#include <components/files/openfile.hpp>
|
||||||
#include <components/files/qtconversion.hpp>
|
#include <components/files/qtconversion.hpp>
|
||||||
|
|
||||||
ContentSelectorModel::ContentModel::ContentModel(QObject* parent, QIcon& warningIcon, bool showOMWScripts)
|
ContentSelectorModel::ContentModel::ContentModel(
|
||||||
|
QObject* parent, QIcon& warningIcon, QIcon& errorIcon, bool showOMWScripts)
|
||||||
: QAbstractTableModel(parent)
|
: QAbstractTableModel(parent)
|
||||||
, mWarningIcon(warningIcon)
|
, mWarningIcon(warningIcon)
|
||||||
|
, mErrorIcon(errorIcon)
|
||||||
, mShowOMWScripts(showOMWScripts)
|
, mShowOMWScripts(showOMWScripts)
|
||||||
, mMimeType("application/omwcontent")
|
, mMimeType("application/omwcontent")
|
||||||
, mMimeTypes(QStringList() << mMimeType)
|
, mMimeTypes(QStringList() << mMimeType)
|
||||||
@ -169,7 +171,12 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
|
|||||||
{
|
{
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
{
|
{
|
||||||
return isLoadOrderError(file) ? mWarningIcon : QVariant();
|
if (file->isMissing())
|
||||||
|
return mErrorIcon;
|
||||||
|
else if (isLoadOrderError(file))
|
||||||
|
return mWarningIcon;
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::FontRole:
|
case Qt::FontRole:
|
||||||
@ -595,10 +602,32 @@ void ContentSelectorModel::ContentModel::sortFiles()
|
|||||||
{
|
{
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
|
|
||||||
int firstModifiable = 0;
|
// make both Qt5 (int) and Qt6 (qsizetype aka size_t) happy
|
||||||
while (firstModifiable < mFiles.size()
|
using index_t = ContentFileList::size_type;
|
||||||
&& (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile()))
|
|
||||||
++firstModifiable;
|
// ensure built-in are first
|
||||||
|
index_t firstModifiable = 0;
|
||||||
|
for (index_t i = 0; i < mFiles.length(); ++i)
|
||||||
|
{
|
||||||
|
if (mFiles.at(i)->builtIn())
|
||||||
|
mFiles.move(i, firstModifiable++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then non-user content
|
||||||
|
for (const auto& filename : mNonUserContent)
|
||||||
|
{
|
||||||
|
const EsmFile* file = item(filename);
|
||||||
|
int filePosition = indexFromItem(file).row();
|
||||||
|
if (filePosition >= 0)
|
||||||
|
mFiles.move(filePosition, firstModifiable++);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the file is not in the VFS, and will be displayed with an error
|
||||||
|
auto missingFile = std::make_unique<EsmFile>(filename);
|
||||||
|
missingFile->setFromAnotherConfigFile(true);
|
||||||
|
mFiles.insert(firstModifiable++, missingFile.release());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// For the purposes of dependency sort we'll hallucinate that Bloodmoon is dependent on Tribunal
|
// For the purposes of dependency sort we'll hallucinate that Bloodmoon is dependent on Tribunal
|
||||||
const EsmFile* tribunalFile = item("Tribunal.esm");
|
const EsmFile* tribunalFile = item("Tribunal.esm");
|
||||||
@ -669,20 +698,10 @@ void ContentSelectorModel::ContentModel::setNonUserContent(const QStringList& fi
|
|||||||
{
|
{
|
||||||
mNonUserContent.clear();
|
mNonUserContent.clear();
|
||||||
for (const auto& file : fileList)
|
for (const auto& file : fileList)
|
||||||
mNonUserContent.insert(file.toLower());
|
mNonUserContent.append(file.toLower());
|
||||||
for (auto* file : mFiles)
|
for (auto* file : mFiles)
|
||||||
file->setFromAnotherConfigFile(mNonUserContent.contains(file->fileName().toLower()));
|
file->setFromAnotherConfigFile(mNonUserContent.contains(file->fileName().toLower()));
|
||||||
|
|
||||||
auto insertPosition
|
|
||||||
= std::ranges::find_if(mFiles, [](const EsmFile* file) { return !file->builtIn(); }) - mFiles.begin();
|
|
||||||
|
|
||||||
for (const auto& filepath : fileList)
|
|
||||||
{
|
|
||||||
const EsmFile* file = item(filepath);
|
|
||||||
int filePosition = indexFromItem(file).row();
|
|
||||||
mFiles.move(filePosition, insertPosition++);
|
|
||||||
}
|
|
||||||
|
|
||||||
sortFiles();
|
sortFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace ContentSelectorModel
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit ContentModel(QObject* parent, QIcon& warningIcon, bool showOMWScripts);
|
explicit ContentModel(QObject* parent, QIcon& warningIcon, QIcon& errorIcon, bool showOMWScripts);
|
||||||
~ContentModel();
|
~ContentModel();
|
||||||
|
|
||||||
void setEncoding(const QString& encoding);
|
void setEncoding(const QString& encoding);
|
||||||
@ -86,12 +86,13 @@ namespace ContentSelectorModel
|
|||||||
|
|
||||||
const EsmFile* mGameFile;
|
const EsmFile* mGameFile;
|
||||||
ContentFileList mFiles;
|
ContentFileList mFiles;
|
||||||
QSet<QString> mNonUserContent;
|
QStringList mNonUserContent;
|
||||||
std::set<const EsmFile*> mCheckedFiles;
|
std::set<const EsmFile*> mCheckedFiles;
|
||||||
QHash<QString, bool> mNewFiles;
|
QHash<QString, bool> mNewFiles;
|
||||||
QSet<QString> mPluginsWithLoadOrderError;
|
QSet<QString> mPluginsWithLoadOrderError;
|
||||||
QString mEncoding;
|
QString mEncoding;
|
||||||
QIcon mWarningIcon;
|
QIcon mWarningIcon;
|
||||||
|
QIcon mErrorIcon;
|
||||||
bool mShowOMWScripts;
|
bool mShowOMWScripts;
|
||||||
|
|
||||||
QString mErrorToolTips[ContentSelectorModel::LoadOrderError::ErrorCode_LoadOrder]
|
QString mErrorToolTips[ContentSelectorModel::LoadOrderError::ErrorCode_LoadOrder]
|
||||||
|
@ -55,12 +55,15 @@ namespace ContentSelectorModel
|
|||||||
QString filePath() const { return mPath; }
|
QString filePath() const { return mPath; }
|
||||||
bool builtIn() const { return mBuiltIn; }
|
bool builtIn() const { return mBuiltIn; }
|
||||||
bool fromAnotherConfigFile() const { return mFromAnotherConfigFile; }
|
bool fromAnotherConfigFile() const { return mFromAnotherConfigFile; }
|
||||||
|
bool isMissing() const { return mPath.isEmpty(); }
|
||||||
|
|
||||||
/// @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
|
||||||
{
|
{
|
||||||
|
if (isMissing())
|
||||||
|
return tr("<b>This file is specified in a non-user config file, but does not exist in the VFS.</b>");
|
||||||
QString tooltip = mTooltipTemlate.arg(mAuthor)
|
QString tooltip = mTooltipTemlate.arg(mAuthor)
|
||||||
.arg(mVersion)
|
.arg(mVersion)
|
||||||
.arg(mModified.toString(Qt::ISODate))
|
.arg(mModified.toString(Qt::ISODate))
|
||||||
|
@ -32,7 +32,8 @@ ContentSelectorView::ContentSelector::~ContentSelector() = default;
|
|||||||
void ContentSelectorView::ContentSelector::buildContentModel(bool showOMWScripts)
|
void ContentSelectorView::ContentSelector::buildContentModel(bool showOMWScripts)
|
||||||
{
|
{
|
||||||
QIcon warningIcon(ui->addonView->style()->standardIcon(QStyle::SP_MessageBoxWarning));
|
QIcon warningIcon(ui->addonView->style()->standardIcon(QStyle::SP_MessageBoxWarning));
|
||||||
mContentModel = new ContentSelectorModel::ContentModel(this, warningIcon, showOMWScripts);
|
QIcon errorIcon(ui->addonView->style()->standardIcon(QStyle::SP_MessageBoxCritical));
|
||||||
|
mContentModel = new ContentSelectorModel::ContentModel(this, warningIcon, errorIcon, showOMWScripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentSelectorView::ContentSelector::buildGameFileView()
|
void ContentSelectorView::ContentSelector::buildGameFileView()
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source><b>This file is specified in a non-user config file, but does not exist in the VFS.</b></source>
|
||||||
|
<translation><b>Diese Datei ist in einer Nicht-Benutzerkonfigurationsdatei angegeben, existiert aber nicht im VFS.</b></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ContentSelectorView::ContentSelector</name>
|
<name>ContentSelectorView::ContentSelector</name>
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
<source><b>Author:</b> %1<br/><b>Format version:</b> %2<br/><b>Modified:</b> %3<br/><b>Path:</b><br/>%4<br/><br/><b>Description:</b><br/>%5<br/><br/><b>Dependencies: </b>%6<br/></source>
|
<source><b>Author:</b> %1<br/><b>Format version:</b> %2<br/><b>Modified:</b> %3<br/><b>Path:</b><br/>%4<br/><br/><b>Description:</b><br/>%5<br/><br/><b>Dependencies: </b>%6<br/></source>
|
||||||
<translation></translation>
|
<translation></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source><b>This file is specified in a non-user config file, but does not exist in the VFS.</b></source>
|
||||||
|
<translation></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ContentSelectorView::ContentSelector</name>
|
<name>ContentSelectorView::ContentSelector</name>
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
||||||
<translation><br/><b>Ce fichier de contenu ne peut être désactivé, car il est activé par un fichier de configuration non contrôlé par l'utilisateur.</b><br/></translation>
|
<translation><br/><b>Ce fichier de contenu ne peut être désactivé, car il est activé par un fichier de configuration non contrôlé par l'utilisateur.</b><br/></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source><b>This file is specified in a non-user config file, but does not exist in the VFS.</b></source>
|
||||||
|
<translation><b>Ce fichier est spécifié dans un ficher de configuration non contrôlé par l'utilisateur, mais ne semble pas exister.</b></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ContentSelectorView::ContentSelector</name>
|
<name>ContentSelectorView::ContentSelector</name>
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
||||||
<translation><br/><b>Этот файл данных не может быть отключен, потому что он включен в файле с настройками, не являющемся пользовательским.</b><br/></translation>
|
<translation><br/><b>Этот файл данных не может быть отключен, потому что он включен в файле с настройками, не являющемся пользовательским.</b><br/></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source><b>This file is specified in a non-user config file, but does not exist in the VFS.</b></source>
|
||||||
|
<translation><b>Этот файл указан в непользовательском файле настроек, но не существует в виртуальной файловой системе.</b></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ContentSelectorView::ContentSelector</name>
|
<name>ContentSelectorView::ContentSelector</name>
|
||||||
|
@ -37,6 +37,10 @@
|
|||||||
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
<source><br/><b>This content file cannot be disabled because it is enabled in a config file other than the user one.</b><br/></source>
|
||||||
<translation><br/><b>Denna innehållsfil kan inte inaktiveras då den är en aktiverad i en annan konfigurationsfil än användarens.</b><br/></translation>
|
<translation><br/><b>Denna innehållsfil kan inte inaktiveras då den är en aktiverad i en annan konfigurationsfil än användarens.</b><br/></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source><b>This file is specified in a non-user config file, but does not exist in the VFS.</b></source>
|
||||||
|
<translation><b>Den här filen anges i en konfigfil som inte är avsedd för användare, men den finns inte i det virtuella filsystemet.</b></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>ContentSelectorView::ContentSelector</name>
|
<name>ContentSelectorView::ContentSelector</name>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user