1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 12:39:55 +00:00

Merge remote-tracking branch 'dteviot/FixLoadOrderReset'

This commit is contained in:
Marc Zinnschlag 2015-01-09 09:32:23 +01:00
commit d254bb0a34
9 changed files with 192 additions and 16 deletions

View File

@ -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)

View File

@ -134,6 +134,8 @@ namespace Launcher
}
};
QStringList filesInProfile(const QString& profileName, PathIterator& pathIterator);
};
}
#endif

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;

View 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);
}

View 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

View File

@ -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

View File

@ -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;