Added new plugin model for the Data Files tab in the launcher

pull/37/head
Pieter van der Kloet 12 years ago
parent bb0f94decb
commit 4174d3c235

@ -1,5 +1,6 @@
set(LAUNCHER
datafilespage.cpp
filedialog.cpp
graphicspage.cpp
lineedit.cpp
main.cpp
@ -8,14 +9,18 @@ set(LAUNCHER
playpage.cpp
pluginsmodel.cpp
pluginsview.cpp
filedialog.cpp
launcher.rc
model/datafilesmodel.cpp
model/modelitem.cpp
model/esm/esmfile.cpp
)
set(LAUNCHER_HEADER
combobox.hpp
datafilespage.hpp
filedialog.hpp
graphicspage.hpp
lineedit.hpp
maindialog.hpp
@ -23,20 +28,27 @@ set(LAUNCHER_HEADER
playpage.hpp
pluginsmodel.hpp
pluginsview.hpp
filedialog.hpp
model/datafilesmodel.hpp
model/modelitem.hpp
model/esm/esmfile.hpp
)
# Headers that must be pre-processed
set(LAUNCHER_HEADER_MOC
combobox.hpp
datafilespage.hpp
filedialog.hpp
graphicspage.hpp
lineedit.hpp
maindialog.hpp
playpage.hpp
pluginsmodel.hpp
pluginsview.hpp
filedialog.hpp
model/datafilesmodel.hpp
model/modelitem.hpp
model/esm/esmfile.hpp
)
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC})

@ -0,0 +1,443 @@
#include <QDebug>
#include <QFileInfo>
#include <QDir>
#include <components/esm/esm_reader.hpp>
#include "esm/esmfile.hpp"
#include "datafilesmodel.hpp"
#include "../naturalsort.hpp"
DataFilesModel::DataFilesModel(QObject *parent) :
QAbstractTableModel(parent)
{
}
DataFilesModel::~DataFilesModel()
{
}
void DataFilesModel::setCheckState(const QModelIndex &index, Qt::CheckState state)
{
setData(index, state, Qt::CheckStateRole);
}
Qt::CheckState DataFilesModel::checkState(const QModelIndex &index)
{
EsmFile *file = item(index.row());
return mCheckStates[file->fileName()];
}
int DataFilesModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : 9;
}
int DataFilesModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : mFiles.count();
}
bool DataFilesModel::moveRow(int oldrow, int row, const QModelIndex &parent)
{
if (oldrow < 0 || row < 0 || oldrow == row)
return false;
emit layoutAboutToBeChanged();
//emit beginMoveRows(parent, oldrow, oldrow, parent, row);
mFiles.swap(oldrow, row);
//emit endInsertRows();
emit layoutChanged();
return true;
}
QVariant DataFilesModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
// if (index.row() < 0 || index.row() >= mPlugins.size())
// return QVariant();
EsmFile *file = mFiles.at(index.row());
const int column = index.column();
switch (role) {
case Qt::DisplayRole: {
switch (column) {
case 0:
return file->fileName();
case 1:
return file->author();
case 2:
return QString("%1 kB").arg(int((file->size() + 1023) / 1024));
case 3:
//return file->modified().toString(Qt::TextDate);
return file->modified().toString(Qt::ISODate);
case 4:
return file->accessed().toString(Qt::TextDate);
case 5:
return file->version();
case 6:
return file->path();
case 7:
return file->masters().join(", ");
case 8:
return file->description();
}
}
case Qt::TextAlignmentRole: {
switch (column) {
case 0:
return Qt::AlignLeft + Qt::AlignVCenter;
case 1:
return Qt::AlignLeft + Qt::AlignVCenter;
case 2:
return Qt::AlignRight + Qt::AlignVCenter;
case 3:
return Qt::AlignRight + Qt::AlignVCenter;
case 4:
return Qt::AlignRight + Qt::AlignVCenter;
case 5:
return Qt::AlignRight + Qt::AlignVCenter;
default:
return Qt::AlignLeft + Qt::AlignVCenter;
}
}
case Qt::CheckStateRole: {
if (column != 0)
return QVariant();
return mCheckStates[file->fileName()];
}
case Qt::ToolTipRole:
{
if (column != 0)
return QVariant();
if (file->version() == 0.0f)
return QVariant(); // Data not set
QString tooltip =
QString("<b>Author:</b> %1<br/> \
<b>Version:</b> %2<br/> \
<br/><b>Description:</b><br/>%3<br/> \
<br/><b>Dependencies: </b>%4<br/>")
.arg(file->author())
.arg(QString::number(file->version()))
.arg(file->description())
.arg(file->masters().join(", "));
return tooltip;
}
default:
return QVariant();
}
}
Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
EsmFile *file = mFiles.at(index.row());
if (mAvailableFiles.contains(file->fileName())) {
if (index.column() == 0) {
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
} else {
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
} else {
if (index.column() == 0) {
return Qt::ItemIsUserCheckable | Qt::ItemIsSelectable;
} else {
return Qt::NoItemFlags | Qt::ItemIsSelectable;
}
}
}
QVariant DataFilesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0: return tr("Name");
case 1: return tr("Author");
case 2: return tr("Size");
case 3: return tr("Modified");
case 4: return tr("Accessed");
case 5: return tr("Version");
case 6: return tr("Path");
case 7: return tr("Masters");
case 8: return tr("Description");
}
} else {
// Show row numbers
return ++section;
}
return QVariant();
}
bool DataFilesModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
if (role == Qt::CheckStateRole) {
emit layoutAboutToBeChanged();
QString name = item(index.row())->fileName();
mCheckStates[name] = static_cast<Qt::CheckState>(value.toInt());
emit checkedItemsChanged(checkedItems(), uncheckedItems());
emit layoutChanged();
return true;
}
return false;
}
void DataFilesModel::sort(int column, Qt::SortOrder order)
{
// TODO: Make this more efficient
emit layoutAboutToBeChanged();
// A reference list we can sort
QStringList all = uncheckedItems();
//all.append(uncheckedItems());
// Sort the list of items naturally
qSort(all.begin(), all.end(), naturalSortLessThanCI);
for (int i = 0; i < all.size(); ++i) {
const QString currentItem = all.at(i);
QModelIndex index = indexFromItem(findItem(currentItem));
// Move the actual item from the old position to the new
if (index.isValid())
mFiles.swap(index.row(), i);
}
emit layoutChanged();
}
void DataFilesModel::addFile(EsmFile *file)
{
emit beginInsertRows(QModelIndex(), mFiles.count(), mFiles.count());
mFiles.append(file);
emit endInsertRows();
}
void DataFilesModel::addMasters(const QString &path)
{
QDir dir(path);
dir.setNameFilters(QStringList(QLatin1String("*.esp")));
// Read the dependencies from the plugins
foreach (const QString &path, dir.entryList()) {
QFileInfo info(dir.absoluteFilePath(path));
try {
ESM::ESMReader fileReader;
fileReader.setEncoding(std::string("win1252"));
fileReader.open(dir.absoluteFilePath(path).toStdString());
ESM::ESMReader::MasterList mlist = fileReader.getMasters();
for (unsigned int i = 0; i < mlist.size(); ++i) {
QString master = QString::fromStdString(mlist[i].name);
// Add the plugin to the internal dependency map
mDependencies[master].append(path);
// Don't add esps
if (master.endsWith(".esp", Qt::CaseInsensitive))
continue;
EsmFile *file = new EsmFile(master);
// Add the master to the table
if (findItem(master) == 0)
addFile(file);
}
} catch(std::runtime_error &e) {
// An error occurred while reading the .esp
continue;
}
}
// See if the masters actually exist in the filesystem
dir.setNameFilters(QStringList(QLatin1String("*.esm")));
foreach (const QString &path, dir.entryList()) {
if (findItem(path) == 0) {
EsmFile *file = new EsmFile(path);
addFile(file);
}
// Make the master selectable
mAvailableFiles.append(path);
}
}
void DataFilesModel::addPlugins(const QString &path)
{
QDir dir(path);
dir.setNameFilters(QStringList(QLatin1String("*.esp")));
foreach (const QString &path, dir.entryList()) {
QFileInfo info(dir.absoluteFilePath(path));
EsmFile *file = new EsmFile(path);
try {
ESM::ESMReader fileReader;
fileReader.setEncoding(std::string("win1252"));
fileReader.open(dir.absoluteFilePath(path).toStdString());
ESM::ESMReader::MasterList mlist = fileReader.getMasters();
QStringList masters;
for (unsigned int i = 0; i < mlist.size(); ++i) {
QString master = QString::fromStdString(mlist[i].name);
masters.append(master);
// Add the plugin to the internal dependency map
mDependencies[master].append(path);
}
file->setAuthor(QString::fromStdString(fileReader.getAuthor()));
file->setSize(info.size());
file->setDates(info.lastModified(), info.lastRead());
file->setVersion(fileReader.getFVer());
file->setPath(info.absoluteFilePath());
file->setMasters(masters);
file->setDescription(QString::fromStdString(fileReader.getDesc()));
// Put the file in the table
addFile(file);
} catch(std::runtime_error &e) {
// An error occurred while reading the .esp
continue;
}
}
}
QModelIndex DataFilesModel::indexFromItem(EsmFile *item) const
{
if (item)
return createIndex(mFiles.indexOf(item), 0);
return QModelIndex();
}
EsmFile* DataFilesModel::findItem(const QString &name)
{
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
if (name == file->fileName())
return file;
}
// Not found
return 0;
}
EsmFile* DataFilesModel::item(int row)
{
if (row >= 0 && row < mFiles.count())
return mFiles.at(row);
else
return 0;
}
QStringList DataFilesModel::checkedItems()
{
QStringList list;
QHash<QString, Qt::CheckState>::ConstIterator it;
QHash<QString, Qt::CheckState>::ConstIterator itEnd = mCheckStates.constEnd();
for (it = mCheckStates.constBegin(); it != itEnd; ++it) {
if (it.value() == Qt::Checked) {
list << it.key();
}
}
return list;
}
void DataFilesModel::uncheckAll()
{
emit layoutAboutToBeChanged();
mCheckStates.clear();
emit layoutChanged();
}
QStringList DataFilesModel::uncheckedItems()
{
QStringList list;
QStringList checked = checkedItems();
QList<EsmFile *>::ConstIterator it;
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
int i = 0;
for (it = mFiles.constBegin(); it != itEnd; ++it) {
EsmFile *file = item(i);
++i;
// Add the items that are not in the checked list
if (!checked.contains(file->fileName()))
list << file->fileName();
}
return list;
}
void DataFilesModel::slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems)
{
emit layoutAboutToBeChanged();
QStringList list;
foreach (const QString &file, checkedItems) {
list << mDependencies[file];
}
foreach (const QString &file, unCheckedItems) {
foreach (const QString &remove, mDependencies[file]) {
list.removeAll(remove);
}
}
mAvailableFiles.clear();
mAvailableFiles.append(list);
emit layoutChanged();
}

@ -0,0 +1,67 @@
#ifndef DATAFILESMODEL_HPP
#define DATAFILESMODEL_HPP
#include <QAbstractTableModel>
#include <QStringList>
#include <QString>
#include <QHash>
class EsmFile;
class DataFilesModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit DataFilesModel(QObject *parent = 0);
virtual ~DataFilesModel();
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
bool moveRow(int oldrow, int row, const QModelIndex &parent = QModelIndex());
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
inline QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const
{ return QAbstractTableModel::index(row, column, parent); }
void addFile(EsmFile *file);
void addMasters(const QString &path);
void addPlugins(const QString &path);
void uncheckAll();
QStringList checkedItems();
QStringList uncheckedItems();
Qt::CheckState checkState(const QModelIndex &index);
void setCheckState(const QModelIndex &index, Qt::CheckState state);
QModelIndex indexFromItem(EsmFile *item) const;
EsmFile* findItem(const QString &name);
EsmFile* item(int row);
signals:
void checkedItemsChanged(const QStringList checkedItems, const QStringList unCheckedItems);
public slots:
void slotcheckedItemsChanged(const QStringList &checkedItems, const QStringList &unCheckedItems);
private:
QList<EsmFile *> mFiles;
QStringList mAvailableFiles;
QHash<QString, QStringList> mDependencies;
QHash<QString, Qt::CheckState> mCheckStates;
};
#endif // DATAFILESMODEL_HPP

@ -0,0 +1,50 @@
#include "esmfile.hpp"
EsmFile::EsmFile(QString fileName, ModelItem *parent)
: ModelItem(parent)
{
mFileName = fileName;
mSize = 0;
mVersion = 0.0f;
}
void EsmFile::setFileName(const QString &fileName)
{
mFileName = fileName;
}
void EsmFile::setAuthor(const QString &author)
{
mAuthor = author;
}
void EsmFile::setSize(const int size)
{
mSize = size;
}
void EsmFile::setDates(const QDateTime &modified, const QDateTime &accessed)
{
mModified = modified;
mAccessed = accessed;
}
void EsmFile::setVersion(float version)
{
mVersion = version;
}
void EsmFile::setPath(const QString &path)
{
mPath = path;
}
void EsmFile::setMasters(const QStringList &masters)
{
mMasters = masters;
}
void EsmFile::setDescription(const QString &description)
{
mDescription = description;
}

@ -0,0 +1,54 @@
#ifndef ESMFILE_HPP
#define ESMFILE_HPP
#include <QDateTime>
#include <QStringList>
#include "../modelitem.hpp"
class EsmFile : public ModelItem
{
Q_OBJECT
Q_PROPERTY(QString filename READ fileName)
public:
EsmFile(QString fileName = QString(), ModelItem *parent = 0);
~EsmFile()
{}
void setFileName(const QString &fileName);
void setAuthor(const QString &author);
void setSize(const int size);
void setDates(const QDateTime &modified, const QDateTime &accessed);
void setVersion(const float version);
void setPath(const QString &path);
void setMasters(const QStringList &masters);
void setDescription(const QString &description);
inline QString fileName() { return mFileName; }
inline QString author() { return mAuthor; }
inline int size() { return mSize; }
inline QDateTime modified() { return mModified; }
inline QDateTime accessed() { return mAccessed; }
inline float version() { return mVersion; }
inline QString path() { return mPath; }
inline QStringList masters() { return mMasters; }
inline QString description() { return mDescription; }
private:
QString mFileName;
QString mAuthor;
int mSize;
QDateTime mModified;
QDateTime mAccessed;
float mVersion;
QString mPath;
QStringList mMasters;
QString mDescription;
};
#endif

@ -0,0 +1,57 @@
#include "modelitem.hpp"
ModelItem::ModelItem(ModelItem *parent)
: mParentItem(parent)
, QObject(parent)
{
}
ModelItem::~ModelItem()
{
qDeleteAll(mChildItems);
}
ModelItem *ModelItem::parent()
{
return mParentItem;
}
int ModelItem::row() const
{
if (mParentItem)
return 1;
//return mParentItem->childRow(const_cast<ModelItem*>(this));
//return mParentItem->mChildItems.indexOf(const_cast<ModelItem*>(this));
return -1;
}
int ModelItem::childCount() const
{
return mChildItems.count();
}
int ModelItem::childRow(ModelItem *child) const
{
Q_ASSERT(child);
return mChildItems.indexOf(child);
}
ModelItem *ModelItem::child(int row)
{
return mChildItems.value(row);
}
void ModelItem::appendChild(ModelItem *item)
{
mChildItems.append(item);
}
void ModelItem::removeChild(int row)
{
mChildItems.removeAt(row);
}

@ -0,0 +1,32 @@
#ifndef MODELITEM_HPP
#define MODELITEM_HPP
#include <QObject>
#include <QList>
class ModelItem : public QObject
{
Q_OBJECT
public:
ModelItem(ModelItem *parent = 0);
~ModelItem();
ModelItem *parent();
int row() const;
int childCount() const;
int childRow(ModelItem *child) const;
ModelItem *child(int row);
void appendChild(ModelItem *child);
void removeChild(int row);
//virtual bool acceptChild(ModelItem *child);
protected:
ModelItem *mParentItem;
QList<ModelItem*> mChildItems;
};
#endif
Loading…
Cancel
Save