#include "StdInc.h" #include "cmodlistmodel_moc.h" #include namespace ModFields { static const QString names [ModFields::COUNT] = { "name", "", "", "modType", "version", "size", "author" }; static const QString header [ModFields::COUNT] = { "Name", "", // status icon "", // status icon "Type", "Version", "Size", "Author" }; } namespace ModStatus { static const QString iconDelete = "icons:mod-delete.png"; static const QString iconDisabled = "icons:mod-disabled.png"; static const QString iconDownload = "icons:mod-download.png"; static const QString iconEnabled = "icons:mod-enabled.png"; static const QString iconUpdate = "icons:mod-update.png"; } CModListModel::CModListModel(QObject *parent) : QAbstractItemModel(parent) { } QString CModListModel::modIndexToName(const QModelIndex & index) const { if (index.isValid()) { return modNameToID.at(index.internalId()); } return ""; } QVariant CModListModel::getValue(const CModEntry &mod, int field) const { switch(field) { case ModFields::STATUS_ENABLED: return mod.getModStatus() & (ModStatus::ENABLED | ModStatus::INSTALLED); case ModFields::STATUS_UPDATE: return mod.getModStatus() & (ModStatus::UPDATEABLE | ModStatus::INSTALLED); default: return mod.getValue(ModFields::names[field]); } } QVariant CModListModel::getText(const CModEntry & mod, int field) const { switch(field) { case ModFields::STATUS_ENABLED: case ModFields::STATUS_UPDATE: return ""; case ModFields::SIZE: return CModEntry::sizeToString(getValue(mod, field).toDouble()); default: return getValue(mod, field); } } QVariant CModListModel::getIcon(const CModEntry & mod, int field) const { if (field == ModFields::STATUS_ENABLED && mod.isEnabled()) return QIcon(ModStatus::iconEnabled); if (field == ModFields::STATUS_ENABLED && mod.isDisabled()) return QIcon(ModStatus::iconDisabled); if (field == ModFields::STATUS_UPDATE && mod.isUpdateable()) return QIcon(ModStatus::iconUpdate); if (field == ModFields::STATUS_UPDATE && !mod.isInstalled()) return QIcon(ModStatus::iconDownload); return QVariant(); } QVariant CModListModel::getTextAlign(int field) const { if (field == ModFields::SIZE) return QVariant(Qt::AlignRight | Qt::AlignVCenter); //if (field == ModFields::NAME) // return QVariant(Qt::AlignHCenter | Qt::AlignVCenter); return QVariant(Qt::AlignLeft | Qt::AlignVCenter); } QVariant CModListModel::data(const QModelIndex &index, int role) const { if (index.isValid()) { auto mod = getMod(modIndexToName(index)); switch (role) { case Qt::DecorationRole: return getIcon(mod, index.column()); case Qt::DisplayRole: return getText(mod, index.column()); case Qt::TextAlignmentRole: return getTextAlign(index.column()); case ModRoles::ValueRole: return getValue(mod, index.column()); case ModRoles::ModNameRole: return mod.getName(); } } return QVariant(); } int CModListModel::rowCount(const QModelIndex & index) const { if (index.isValid()) return modIndex[modIndexToName(index)].size(); return modIndex[""].size(); } int CModListModel::columnCount(const QModelIndex &) const { return ModFields::COUNT; } Qt::ItemFlags CModListModel::flags(const QModelIndex &) const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } QVariant CModListModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal) return ModFields::header[section]; return QVariant(); } void CModListModel::resetRepositories() { beginResetModel(); CModList::resetRepositories(); endResetModel(); } void CModListModel::addRepository(QVariantMap data) { beginResetModel(); CModList::addRepository(data); endResetModel(); } void CModListModel::modChanged(QString modID) { int index = modNameToID.indexOf(modID); QModelIndex parent = this->parent(createIndex(0, 0, index)); int row = modIndex[modIndexToName(parent)].indexOf(modID); emit dataChanged(createIndex(row, 0, index), createIndex(row, 4, index)); } void CModListModel::endResetModel() { modNameToID = getModList(); modIndex.clear(); for (const QString & str : modNameToID) { if (str.contains('.')) { modIndex[str.section('.', 0, -2)].append(str); } else { modIndex[""].append(str); } } QAbstractItemModel::endResetModel(); } QModelIndex CModListModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid()) { if (modIndex[modIndexToName(parent)].size() > row) return createIndex(row, column, modNameToID.indexOf(modIndex[modIndexToName(parent)][row])); } else { if (modIndex[""].size() > row) return createIndex(row, column, modNameToID.indexOf(modIndex[""][row])); } return QModelIndex(); } QModelIndex CModListModel::parent(const QModelIndex &child) const { QString modID = modNameToID[child.internalId()]; for (auto entry = modIndex.begin(); entry != modIndex.end(); entry++) // because using range-for entry type is QMap::value_type oO { if (entry.key() != "" && entry.value().indexOf(modID) != -1) { return createIndex(entry.value().indexOf(modID), child.column(), modNameToID.indexOf(entry.key())); } } return QModelIndex(); } void CModFilterModel::setTypeFilter(int filteredType, int filterMask) { this->filterMask = filterMask; this->filteredType = filteredType; invalidateFilter(); } bool CModFilterModel::filterMatchesThis(const QModelIndex &source) const { CModEntry mod = base->getMod(source.data(ModRoles::ModNameRole).toString()); return (mod.getModStatus() & filterMask) == filteredType && QSortFilterProxyModel::filterAcceptsRow(source.row(), source.parent()); } bool CModFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { QModelIndex index = base->index(source_row, 0, source_parent); if (filterMatchesThis(index)) { return true; } for (size_t i=0; irowCount(index); i++) { if (filterMatchesThis(index.child(i, 0))) return true; } QModelIndex parent = source_parent; while (parent.isValid()) { if (filterMatchesThis(parent)) return true; parent = parent.parent(); } return false; } CModFilterModel::CModFilterModel(CModListModel * model, QObject * parent): QSortFilterProxyModel(parent), base(model), filteredType(ModStatus::MASK_NONE), filterMask(ModStatus::MASK_NONE) { setSourceModel(model); setSortRole(ModRoles::ValueRole); }