mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 03:40:14 +00:00
Merge remote-tracking branch 'dteviot/FixLoadOrderReset'
This commit is contained in:
commit
d254bb0a34
@ -94,20 +94,28 @@ bool Launcher::DataFilesPage::loadSettings()
|
||||
if (!currentProfile.isEmpty())
|
||||
addProfile(currentProfile, true);
|
||||
|
||||
QStringList files = mLauncherSettings.values(QString("Profiles/") + currentProfile + QString("/content"), Qt::MatchExactly);
|
||||
mSelector->setProfileContent(filesInProfile(currentProfile, pathIterator));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList Launcher::DataFilesPage::filesInProfile(const QString& profileName, PathIterator& pathIterator)
|
||||
{
|
||||
QStringList files = mLauncherSettings.values(QString("Profiles/") + profileName + QString("/content"), Qt::MatchExactly);
|
||||
QStringList filepaths;
|
||||
|
||||
foreach (const QString &file, files)
|
||||
// mLauncherSettings.values() returns the files in reverse load order
|
||||
QListIterator<QString> i(files);
|
||||
i.toBack();
|
||||
while (i.hasPrevious())
|
||||
{
|
||||
QString filepath = pathIterator.findFirstPath (file);
|
||||
QString filepath = pathIterator.findFirstPath(i.previous());
|
||||
|
||||
if (!filepath.isEmpty())
|
||||
filepaths << filepath;
|
||||
}
|
||||
|
||||
mSelector->setProfileContent (filepaths);
|
||||
|
||||
return true;
|
||||
return filepaths;
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::saveSettings(const QString &profile)
|
||||
|
@ -134,6 +134,8 @@ namespace Launcher
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
QStringList filesInProfile(const QString& profileName, PathIterator& pathIterator);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
@ -133,6 +133,7 @@ if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
|
||||
add_component_qt_dir (contentselector
|
||||
model/modelitem model/esmfile
|
||||
model/naturalsort model/contentmodel
|
||||
model/loadordererror
|
||||
view/combobox view/contentselector
|
||||
)
|
||||
add_component_qt_dir (config
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QDir>
|
||||
#include <QTextCodec>
|
||||
#include <QDebug>
|
||||
#include <QBrush>
|
||||
|
||||
#include "components/esm/esmreader.hpp"
|
||||
|
||||
@ -176,6 +177,16 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex &index, int
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::ForegroundRole:
|
||||
{
|
||||
if (isLoadOrderError(file))
|
||||
{
|
||||
QBrush redBackground(Qt::red, Qt::SolidPattern);
|
||||
return redBackground;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::EditRole:
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
@ -205,7 +216,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex &index, int
|
||||
if (column != 0)
|
||||
return QVariant();
|
||||
|
||||
return file->toolTip();
|
||||
return toolTip(file);
|
||||
}
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
@ -290,7 +301,7 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex &index, const
|
||||
{
|
||||
setCheckState(file->filePath(), success);
|
||||
emit dataChanged(index, index);
|
||||
|
||||
checkForLoadOrderErrors();
|
||||
}
|
||||
else
|
||||
return success;
|
||||
@ -340,6 +351,8 @@ bool ContentSelectorModel::ContentModel::removeRows(int position, int rows, cons
|
||||
|
||||
} endRemoveRows();
|
||||
|
||||
// at this point we know that drag and drop has finished.
|
||||
checkForLoadOrderErrors();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -531,11 +544,95 @@ bool ContentSelectorModel::ContentModel::isEnabled (QModelIndex index) const
|
||||
return (flags(index) & Qt::ItemIsEnabled);
|
||||
}
|
||||
|
||||
void ContentSelectorModel::ContentModel::setCheckStates (const QStringList &fileList, bool isChecked)
|
||||
bool ContentSelectorModel::ContentModel::isLoadOrderError(const EsmFile *file) const
|
||||
{
|
||||
foreach (const QString &file, fileList)
|
||||
return mPluginsWithLoadOrderError.contains(file->filePath());
|
||||
}
|
||||
|
||||
void ContentSelectorModel::ContentModel::setContentList(const QStringList &fileList, bool isChecked)
|
||||
{
|
||||
mPluginsWithLoadOrderError.clear();
|
||||
int previousPosition = -1;
|
||||
foreach (const QString &filepath, fileList)
|
||||
{
|
||||
setCheckState (file, isChecked);
|
||||
if (setCheckState(filepath, isChecked))
|
||||
{
|
||||
// as necessary, move plug-ins in visible list to match sequence of supplied filelist
|
||||
const EsmFile* file = item(filepath);
|
||||
int filePosition = indexFromItem(file).row();
|
||||
if (filePosition < previousPosition)
|
||||
{
|
||||
mFiles.move(filePosition, previousPosition);
|
||||
emit dataChanged(index(filePosition, 0, QModelIndex()), index(previousPosition, 0, QModelIndex()));
|
||||
}
|
||||
else
|
||||
{
|
||||
previousPosition = filePosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkForLoadOrderErrors();
|
||||
}
|
||||
|
||||
void ContentSelectorModel::ContentModel::checkForLoadOrderErrors()
|
||||
{
|
||||
for (int row = 0; row < mFiles.count(); ++row)
|
||||
{
|
||||
EsmFile* file = item(row);
|
||||
bool isRowInError = checkForLoadOrderErrors(file, row).count() != 0;
|
||||
if (isRowInError)
|
||||
{
|
||||
mPluginsWithLoadOrderError.insert(file->filePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
mPluginsWithLoadOrderError.remove(file->filePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<ContentSelectorModel::LoadOrderError> ContentSelectorModel::ContentModel::checkForLoadOrderErrors(const EsmFile *file, int row) const
|
||||
{
|
||||
QList<LoadOrderError> errors = QList<LoadOrderError>();
|
||||
foreach(QString dependentfileName, file->gameFiles())
|
||||
{
|
||||
const EsmFile* dependentFile = item(dependentfileName);
|
||||
|
||||
if (!dependentFile)
|
||||
{
|
||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_MissingDependency, dependentfileName));
|
||||
}
|
||||
if (!isChecked(dependentFile->filePath()))
|
||||
{
|
||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_InactiveDependency, dependentfileName));
|
||||
}
|
||||
if (row < indexFromItem(dependentFile).row())
|
||||
{
|
||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_LoadOrder, dependentfileName));
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
QString ContentSelectorModel::ContentModel::toolTip(const EsmFile *file) const
|
||||
{
|
||||
if (isLoadOrderError(file))
|
||||
{
|
||||
QString text("<font color=#840000><b>");
|
||||
int index = indexFromItem(item(file->filePath())).row();
|
||||
foreach(const LoadOrderError& error, checkForLoadOrderErrors(file, index))
|
||||
{
|
||||
text += "<p>";
|
||||
text += error.toolTip();
|
||||
text += "</p>";
|
||||
}
|
||||
text += ("</b></font>");
|
||||
text += file->toolTip();
|
||||
return text;
|
||||
}
|
||||
else
|
||||
{
|
||||
return file->toolTip();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QStringList>
|
||||
#include <QSet>
|
||||
|
||||
#include "loadordererror.hpp"
|
||||
|
||||
namespace ContentSelectorModel
|
||||
{
|
||||
@ -48,7 +51,7 @@ namespace ContentSelectorModel
|
||||
bool isEnabled (QModelIndex index) const;
|
||||
bool isChecked(const QString &filepath) const;
|
||||
bool setCheckState(const QString &filepath, bool isChecked);
|
||||
void setCheckStates (const QStringList &fileList, bool isChecked);
|
||||
void setContentList(const QStringList &fileList, bool isChecked);
|
||||
ContentFileList checkedItems() const;
|
||||
void uncheckAll();
|
||||
|
||||
@ -62,8 +65,21 @@ namespace ContentSelectorModel
|
||||
|
||||
void sortFiles();
|
||||
|
||||
/// Checks all plug-ins for load order errors and updates mPluginsWithLoadOrderError with plug-ins with issues
|
||||
void checkForLoadOrderErrors();
|
||||
|
||||
/// Checks a specific plug-in for load order errors
|
||||
/// \return all errors found for specific plug-in
|
||||
QList<LoadOrderError> checkForLoadOrderErrors(const EsmFile *file, int row) const;
|
||||
|
||||
/// \return true if plug-in has a Load Order error
|
||||
bool isLoadOrderError(const EsmFile *file) const;
|
||||
|
||||
QString toolTip(const EsmFile *file) const;
|
||||
|
||||
ContentFileList mFiles;
|
||||
QHash<QString, Qt::CheckState> mCheckStates;
|
||||
QSet<QString> mPluginsWithLoadOrderError;
|
||||
QTextCodec *mCodec;
|
||||
QString mEncoding;
|
||||
|
||||
|
15
components/contentselector/model/loadordererror.cpp
Normal file
15
components/contentselector/model/loadordererror.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "loadordererror.hpp"
|
||||
#include <assert.h>
|
||||
|
||||
QString ContentSelectorModel::LoadOrderError::sErrorToolTips[ErrorCode_LoadOrder] =
|
||||
{
|
||||
QString("Unable to find dependent file: %1"),
|
||||
QString("Dependent file needs to be active: %1"),
|
||||
QString("This file needs to load after %1")
|
||||
};
|
||||
|
||||
QString ContentSelectorModel::LoadOrderError::toolTip() const
|
||||
{
|
||||
assert(mErrorCode);
|
||||
return sErrorToolTips[mErrorCode - 1].arg(mFileName);
|
||||
}
|
37
components/contentselector/model/loadordererror.hpp
Normal file
37
components/contentselector/model/loadordererror.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef LOADORDERERROR_HPP
|
||||
#define LOADORDERERROR_HPP
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace ContentSelectorModel
|
||||
{
|
||||
/// \brief Details of a suspected Load Order problem a plug-in will have. This is basically a POD.
|
||||
class LoadOrderError
|
||||
{
|
||||
public:
|
||||
enum ErrorCode
|
||||
{
|
||||
ErrorCode_None = 0,
|
||||
ErrorCode_MissingDependency = 1,
|
||||
ErrorCode_InactiveDependency = 2,
|
||||
ErrorCode_LoadOrder = 3
|
||||
};
|
||||
|
||||
inline LoadOrderError() : mErrorCode(ErrorCode_None) {};
|
||||
inline LoadOrderError(ErrorCode errorCode, QString fileName)
|
||||
{
|
||||
mErrorCode = errorCode;
|
||||
mFileName = fileName;
|
||||
}
|
||||
inline ErrorCode errorCode() const { return mErrorCode; }
|
||||
inline QString fileName() const { return mFileName; }
|
||||
QString toolTip() const;
|
||||
|
||||
private:
|
||||
ErrorCode mErrorCode;
|
||||
QString mFileName;
|
||||
static QString sErrorToolTips[ErrorCode_LoadOrder];
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LOADORDERERROR_HPP
|
@ -75,7 +75,7 @@ void ContentSelectorView::ContentSelector::setProfileContent(const QStringList &
|
||||
}
|
||||
}
|
||||
|
||||
setCheckStates (fileList);
|
||||
setContentList(fileList);
|
||||
}
|
||||
|
||||
void ContentSelectorView::ContentSelector::setGameFile(const QString &filename)
|
||||
@ -103,14 +103,14 @@ void ContentSelectorView::ContentSelector::clearCheckStates()
|
||||
mContentModel->uncheckAll();
|
||||
}
|
||||
|
||||
void ContentSelectorView::ContentSelector::setCheckStates(const QStringList &list)
|
||||
void ContentSelectorView::ContentSelector::setContentList(const QStringList &list)
|
||||
{
|
||||
if (list.isEmpty())
|
||||
{
|
||||
slotCurrentGameFileIndexChanged (ui.gameFileView->currentIndex());
|
||||
}
|
||||
else
|
||||
mContentModel->setCheckStates (list, true);
|
||||
mContentModel->setContentList(list, true);
|
||||
}
|
||||
|
||||
ContentSelectorModel::ContentFileList
|
||||
|
@ -32,7 +32,7 @@ namespace ContentSelectorView
|
||||
void setProfileContent (const QStringList &fileList);
|
||||
|
||||
void clearCheckStates();
|
||||
void setCheckStates (const QStringList &list);
|
||||
void setContentList(const QStringList &list);
|
||||
|
||||
ContentSelectorModel::ContentFileList selectedFiles() const;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user