mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 15:09:43 +00:00
Merge branch 'pickme' into 'master'
Override launcher file info with higher priority info Closes #7733 and #7103 See merge request OpenMW/openmw!3743
This commit is contained in:
commit
78d8cf86c3
8 changed files with 78 additions and 126 deletions
|
@ -64,6 +64,7 @@
|
||||||
Bug #7084: Resurrecting an actor doesn't take into account base record changes
|
Bug #7084: Resurrecting an actor doesn't take into account base record changes
|
||||||
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
Bug #7088: Deleting last save game of last character doesn't clear character name/details
|
||||||
Bug #7092: BSA archives from higher priority directories don't take priority
|
Bug #7092: BSA archives from higher priority directories don't take priority
|
||||||
|
Bug #7103: Multiple paths pointing to the same plugin but with different cases lead to automatically removed config entries
|
||||||
Bug #7122: Teleportation to underwater should cancel active water walking effect
|
Bug #7122: Teleportation to underwater should cancel active water walking effect
|
||||||
Bug #7131: MyGUI log spam when post processing HUD is open
|
Bug #7131: MyGUI log spam when post processing HUD is open
|
||||||
Bug #7134: Saves with an invalid last generated RefNum can be loaded
|
Bug #7134: Saves with an invalid last generated RefNum can be loaded
|
||||||
|
@ -121,6 +122,7 @@
|
||||||
Bug #7712: Casting doesn't support spells and enchantments with no effects
|
Bug #7712: Casting doesn't support spells and enchantments with no effects
|
||||||
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
|
Bug #7723: Assaulting vampires and werewolves shouldn't be a crime
|
||||||
Bug #7724: Guards don't help vs werewolves
|
Bug #7724: Guards don't help vs werewolves
|
||||||
|
Bug #7733: Launcher shows incorrect data paths when there's two plugins with the same name
|
||||||
Bug #7742: Governing attribute training limit should use the modified attribute
|
Bug #7742: Governing attribute training limit should use the modified attribute
|
||||||
Bug #7758: Water walking is not taken into account to compute path cost on the water
|
Bug #7758: Water walking is not taken into account to compute path cost on the water
|
||||||
Bug #7761: Rain and ambient loop sounds are mutually exclusive
|
Bug #7761: Rain and ambient loop sounds are mutually exclusive
|
||||||
|
|
|
@ -125,27 +125,6 @@ namespace Launcher
|
||||||
{
|
{
|
||||||
return Settings::navigator().mMaxNavmeshdbFileSize / (1024 * 1024);
|
return Settings::navigator().mMaxNavmeshdbFileSize / (1024 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> findFirstPath(const QStringList& directories, const QString& fileName)
|
|
||||||
{
|
|
||||||
for (const QString& directoryPath : directories)
|
|
||||||
{
|
|
||||||
const QString filePath = QDir(directoryPath).absoluteFilePath(fileName);
|
|
||||||
if (QFile::exists(filePath))
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList findAllFilePaths(const QStringList& directories, const QStringList& fileNames)
|
|
||||||
{
|
|
||||||
QStringList result;
|
|
||||||
result.reserve(fileNames.size());
|
|
||||||
for (const QString& fileName : fileNames)
|
|
||||||
if (const auto filepath = findFirstPath(directories, fileName))
|
|
||||||
result.append(*filepath);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,8 +345,7 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
mSelector->setProfileContent(
|
mSelector->setProfileContent(mLauncherSettings.getContentListFiles(contentModelName));
|
||||||
findAllFilePaths(directories, mLauncherSettings.getContentListFiles(contentModelName)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
||||||
|
|
|
@ -2,12 +2,15 @@
|
||||||
#include "esmfile.hpp"
|
#include "esmfile.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
#include <QIODevice>
|
||||||
|
|
||||||
#include <components/esm/format.hpp>
|
#include <components/esm/format.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
@ -127,7 +130,7 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex& index
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
noGameFiles = false;
|
noGameFiles = false;
|
||||||
if (isChecked(depFile->filePath()))
|
if (mCheckedFiles.contains(depFile))
|
||||||
{
|
{
|
||||||
gamefileChecked = true;
|
gamefileChecked = true;
|
||||||
break;
|
break;
|
||||||
|
@ -214,7 +217,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
|
||||||
if (file == mGameFile)
|
if (file == mGameFile)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
return mCheckStates[file->filePath()];
|
return mCheckedFiles.contains(file) ? Qt::Checked : Qt::Unchecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::UserRole:
|
case Qt::UserRole:
|
||||||
|
@ -228,7 +231,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int
|
||||||
}
|
}
|
||||||
|
|
||||||
case Qt::UserRole + 1:
|
case Qt::UserRole + 1:
|
||||||
return isChecked(file->filePath());
|
return mCheckedFiles.contains(file);
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -276,12 +279,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) && !isChecked(file->filePath()))
|
if (checkValue == Qt::Checked && !mCheckedFiles.contains(file))
|
||||||
{
|
{
|
||||||
setState = true;
|
setState = true;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else if ((checkValue == Qt::Checked) && isChecked(file->filePath()))
|
else if (checkValue == Qt::Checked && mCheckedFiles.contains(file))
|
||||||
setState = true;
|
setState = true;
|
||||||
else if (checkValue == Qt::Unchecked)
|
else if (checkValue == Qt::Unchecked)
|
||||||
setState = true;
|
setState = true;
|
||||||
|
@ -314,34 +317,12 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const
|
||||||
|
|
||||||
bool ContentSelectorModel::ContentModel::insertRows(int position, int rows, const QModelIndex& parent)
|
bool ContentSelectorModel::ContentModel::insertRows(int position, int rows, const QModelIndex& parent)
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
beginInsertRows(parent, position, position + rows - 1);
|
|
||||||
{
|
|
||||||
for (int row = 0; row < rows; ++row)
|
|
||||||
mFiles.insert(position, new EsmFile);
|
|
||||||
}
|
|
||||||
endInsertRows();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContentSelectorModel::ContentModel::removeRows(int position, int rows, const QModelIndex& parent)
|
bool ContentSelectorModel::ContentModel::removeRows(int position, int rows, const QModelIndex& parent)
|
||||||
{
|
{
|
||||||
if (parent.isValid())
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
beginRemoveRows(parent, position, position + rows - 1);
|
|
||||||
{
|
|
||||||
for (int row = 0; row < rows; ++row)
|
|
||||||
delete mFiles.takeAt(position);
|
|
||||||
}
|
|
||||||
endRemoveRows();
|
|
||||||
|
|
||||||
// at this point we know that drag and drop has finished.
|
|
||||||
checkForLoadOrderErrors();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::DropActions ContentSelectorModel::ContentModel::supportedDropActions() const
|
Qt::DropActions ContentSelectorModel::ContentModel::supportedDropActions() const
|
||||||
|
@ -357,13 +338,14 @@ QStringList ContentSelectorModel::ContentModel::mimeTypes() const
|
||||||
QMimeData* ContentSelectorModel::ContentModel::mimeData(const QModelIndexList& indexes) const
|
QMimeData* ContentSelectorModel::ContentModel::mimeData(const QModelIndexList& indexes) const
|
||||||
{
|
{
|
||||||
QByteArray encodedData;
|
QByteArray encodedData;
|
||||||
|
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
||||||
|
|
||||||
for (const QModelIndex& index : indexes)
|
for (const QModelIndex& index : indexes)
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
encodedData.append(item(index.row())->encodedData());
|
stream << index.row();
|
||||||
}
|
}
|
||||||
|
|
||||||
QMimeData* mimeData = new QMimeData();
|
QMimeData* mimeData = new QMimeData();
|
||||||
|
@ -395,26 +377,31 @@ bool ContentSelectorModel::ContentModel::dropMimeData(
|
||||||
QByteArray encodedData = data->data(mMimeType);
|
QByteArray encodedData = data->data(mMimeType);
|
||||||
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
QDataStream stream(&encodedData, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
std::vector<EsmFile*> toMove;
|
||||||
while (!stream.atEnd())
|
while (!stream.atEnd())
|
||||||
{
|
{
|
||||||
|
int sourceRow;
|
||||||
QString value;
|
stream >> sourceRow;
|
||||||
QStringList values;
|
toMove.emplace_back(mFiles.at(sourceRow));
|
||||||
QStringList gamefiles;
|
|
||||||
|
|
||||||
for (int i = 0; i < EsmFile::FileProperty_GameFile; ++i)
|
|
||||||
{
|
|
||||||
stream >> value;
|
|
||||||
values << value;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream >> gamefiles;
|
|
||||||
|
|
||||||
insertRows(beginRow, 1);
|
|
||||||
|
|
||||||
QModelIndex idx = index(beginRow++, 0, QModelIndex());
|
|
||||||
setData(idx, QStringList() << values << gamefiles, Qt::EditRole);
|
|
||||||
}
|
}
|
||||||
|
int minRow = mFiles.size();
|
||||||
|
int maxRow = 0;
|
||||||
|
for (EsmFile* file : toMove)
|
||||||
|
{
|
||||||
|
int from = mFiles.indexOf(file);
|
||||||
|
int to = beginRow;
|
||||||
|
if (from < beginRow)
|
||||||
|
to--;
|
||||||
|
else if (from > beginRow)
|
||||||
|
beginRow++;
|
||||||
|
minRow = std::min(minRow, std::min(to, from));
|
||||||
|
maxRow = std::max(maxRow, std::max(to, from));
|
||||||
|
mFiles.move(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataChanged(index(minRow, 0), index(maxRow, 0));
|
||||||
|
// at this point we know that drag and drop has finished.
|
||||||
|
checkForLoadOrderErrors();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -447,26 +434,37 @@ void ContentSelectorModel::ContentModel::addFiles(const QString& path, bool newf
|
||||||
{
|
{
|
||||||
QFileInfo info(dir.absoluteFilePath(path2));
|
QFileInfo info(dir.absoluteFilePath(path2));
|
||||||
|
|
||||||
if (item(info.fileName()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Enabled by default in system openmw.cfg; shouldn't be shown in content list.
|
// Enabled by default in system openmw.cfg; shouldn't be shown in content list.
|
||||||
if (info.fileName().compare("builtin.omwscripts", Qt::CaseInsensitive) == 0)
|
if (info.fileName().compare("builtin.omwscripts", Qt::CaseInsensitive) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
EsmFile* file = const_cast<EsmFile*>(item(info.fileName()));
|
||||||
|
bool add = file == nullptr;
|
||||||
|
std::unique_ptr<EsmFile> newFile;
|
||||||
|
if (add)
|
||||||
|
{
|
||||||
|
newFile = std::make_unique<EsmFile>(path2);
|
||||||
|
file = newFile.get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We've found the same file in a higher priority dir, update our existing entry
|
||||||
|
file->setFileName(path2);
|
||||||
|
file->setGameFiles({});
|
||||||
|
}
|
||||||
|
|
||||||
if (info.fileName().endsWith(".omwscripts", Qt::CaseInsensitive))
|
if (info.fileName().endsWith(".omwscripts", Qt::CaseInsensitive))
|
||||||
{
|
{
|
||||||
EsmFile* file = new EsmFile(path2);
|
|
||||||
file->setDate(info.lastModified());
|
file->setDate(info.lastModified());
|
||||||
file->setFilePath(info.absoluteFilePath());
|
file->setFilePath(info.absoluteFilePath());
|
||||||
addFile(file);
|
if (add)
|
||||||
|
addFile(newFile.release());
|
||||||
setNew(file->fileName(), newfiles);
|
setNew(file->fileName(), newfiles);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
EsmFile* file = new EsmFile(path2);
|
|
||||||
file->setDate(info.lastModified());
|
file->setDate(info.lastModified());
|
||||||
file->setFilePath(info.absoluteFilePath());
|
file->setFilePath(info.absoluteFilePath());
|
||||||
std::filesystem::path filepath = Files::pathFromQString(info.absoluteFilePath());
|
std::filesystem::path filepath = Files::pathFromQString(info.absoluteFilePath());
|
||||||
|
@ -522,14 +520,14 @@ void ContentSelectorModel::ContentModel::addFiles(const QString& path, bool newf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the file in the table
|
// Put the file in the table
|
||||||
addFile(file);
|
if (add)
|
||||||
|
addFile(newFile.release());
|
||||||
setNew(file->fileName(), newfiles);
|
setNew(file->fileName(), newfiles);
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& e)
|
catch (std::runtime_error& e)
|
||||||
{
|
{
|
||||||
// An error occurred while reading the .esp
|
// An error occurred while reading the .esp
|
||||||
qWarning() << "Error reading addon file: " << e.what();
|
qWarning() << "Error reading addon file: " << e.what();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,6 +552,7 @@ void ContentSelectorModel::ContentModel::clearFiles()
|
||||||
if (filesCount > 0)
|
if (filesCount > 0)
|
||||||
{
|
{
|
||||||
beginRemoveRows(QModelIndex(), 0, filesCount - 1);
|
beginRemoveRows(QModelIndex(), 0, filesCount - 1);
|
||||||
|
qDeleteAll(mFiles);
|
||||||
mFiles.clear();
|
mFiles.clear();
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
@ -616,14 +615,6 @@ void ContentSelectorModel::ContentModel::sortFiles()
|
||||||
emit layoutChanged();
|
emit layoutChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ContentSelectorModel::ContentModel::isChecked(const QString& filepath) const
|
|
||||||
{
|
|
||||||
const auto it = mCheckStates.find(filepath);
|
|
||||||
if (it == mCheckStates.end())
|
|
||||||
return false;
|
|
||||||
return it.value() == Qt::Checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContentSelectorModel::ContentModel::isEnabled(const QModelIndex& index) const
|
bool ContentSelectorModel::ContentModel::isEnabled(const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
return (flags(index) & Qt::ItemIsEnabled);
|
return (flags(index) & Qt::ItemIsEnabled);
|
||||||
|
@ -684,7 +675,7 @@ void ContentSelectorModel::ContentModel::checkForLoadOrderErrors()
|
||||||
{
|
{
|
||||||
for (int row = 0; row < mFiles.count(); ++row)
|
for (int row = 0; row < mFiles.count(); ++row)
|
||||||
{
|
{
|
||||||
EsmFile* file = item(row);
|
EsmFile* file = mFiles.at(row);
|
||||||
bool isRowInError = checkForLoadOrderErrors(file, row).count() != 0;
|
bool isRowInError = checkForLoadOrderErrors(file, row).count() != 0;
|
||||||
if (isRowInError)
|
if (isRowInError)
|
||||||
{
|
{
|
||||||
|
@ -711,7 +702,7 @@ QList<ContentSelectorModel::LoadOrderError> ContentSelectorModel::ContentModel::
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!isChecked(dependentFile->filePath()))
|
if (!mCheckedFiles.contains(dependentFile))
|
||||||
{
|
{
|
||||||
errors.append(LoadOrderError(LoadOrderError::ErrorCode_InactiveDependency, dependentfileName));
|
errors.append(LoadOrderError(LoadOrderError::ErrorCode_InactiveDependency, dependentfileName));
|
||||||
}
|
}
|
||||||
|
@ -761,19 +752,18 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath,
|
||||||
if (!file)
|
if (!file)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Qt::CheckState state = Qt::Unchecked;
|
|
||||||
|
|
||||||
if (checkState)
|
if (checkState)
|
||||||
state = Qt::Checked;
|
mCheckedFiles.insert(file);
|
||||||
|
else
|
||||||
|
mCheckedFiles.erase(file);
|
||||||
|
|
||||||
mCheckStates[filepath] = state;
|
|
||||||
emit dataChanged(indexFromItem(item(filepath)), indexFromItem(item(filepath)));
|
emit dataChanged(indexFromItem(item(filepath)), indexFromItem(item(filepath)));
|
||||||
|
|
||||||
if (file->isGameFile())
|
if (file->isGameFile())
|
||||||
refreshModel();
|
refreshModel();
|
||||||
|
|
||||||
// if we're checking an item, ensure all "upstream" files (dependencies) are checked as well.
|
// if we're checking an item, ensure all "upstream" files (dependencies) are checked as well.
|
||||||
if (state == Qt::Checked)
|
if (checkState)
|
||||||
{
|
{
|
||||||
for (const QString& upstreamName : file->gameFiles())
|
for (const QString& upstreamName : file->gameFiles())
|
||||||
{
|
{
|
||||||
|
@ -782,14 +772,13 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath,
|
||||||
if (!upstreamFile)
|
if (!upstreamFile)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!isChecked(upstreamFile->filePath()))
|
mCheckedFiles.insert(upstreamFile);
|
||||||
mCheckStates[upstreamFile->filePath()] = Qt::Checked;
|
|
||||||
|
|
||||||
emit dataChanged(indexFromItem(upstreamFile), indexFromItem(upstreamFile));
|
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.
|
// otherwise, if we're unchecking an item (or the file is a game file) ensure all downstream files are unchecked.
|
||||||
if (state == Qt::Unchecked)
|
else
|
||||||
{
|
{
|
||||||
for (const EsmFile* downstreamFile : mFiles)
|
for (const EsmFile* downstreamFile : mFiles)
|
||||||
{
|
{
|
||||||
|
@ -798,8 +787,7 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath,
|
||||||
|
|
||||||
if (downstreamFile->gameFiles().contains(filename, Qt::CaseInsensitive))
|
if (downstreamFile->gameFiles().contains(filename, Qt::CaseInsensitive))
|
||||||
{
|
{
|
||||||
if (mCheckStates.contains(downstreamFile->filePath()))
|
mCheckedFiles.erase(downstreamFile);
|
||||||
mCheckStates[downstreamFile->filePath()] = Qt::Unchecked;
|
|
||||||
|
|
||||||
emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile));
|
emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile));
|
||||||
}
|
}
|
||||||
|
@ -817,7 +805,7 @@ ContentSelectorModel::ContentFileList ContentSelectorModel::ContentModel::checke
|
||||||
// First search for game files and next addons,
|
// First search for game files and next addons,
|
||||||
// so we get more or less correct game files vs addons order.
|
// so we get more or less correct game files vs addons order.
|
||||||
for (EsmFile* file : mFiles)
|
for (EsmFile* file : mFiles)
|
||||||
if (isChecked(file->filePath()))
|
if (mCheckedFiles.contains(file))
|
||||||
list << file;
|
list << file;
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -826,6 +814,6 @@ ContentSelectorModel::ContentFileList ContentSelectorModel::ContentModel::checke
|
||||||
void ContentSelectorModel::ContentModel::uncheckAll()
|
void ContentSelectorModel::ContentModel::uncheckAll()
|
||||||
{
|
{
|
||||||
emit layoutAboutToBeChanged();
|
emit layoutAboutToBeChanged();
|
||||||
mCheckStates.clear();
|
mCheckedFiles.clear();
|
||||||
emit layoutChanged();
|
emit layoutChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace ContentSelectorModel
|
namespace ContentSelectorModel
|
||||||
{
|
{
|
||||||
class EsmFile;
|
class EsmFile;
|
||||||
|
@ -57,7 +59,6 @@ namespace ContentSelectorModel
|
||||||
void setCurrentGameFile(const EsmFile* file);
|
void setCurrentGameFile(const EsmFile* file);
|
||||||
|
|
||||||
bool isEnabled(const QModelIndex& index) const;
|
bool isEnabled(const QModelIndex& index) const;
|
||||||
bool isChecked(const QString& filepath) const;
|
|
||||||
bool setCheckState(const QString& filepath, bool isChecked);
|
bool setCheckState(const QString& filepath, bool isChecked);
|
||||||
bool isNew(const QString& filepath) const;
|
bool isNew(const QString& filepath) const;
|
||||||
void setNew(const QString& filepath, bool isChecked);
|
void setNew(const QString& filepath, bool isChecked);
|
||||||
|
@ -85,7 +86,7 @@ namespace ContentSelectorModel
|
||||||
const EsmFile* mGameFile;
|
const EsmFile* mGameFile;
|
||||||
ContentFileList mFiles;
|
ContentFileList mFiles;
|
||||||
QStringList mArchives;
|
QStringList mArchives;
|
||||||
QHash<QString, Qt::CheckState> mCheckStates;
|
std::set<const EsmFile*> mCheckedFiles;
|
||||||
QHash<QString, bool> mNewFiles;
|
QHash<QString, bool> mNewFiles;
|
||||||
QSet<QString> mPluginsWithLoadOrderError;
|
QSet<QString> mPluginsWithLoadOrderError;
|
||||||
QString mEncoding;
|
QString mEncoding;
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
#include "esmfile.hpp"
|
#include "esmfile.hpp"
|
||||||
|
|
||||||
#include <QDataStream>
|
|
||||||
#include <QIODevice>
|
|
||||||
|
|
||||||
int ContentSelectorModel::EsmFile::sPropertyCount = 7;
|
|
||||||
|
|
||||||
ContentSelectorModel::EsmFile::EsmFile(const QString& fileName, ModelItem* parent)
|
ContentSelectorModel::EsmFile::EsmFile(const QString& fileName, ModelItem* parent)
|
||||||
: ModelItem(parent)
|
: ModelItem(parent)
|
||||||
, mFileName(fileName)
|
, mFileName(fileName)
|
||||||
|
@ -46,17 +41,6 @@ void ContentSelectorModel::EsmFile::setDescription(const QString& description)
|
||||||
mDescription = description;
|
mDescription = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ContentSelectorModel::EsmFile::encodedData() const
|
|
||||||
{
|
|
||||||
QByteArray encodedData;
|
|
||||||
QDataStream stream(&encodedData, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
stream << mFileName << mAuthor << mVersion << mModified.toString(Qt::ISODate) << mPath << mDescription
|
|
||||||
<< mGameFiles;
|
|
||||||
|
|
||||||
return encodedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContentSelectorModel::EsmFile::isGameFile() const
|
bool ContentSelectorModel::EsmFile::isGameFile() const
|
||||||
{
|
{
|
||||||
return (mGameFiles.size() == 0)
|
return (mGameFiles.size() == 0)
|
||||||
|
|
|
@ -30,15 +30,11 @@ namespace ContentSelectorModel
|
||||||
};
|
};
|
||||||
|
|
||||||
EsmFile(const QString& fileName = QString(), ModelItem* parent = nullptr);
|
EsmFile(const QString& fileName = QString(), ModelItem* parent = nullptr);
|
||||||
// EsmFile(const EsmFile &);
|
|
||||||
|
|
||||||
~EsmFile() {}
|
|
||||||
|
|
||||||
void setFileProperty(const FileProperty prop, const QString& value);
|
void setFileProperty(const FileProperty prop, const QString& value);
|
||||||
|
|
||||||
void setFileName(const QString& fileName);
|
void setFileName(const QString& fileName);
|
||||||
void setAuthor(const QString& author);
|
void setAuthor(const QString& author);
|
||||||
void setSize(const int size);
|
|
||||||
void setDate(const QDateTime& modified);
|
void setDate(const QDateTime& modified);
|
||||||
void setFormat(const QString& format);
|
void setFormat(const QString& format);
|
||||||
void setFilePath(const QString& path);
|
void setFilePath(const QString& path);
|
||||||
|
@ -68,10 +64,6 @@ namespace ContentSelectorModel
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isGameFile() const;
|
bool isGameFile() const;
|
||||||
QByteArray encodedData() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static int sPropertyCount;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString mTooltipTemlate = tr(
|
QString mTooltipTemlate = tr(
|
||||||
|
|
|
@ -108,6 +108,7 @@ void ContentSelectorView::ContentSelector::buildAddonView()
|
||||||
connect(ui->addonView, &QTableView::activated, this, &ContentSelector::slotAddonTableItemActivated);
|
connect(ui->addonView, &QTableView::activated, this, &ContentSelector::slotAddonTableItemActivated);
|
||||||
connect(mContentModel, &ContentSelectorModel::ContentModel::dataChanged, this,
|
connect(mContentModel, &ContentSelectorModel::ContentModel::dataChanged, this,
|
||||||
&ContentSelector::signalAddonDataChanged);
|
&ContentSelector::signalAddonDataChanged);
|
||||||
|
connect(mContentModel, &ContentSelectorModel::ContentModel::dataChanged, this, &ContentSelector::slotRowsMoved);
|
||||||
buildContextMenu();
|
buildContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,3 +332,8 @@ void ContentSelectorView::ContentSelector::slotSearchFilterTextChanged(const QSt
|
||||||
{
|
{
|
||||||
ui->addonView->setDragEnabled(newText.isEmpty());
|
ui->addonView->setDragEnabled(newText.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentSelectorView::ContentSelector::slotRowsMoved()
|
||||||
|
{
|
||||||
|
ui->addonView->selectionModel()->clearSelection();
|
||||||
|
}
|
|
@ -85,6 +85,7 @@ namespace ContentSelectorView
|
||||||
void slotUncheckMultiSelectedItems();
|
void slotUncheckMultiSelectedItems();
|
||||||
void slotCopySelectedItemsPaths();
|
void slotCopySelectedItemsPaths();
|
||||||
void slotSearchFilterTextChanged(const QString& newText);
|
void slotSearchFilterTextChanged(const QString& newText);
|
||||||
|
void slotRowsMoved();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue