diff options
author | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:31 -0400 |
---|---|---|
committer | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:31 -0400 |
commit | 294b5ec5834affa57641475946b8d2aeca53c577 (patch) | |
tree | ca25b634d0f24ab5b1fc38eb805e72e0e993e0f1 /src/backend/bookshelfmodel | |
parent | e8a196082586bb68e0bf254a8f6f4b8f39071f32 (diff) |
Imported Upstream version 2.4
Diffstat (limited to 'src/backend/bookshelfmodel')
20 files changed, 482 insertions, 120 deletions
diff --git a/src/backend/bookshelfmodel/btbookshelfmodel.cpp b/src/backend/bookshelfmodel/btbookshelfmodel.cpp index 99f83ba..6882b90 100644 --- a/src/backend/bookshelfmodel/btbookshelfmodel.cpp +++ b/src/backend/bookshelfmodel/btbookshelfmodel.cpp @@ -14,7 +14,8 @@ #include <QSet> #include "util/cresmgr.h" -#include "util/directoryutil.h" +#include "util/directory.h" + BtBookshelfModel::BtBookshelfModel(QObject *parent) : QAbstractListModel(parent) { @@ -29,25 +30,35 @@ int BtBookshelfModel::rowCount(const QModelIndex &parent) const { return m_data.size(); } -QVariant BtBookshelfModel::data(const QModelIndex &index, int role) const { - if (!index.isValid() || index.column() != 0 || index.parent().isValid()) { - return QVariant(); - } - int row(index.row()); - if (row >= m_data.size()) return QVariant(); - +QVariant BtBookshelfModel::data(CSwordModuleInfo *module, int role) const { switch (role) { case ModuleNameRole: // Qt::DisplayRole - return m_data.at(row)->name(); + return module->name(); case ModuleIconRole: // Qt::DecorationRole - return moduleIcon(m_data.at(row)); + return moduleIcon(module); case ModulePointerRole: - return qVariantFromValue((void*) m_data.at(row)); + return qVariantFromValue((void*) module); + case ModuleCategoryRole: + return QVariant::fromValue(module->category()); + case ModuleLanguageRole: + return QVariant(); /// \todo Unimplemented + case ModuleHiddenRole: + return module->isHidden(); default: return QVariant(); } } +QVariant BtBookshelfModel::data(const QModelIndex &index, int role) const { + if (!index.isValid() || index.column() != 0 || index.parent().isValid()) { + return QVariant(); + } + int row(index.row()); + if (row >= m_data.size()) return QVariant(); + + return data(m_data.at(row), role); +} + QVariant BtBookshelfModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole && orientation == Qt::Horizontal && @@ -58,8 +69,25 @@ QVariant BtBookshelfModel::headerData(int section, Qt::Orientation orientation, return QVariant(); } +bool BtBookshelfModel::setData(const QModelIndex &index, const QVariant &value, + int role) { + int row(index.row()); + if (role == ModuleHiddenRole && row >= 0 && row < m_data.size() + && index.column() == 0) + { + /* + Emitting dataChanged here is actually mandatory, but were not doing it + directly. Since we're connected to the module, changing its hidden + state will emit a signal we catch in moduleHidden(), which in turn is + what will actually emit dataChanged(). + */ + return m_data.at(row)->setHidden(value.toBool()); + } + return false; +} + QIcon BtBookshelfModel::moduleIcon(const CSwordModuleInfo *m) { - typedef util::filesystem::DirectoryUtil DU; + namespace DU = util::directory; /// \todo Make CSwordModuleInfo::isLocked() const and remove const_cast: CSwordModuleInfo *module(const_cast<CSwordModuleInfo*>(m)); @@ -101,7 +129,7 @@ QIcon BtBookshelfModel::moduleIcon(const CSwordModuleInfo *m) { } QIcon BtBookshelfModel::categoryIcon(const CSwordModuleInfo::Category &category) { - typedef util::filesystem::DirectoryUtil DU; + namespace DU = util::directory; switch (category) { case CSwordModuleInfo::Bibles: @@ -174,6 +202,8 @@ void BtBookshelfModel::addModule(CSwordModuleInfo * const module) { const int index(m_data.size()); beginInsertRows(QModelIndex(), index, index); m_data.append(module); + connect(module, SIGNAL(hiddenChanged(bool)), + this, SLOT(moduleHidden(bool))); endInsertRows(); } @@ -193,13 +223,11 @@ void BtBookshelfModel::addModules(const QSet<CSwordModuleInfo *> &modules) { beginInsertRows(QModelIndex(), m_data.size(), m_data.size() + newModules.size() - 1); -#if QT_VERSION >= 0x040500 - m_data.append(newModules); -#else Q_FOREACH(CSwordModuleInfo *module, newModules) { m_data.append(module); + connect(module, SIGNAL(hiddenChanged(bool)), + this, SLOT(moduleHidden(bool))); } -#endif endInsertRows(); } @@ -210,6 +238,8 @@ void BtBookshelfModel::removeModule(CSwordModuleInfo * const module, if (index == -1) return; beginRemoveRows(QModelIndex(), index, index); + disconnect(module, SIGNAL(hiddenChanged(bool)), + this, SLOT(moduleHidden(bool))); m_data.removeAt(index); endRemoveRows(); if (destroy) delete module; @@ -236,3 +266,13 @@ CSwordModuleInfo* BtBookshelfModel::getModule(const QString &name) const { } return 0; } + +void BtBookshelfModel::moduleHidden(bool) { + Q_ASSERT(qobject_cast<CSwordModuleInfo*>(sender()) != 0); + + CSwordModuleInfo *module(static_cast<CSwordModuleInfo*>(sender())); + Q_ASSERT(m_data.count(module) == 1); + + QModelIndex i(index(m_data.indexOf(module), 0)); + emit dataChanged(i, i); +} diff --git a/src/backend/bookshelfmodel/btbookshelfmodel.h b/src/backend/bookshelfmodel/btbookshelfmodel.h index 01fc260..16fdb13 100644 --- a/src/backend/bookshelfmodel/btbookshelfmodel.h +++ b/src/backend/bookshelfmodel/btbookshelfmodel.h @@ -17,6 +17,7 @@ #include "backend/drivers/cswordmoduleinfo.h" + class BtBookshelfModel: public QAbstractListModel { Q_OBJECT public: @@ -26,6 +27,7 @@ class BtBookshelfModel: public QAbstractListModel { ModulePointerRole = Qt::UserRole, ModuleCategoryRole = Qt::UserRole + 1, ModuleLanguageRole = Qt::UserRole + 2, + ModuleHiddenRole = Qt::UserRole + 3, UserRole = Qt::UserRole + 100 }; @@ -33,9 +35,12 @@ class BtBookshelfModel: public QAbstractListModel { virtual ~BtBookshelfModel(); virtual int rowCount(const QModelIndex &parent) const; + virtual QVariant data(CSwordModuleInfo *module, int role) const; virtual QVariant data(const QModelIndex &index, int role) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + bool setData(const QModelIndex &index, const QVariant &value, + int role = ModuleHiddenRole); inline CSwordModuleInfo *module(const QModelIndex &index) const { return (CSwordModuleInfo *) @@ -64,6 +69,9 @@ class BtBookshelfModel: public QAbstractListModel { return m_data; } + protected slots: + void moduleHidden(bool hidden); + protected: QList<CSwordModuleInfo *> m_data; }; diff --git a/src/backend/bookshelfmodel/btbookshelftreemodel.cpp b/src/backend/bookshelfmodel/btbookshelftreemodel.cpp index 8e457e7..5be1aec 100644 --- a/src/backend/bookshelfmodel/btbookshelftreemodel.cpp +++ b/src/backend/bookshelfmodel/btbookshelftreemodel.cpp @@ -12,25 +12,26 @@ #include "backend/bookshelfmodel/btbookshelftreemodel.h" -#include <QQueue> #include <QSet> #include "backend/bookshelfmodel/categoryitem.h" #include "backend/bookshelfmodel/distributionitem.h" #include "backend/bookshelfmodel/languageitem.h" #include "backend/bookshelfmodel/moduleitem.h" + using namespace BookshelfModel; BtBookshelfTreeModel::BtBookshelfTreeModel(QObject *parent) : QAbstractItemModel(parent), m_sourceModel(0), m_rootItem(new RootItem), - m_checkable(false), m_defaultChecked(false) { + m_defaultChecked(MODULE_HIDDEN), m_checkable(false) { m_groupingOrder.push_back(GROUP_CATEGORY); m_groupingOrder.push_back(GROUP_LANGUAGE); } BtBookshelfTreeModel::BtBookshelfTreeModel(const Grouping &g, QObject *parent) : QAbstractItemModel(parent), m_sourceModel(0), m_rootItem(new RootItem), - m_groupingOrder(g), m_checkable(false), m_defaultChecked(false) { + m_groupingOrder(g), m_defaultChecked(MODULE_HIDDEN), m_checkable(false) +{ // Intentionally empty } @@ -79,8 +80,6 @@ QModelIndex BtBookshelfTreeModel::parent(const QModelIndex &index) const { } QVariant BtBookshelfTreeModel::data(const QModelIndex &index, int role) const { - typedef util::filesystem::DirectoryUtil DU; - if (!index.isValid() || index.column() != 0) { return QVariant(); } @@ -89,22 +88,33 @@ QVariant BtBookshelfTreeModel::data(const QModelIndex &index, int role) const { Q_ASSERT(i != 0); switch (role) { case Qt::DisplayRole: - return i->name(); + if (i->type() == Item::ITEM_MODULE) { + return parentData(static_cast<ModuleItem *>(i), role); + } else { + return i->name(); + } case Qt::CheckStateRole: if (!m_checkable) break; case BtBookshelfTreeModel::CheckStateRole: return i->checkState(); case Qt::DecorationRole: - return i->icon(); + if (i->type() == Item::ITEM_MODULE) { + return parentData(static_cast<ModuleItem *>(i), role); + } else { + return i->icon(); + } case BtBookshelfModel::ModulePointerRole: if (i->type() == Item::ITEM_MODULE) { - ModuleItem *mi(dynamic_cast<ModuleItem *>(i)); - if (mi != 0) { - return qVariantFromValue((void*) mi->moduleInfo()); - } + ModuleItem *mi(static_cast<ModuleItem *>(i)); + return qVariantFromValue((void*) mi->moduleInfo()); } return 0; + case BtBookshelfModel::ModuleHiddenRole: + return i->isHidden(); default: + if (i->type() == Item::ITEM_MODULE) { + return parentData(static_cast<ModuleItem *>(i), role); + } break; } return QVariant(); @@ -115,37 +125,47 @@ bool BtBookshelfTreeModel::setData(const QModelIndex &itemIndex, int role) { typedef QPair<Item *, QModelIndex> IP; - if (role == Qt::CheckStateRole) { + Qt::CheckState newState; + if (role == BtBookshelfModel::ModuleHiddenRole) { + newState = value.toBool() ? Qt::Checked : Qt::Unchecked; + } else if (role == Qt::CheckStateRole) { bool ok; - Qt::CheckState newState((Qt::CheckState) value.toInt(&ok)); - if (ok && newState != Qt::PartiallyChecked) { - Item *i(static_cast<Item*>(itemIndex.internalPointer())); - Q_ASSERT(i != 0); - // Recursively (un)check all children: - QList<IP> q; - q.append(IP(i, itemIndex)); - while (!q.isEmpty()) { - const IP p(q.takeFirst()); - Item *item(p.first); - item->setCheckState(newState); - emit dataChanged(p.second, p.second); + newState = (Qt::CheckState) value.toInt(&ok); + if (!ok || newState == Qt::PartiallyChecked) return false; + } else { + return false; + } + + Item *item(static_cast<Item*>(itemIndex.internalPointer())); + Q_ASSERT(item != 0); + if (item->checkState() == newState) return false; + + // Recursively (un)check all children: + QList<IP> q; + IP p(item, itemIndex); + for (;;) { + if (item->checkState() != newState) { + item->setCheckState(newState); + emit dataChanged(p.second, p.second); + if (item->type() == Item::ITEM_MODULE) { + ModuleItem *mi(static_cast<ModuleItem*>(item)); + emit moduleChecked(mi->moduleInfo(), newState == Qt::Checked); + } else { const QList<Item*> &children(item->children()); for (int i(0); i < children.size(); i++) { q.append(IP(children.at(i), index(i, 0, p.second))); } } + } + if (q.empty()) break; + p = q.takeFirst(); + item = p.first; + } - // Change check state of the item itself - i->setCheckState(newState); - emit dataChanged(itemIndex, itemIndex); - - // Recursively change parent check states. - resetParentCheckStates(itemIndex.parent()); + // Recursively change parent check states. + resetParentCheckStates(itemIndex.parent()); - return true; - } // if (ok && newState != Qt::PartiallyChecked) - } // if (role == Qt::CheckStateRole) - return false; + return true; } Qt::ItemFlags BtBookshelfTreeModel::flags(const QModelIndex &index) const { @@ -176,7 +196,7 @@ QVariant BtBookshelfTreeModel::headerData(int section, return QVariant(); } -void BtBookshelfTreeModel::setSourceModel(QAbstractListModel *sourceModel) { +void BtBookshelfTreeModel::setSourceModel(QAbstractItemModel *sourceModel) { if (m_sourceModel == sourceModel) return; if (m_sourceModel != 0) { @@ -186,6 +206,7 @@ void BtBookshelfTreeModel::setSourceModel(QAbstractListModel *sourceModel) { beginRemoveRows(QModelIndex(), 0, m_rootItem->children().size() - 1); delete m_rootItem; m_modules.clear(); + m_sourceIndexMap.clear(); m_rootItem = new RootItem; endRemoveRows(); } @@ -200,28 +221,25 @@ void BtBookshelfTreeModel::setSourceModel(QAbstractListModel *sourceModel) { connect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(moduleDataChanged(QModelIndex, QModelIndex))); - BtBookshelfModel *m(dynamic_cast<BtBookshelfModel*>(sourceModel)); - if (m != 0) { - Q_FOREACH(CSwordModuleInfo *module, m->modules()) { - addModule(module, m_defaultChecked); - } - } - else { - for (int i(0); i < sourceModel->rowCount(); i++) { - CSwordModuleInfo *module( - static_cast<CSwordModuleInfo *>( - sourceModel->data( - sourceModel->index(i), - BtBookshelfModel::ModulePointerRole - ).value<void*>() - ) - ); - Q_ASSERT(module != 0); - addModule( - module, - m_defaultChecked - ); + for (int i(0); i < sourceModel->rowCount(); i++) { + typedef BtBookshelfModel::ModuleRole MRole; + static const MRole HR(BtBookshelfModel::ModuleHiddenRole); + static const MRole PR(BtBookshelfModel::ModulePointerRole); + QModelIndex moduleIndex(sourceModel->index(i, 0)); + CSwordModuleInfo *module( + static_cast<CSwordModuleInfo *>( + sourceModel->data(moduleIndex, PR).value<void*>() + ) + ); + Q_ASSERT(module != 0); + bool checked; + if (m_defaultChecked == MODULE_HIDDEN) { + checked = !sourceModel->data(moduleIndex, HR).toBool(); + } else { + checked = (m_defaultChecked == CHECKED); } + m_sourceIndexMap[module] = moduleIndex; + addModule(module, checked); } } } @@ -249,7 +267,7 @@ void BtBookshelfTreeModel::setGroupingOrder(const Grouping &groupingOrder) { CSwordModuleInfo *module( static_cast<CSwordModuleInfo *>( m_sourceModel->data( - m_sourceModel->index(i), + m_sourceModel->index(i, 0), BtBookshelfModel::ModulePointerRole ).value<void*>() ) @@ -295,6 +313,14 @@ QList<CSwordModuleInfo*> BtBookshelfTreeModel::checkedModules() const { return modules; } +QVariant BtBookshelfTreeModel::parentData(BookshelfModel::ModuleItem *item, + int role) const +{ + CSwordModuleInfo* m(item->moduleInfo()); + Q_ASSERT(m_sourceIndexMap.contains(m)); + return m_sourceModel->data(m_sourceIndexMap.value(m), role); +} + void BtBookshelfTreeModel::addModule(CSwordModuleInfo *module, bool checked) { if (m_modules.contains(module)) return; Grouping g(m_groupingOrder); @@ -345,8 +371,9 @@ void BtBookshelfTreeModel::addModule(CSwordModuleInfo *module, } void BtBookshelfTreeModel::removeModule(CSwordModuleInfo *module) { - Item *i(m_modules.value(module, 0)); - if (i == 0) return; + if (!m_modules.contains(module)) return; + + Item *i(m_modules[module]); // Set i to be the lowest item (including empty groups) to remove: Q_ASSERT(i->parent() != 0); @@ -354,22 +381,11 @@ void BtBookshelfTreeModel::removeModule(CSwordModuleInfo *module) { i = i->parent(); } Q_ASSERT(i != 0); - - // Calculate index of parent item: - QModelIndex parentIndex; - { - QList<int> indexes; - for (Item *j(i->parent()); j != m_rootItem; j = j->parent()) { - Q_ASSERT(j != 0); - indexes.push_back(j->childIndex()); - } - while (!indexes.isEmpty()) { - parentIndex = index(indexes.takeLast(), 0, parentIndex); - } - } + Q_ASSERT(i->parent() != 0); // Remove item: int index(i->childIndex()); + QModelIndex parentIndex(getIndex(i->parent())); beginRemoveRows(parentIndex, index, index); i->parent()->deleteChildAt(index); m_modules.remove(module); @@ -388,6 +404,24 @@ Item *BtBookshelfTreeModel::getItem(const QModelIndex &index) const { } } +QModelIndex BtBookshelfTreeModel::getIndex(const BookshelfModel::Item *item) { + Q_ASSERT(item != 0); + + QList<int> indexes; + for (;;) { + int i(item->childIndex()); + if (i < 0) break; + indexes.append(i); + item = item->parent(); + } + + QModelIndex i; + while (!indexes.isEmpty()) { + i = index(indexes.takeLast(), 0, i); + } + return i; +} + void BtBookshelfTreeModel::resetParentCheckStates(QModelIndex parentIndex) { for ( ; parentIndex.isValid(); parentIndex = parentIndex.parent()) { Item *parentItem(static_cast<Item*>(parentIndex.internalPointer())); @@ -445,11 +479,19 @@ void BtBookshelfTreeModel::moduleDataChanged(const QModelIndex &topLeft, QModelIndex moduleIndex(m_sourceModel->index(i, 0, topLeft.parent())); QVariant data(m_sourceModel->data(moduleIndex, PR)); CSwordModuleInfo *module((CSwordModuleInfo *) (data.value<void*>())); + QModelIndex itemIndex(getIndex(m_modules[module])); + Q_ASSERT(itemIndex.isValid()); - /// \todo There might be a better way to do this. - bool checked(m_modules.value(module)->checkState() == Qt::Checked); - removeModule(module); - addModule(module, checked); + emit dataChanged(itemIndex, itemIndex); + + /* + Also emit signals for parent items because the change might alter them + as well, e.g. isHidden() + */ + do { + itemIndex = itemIndex.parent(); + emit dataChanged(itemIndex, itemIndex); + } while (itemIndex.isValid()); } } @@ -457,13 +499,21 @@ void BtBookshelfTreeModel::moduleInserted(const QModelIndex &parent, int start, int end) { typedef BtBookshelfModel BM; static const BM::ModuleRole PR(BM::ModulePointerRole); + static const BM::ModuleRole HR(BM::ModuleHiddenRole); for (int i(start); i <= end; i++) { QModelIndex moduleIndex(m_sourceModel->index(i, 0, parent)); QVariant data(m_sourceModel->data(moduleIndex, PR)); CSwordModuleInfo *module((CSwordModuleInfo *) (data.value<void*>())); - addModule(module, m_defaultChecked); + bool checked; + if (m_defaultChecked == MODULE_HIDDEN) { + checked = !m_sourceModel->data(moduleIndex, HR).toBool(); + } else { + checked = (m_defaultChecked == CHECKED); + } + m_sourceIndexMap[module] = moduleIndex; + addModule(module, checked); } } @@ -478,6 +528,7 @@ void BtBookshelfTreeModel::moduleRemoved(const QModelIndex &parent, int start, CSwordModuleInfo *module((CSwordModuleInfo *) (data.value<void*>())); removeModule(module); + m_sourceIndexMap.remove(module); } } diff --git a/src/backend/bookshelfmodel/btbookshelftreemodel.h b/src/backend/bookshelfmodel/btbookshelftreemodel.h index 84293e1..e73b154 100644 --- a/src/backend/bookshelfmodel/btbookshelftreemodel.h +++ b/src/backend/bookshelfmodel/btbookshelftreemodel.h @@ -16,9 +16,11 @@ #include <QAbstractItemModel> #include <QMap> +#include <QPersistentModelIndex> #include "backend/bookshelfmodel/btbookshelfmodel.h" #include "backend/bookshelfmodel/item.h" + namespace BookshelfModel { class ModuleItem; } @@ -30,6 +32,7 @@ class BtBookshelfTreeModel: public QAbstractItemModel { Q_ENUMS(Group) typedef QMap<CSwordModuleInfo*, BookshelfModel::ModuleItem*> ModuleItemMap; + typedef QMap<CSwordModuleInfo*, QPersistentModelIndex> SourceIndexMap; public: enum ModuleRole { @@ -37,6 +40,7 @@ class BtBookshelfTreeModel: public QAbstractItemModel { UserRole = BtBookshelfModel::UserRole + 100 }; enum Group { GROUP_CATEGORY = 0, GROUP_LANGUAGE, GROUP_DISTRIBUTION }; + enum CheckedBehavior { CHECKED, UNCHECKED, MODULE_HIDDEN }; typedef QList<Group> Grouping; BtBookshelfTreeModel(QObject *parent = 0); @@ -59,8 +63,8 @@ class BtBookshelfTreeModel: public QAbstractItemModel { virtual bool setData(const QModelIndex &index, const QVariant &value, int role); - void setSourceModel(QAbstractListModel *sourceModel); - inline QAbstractListModel *sourceModel() const { + void setSourceModel(QAbstractItemModel *sourceModel); + inline QAbstractItemModel *sourceModel() const { return m_sourceModel; } void setGroupingOrder(const Grouping &groupingOrder); @@ -71,22 +75,24 @@ class BtBookshelfTreeModel: public QAbstractItemModel { inline bool checkable() const { return m_checkable; } - inline void setDefaultChecked(bool defaultChecked) { - m_defaultChecked = defaultChecked; + inline void setDefaultChecked(CheckedBehavior b) { + m_defaultChecked = b; } - inline bool defaultChecked() const { + inline CheckedBehavior defaultChecked() const { return m_defaultChecked; } QList<CSwordModuleInfo*> checkedModules() const; protected: + QVariant parentData(BookshelfModel::ModuleItem *item, int role) const; void addModule(CSwordModuleInfo *module, bool checked); void addModule(CSwordModuleInfo *module, QModelIndex parentIndex, Grouping &intermediateGrouping, bool checked); void removeModule(CSwordModuleInfo *module); BookshelfModel::Item *getItem(const QModelIndex &index) const; + QModelIndex getIndex(const BookshelfModel::Item *item); void resetParentCheckStates(QModelIndex parentIndex); template <class T> @@ -112,13 +118,17 @@ class BtBookshelfTreeModel: public QAbstractItemModel { void moduleInserted(const QModelIndex &parent, int start, int end); void moduleRemoved(const QModelIndex &parent, int start, int end); + signals: + void moduleChecked(CSwordModuleInfo *module, bool checked); + protected: - QAbstractListModel *m_sourceModel; + QAbstractItemModel *m_sourceModel; BookshelfModel::Item *m_rootItem; ModuleItemMap m_modules; + SourceIndexMap m_sourceIndexMap; Grouping m_groupingOrder; + CheckedBehavior m_defaultChecked; bool m_checkable; - bool m_defaultChecked; }; QDataStream &operator<<(QDataStream &os, const BtBookshelfTreeModel::Grouping &o); diff --git a/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp b/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp new file mode 100644 index 0000000..a969218 --- /dev/null +++ b/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp @@ -0,0 +1,71 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2009 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#include "backend/bookshelfmodel/btmodulecategoryfilterproxymodel.h" + +#include "backend/bookshelfmodel/btbookshelfmodel.h" + + +typedef CSwordModuleInfo::Categories CS; + +BtModuleCategoryFilterProxyModel::BtModuleCategoryFilterProxyModel( + QObject *parent) + : QSortFilterProxyModel(parent), m_filter(CSwordModuleInfo::AllCategories), + m_enabled(true) +{ + setFilterRole(BtBookshelfModel::ModuleCategoryRole); +} + +BtModuleCategoryFilterProxyModel::~BtModuleCategoryFilterProxyModel() { + // Intentionally empty +} + +void BtModuleCategoryFilterProxyModel::setEnabled(bool enable) { + m_enabled = enable; + invalidateFilter(); +} + +void BtModuleCategoryFilterProxyModel::setShownCategories(CS cs) { + if (m_filter == cs) return; + m_filter = cs; + invalidateFilter(); +} + +void BtModuleCategoryFilterProxyModel::setHiddenCategories(CS cs) { + cs ^= CSwordModuleInfo::AllCategories; + if (m_filter == cs) return; + m_filter = cs; + invalidateFilter(); +} + +bool BtModuleCategoryFilterProxyModel::filterAcceptsRow(int row, + const QModelIndex &parent) const +{ + typedef CSwordModuleInfo::Category C; + + if (!m_enabled) return true; + + const QAbstractItemModel *m(sourceModel()); + Q_ASSERT(m != 0); + + QModelIndex itemIndex(m->index(row, filterKeyColumn(), parent)); + int numChildren(m->rowCount(itemIndex)); + if (numChildren == 0) { + return m_filter.testFlag(m->data(itemIndex, filterRole()).value<C>()); + } + else { + for (int i(0); i < numChildren; i++) { + if (filterAcceptsRow(i, itemIndex)) return true; + } + return false; + } +} diff --git a/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.h b/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.h new file mode 100644 index 0000000..7517986 --- /dev/null +++ b/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.h @@ -0,0 +1,49 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2009 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#ifndef BTMODULECATEGORYFILTERPROXYMODEL_H +#define BTMODULECATEGORYFILTERPROXYMODEL_H + +#include <QSortFilterProxyModel> + +#include "backend/drivers/cswordmoduleinfo.h" + + +class BtModuleCategoryFilterProxyModel: public QSortFilterProxyModel { + Q_OBJECT + public: + BtModuleCategoryFilterProxyModel(QObject *parent = 0); + virtual ~BtModuleCategoryFilterProxyModel(); + + inline bool enabled() const { + return m_enabled; + } + void setEnabled(bool enable); + + inline CSwordModuleInfo::Categories shownCategories() const { + return m_filter; + } + + inline CSwordModuleInfo::Categories hiddenCategories() const { + return ~m_filter & CSwordModuleInfo::AllCategories; + } + void setShownCategories(CSwordModuleInfo::Categories cs); + void setHiddenCategories(CSwordModuleInfo::Categories cs); + + virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; + + protected: + CSwordModuleInfo::Categories m_filter; + bool m_enabled; +}; + +#endif // BTMODULECATEGORYFILTERPROXYMODEL_H diff --git a/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.cpp b/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.cpp new file mode 100644 index 0000000..3a50300 --- /dev/null +++ b/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.cpp @@ -0,0 +1,61 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2009 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#include "backend/bookshelfmodel/btmodulehiddenfilterproxymodel.h" + +#include "backend/bookshelfmodel/btbookshelfmodel.h" + + +BtModuleHiddenFilterProxyModel::BtModuleHiddenFilterProxyModel(QObject *parent) + : QSortFilterProxyModel(parent), m_enabled(true), m_showHidden(false), + m_showShown(true) { + setFilterRole(BtBookshelfModel::ModuleHiddenRole); +} + +BtModuleHiddenFilterProxyModel::~BtModuleHiddenFilterProxyModel() { + // Intentionally empty +} + +void BtModuleHiddenFilterProxyModel::setEnabled(bool enable) { + if (enable == m_enabled) return; + m_enabled = enable; + invalidateFilter(); +} + +void BtModuleHiddenFilterProxyModel::setShowHidden(bool show) { + if (m_showHidden == show) return; + m_showHidden = show; + invalidateFilter(); +} + +void BtModuleHiddenFilterProxyModel::setShowShown(bool show) { + if (m_showShown == show) return; + m_showShown = show; + invalidateFilter(); +} + +bool BtModuleHiddenFilterProxyModel::filterAcceptsRow(int row, + const QModelIndex &parent) const { + typedef Qt::CheckState CS; + + if (!m_enabled) return true; + + QAbstractItemModel *m(sourceModel()); + + QModelIndex i(m->index(row, filterKeyColumn(), parent)); + if ((CS) m->data(i, filterRole()).toBool()) { + return m_showHidden; + } + else { + return m_showShown; + } +} diff --git a/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.h b/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.h new file mode 100644 index 0000000..8871930 --- /dev/null +++ b/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.h @@ -0,0 +1,48 @@ +/********* +* +* In the name of the Father, and of the Son, and of the Holy Spirit. +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2009 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License +* version 2.0. +* +**********/ + +#ifndef BTMODULEHIDDENFILTERPROXYMODEL_H +#define BTMODULEHIDDENFILTERPROXYMODEL_H + +#include <QSortFilterProxyModel> + + +class BtModuleHiddenFilterProxyModel: public QSortFilterProxyModel { + Q_OBJECT + public: + BtModuleHiddenFilterProxyModel(QObject *parent = 0); + virtual ~BtModuleHiddenFilterProxyModel(); + + inline bool enabled() const { + return m_enabled; + } + void setEnabled(bool enable); + + inline bool showHidden() const { + return m_showHidden; + } + void setShowHidden(bool show); + + inline bool showShown() const { + return m_showShown; + } + void setShowShown(bool show); + + virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; + + protected: + bool m_enabled; + bool m_showHidden; + bool m_showShown; +}; + +#endif // BTMODULEHIDDENFILTERPROXYMODEL_H diff --git a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.cpp b/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.cpp index 31b93e1..1d20cdb 100644 --- a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.cpp +++ b/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.cpp @@ -12,8 +12,12 @@ #include "backend/bookshelfmodel/btmodulenamefilterproxymodel.h" +#include "backend/bookshelfmodel/btbookshelfmodel.h" + + BtModuleNameFilterProxyModel::BtModuleNameFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent), m_enabled(true) { + setFilterRole(BtBookshelfModel::ModuleNameRole); setFilterCaseSensitivity(Qt::CaseInsensitive); } @@ -28,7 +32,7 @@ bool BtModuleNameFilterProxyModel::filterAcceptsRow(int row, const QAbstractItemModel *m(sourceModel()); Q_ASSERT(m != 0); - QModelIndex itemIndex(m->index(row, 0, p)); + QModelIndex itemIndex(m->index(row, filterKeyColumn(), p)); int numChildren(m->rowCount(itemIndex)); if (numChildren == 0) { return QSortFilterProxyModel::filterAcceptsRow(row, p); diff --git a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h b/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h index e4499be..9b24dd6 100644 --- a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h +++ b/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h @@ -15,6 +15,7 @@ #include <QSortFilterProxyModel> + class BtModuleNameFilterProxyModel: public QSortFilterProxyModel { Q_OBJECT public: diff --git a/src/backend/bookshelfmodel/categoryitem.cpp b/src/backend/bookshelfmodel/categoryitem.cpp index 3ce6e88..1788dfc 100644 --- a/src/backend/bookshelfmodel/categoryitem.cpp +++ b/src/backend/bookshelfmodel/categoryitem.cpp @@ -10,7 +10,8 @@ * **********/ -#include "categoryitem.h" +#include "backend/bookshelfmodel/categoryitem.h" + namespace BookshelfModel { @@ -23,7 +24,10 @@ bool CategoryItem::operator<(const Item &other) const { if (other.type() != ITEM_CATEGORY) { return ITEM_CATEGORY < other.type(); } - return m_category < static_cast<const CategoryItem &>(other).m_category; + const CategoryItem &o(static_cast<const CategoryItem &>(other)); + if (m_category == CSwordModuleInfo::UnknownCategory) return false; + if (o.m_category == CSwordModuleInfo::UnknownCategory) return true; + return m_category < o.m_category; } } // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/categoryitem.h b/src/backend/bookshelfmodel/categoryitem.h index 40820a2..fcff12b 100644 --- a/src/backend/bookshelfmodel/categoryitem.h +++ b/src/backend/bookshelfmodel/categoryitem.h @@ -19,6 +19,7 @@ #include "backend/bookshelfmodel/btbookshelfmodel.h" #include "backend/drivers/cswordmoduleinfo.h" + namespace BookshelfModel { class CategoryItem: public Item { @@ -41,7 +42,7 @@ class CategoryItem: public Item { return BtBookshelfModel::categoryIcon(m_category); } - inline bool fitFor(CSwordModuleInfo *module) { + inline bool fitFor(CSwordModuleInfo *module) const { return module->category() == m_category; } diff --git a/src/backend/bookshelfmodel/distributionitem.cpp b/src/backend/bookshelfmodel/distributionitem.cpp index 4ae81c5..fee9c19 100644 --- a/src/backend/bookshelfmodel/distributionitem.cpp +++ b/src/backend/bookshelfmodel/distributionitem.cpp @@ -12,6 +12,7 @@ #include "backend/bookshelfmodel/distributionitem.h" + namespace BookshelfModel { DistributionItem::DistributionItem(CSwordModuleInfo *module) diff --git a/src/backend/bookshelfmodel/distributionitem.h b/src/backend/bookshelfmodel/distributionitem.h index 44ae591..4ae1197 100644 --- a/src/backend/bookshelfmodel/distributionitem.h +++ b/src/backend/bookshelfmodel/distributionitem.h @@ -17,6 +17,7 @@ #include "backend/drivers/cswordmoduleinfo.h" + namespace BookshelfModel { class DistributionItem: public Item { @@ -33,7 +34,7 @@ class DistributionItem: public Item { return m_distribution; } - inline bool fitFor(CSwordModuleInfo *module) { + inline bool fitFor(CSwordModuleInfo *module) const { return module->config(CSwordModuleInfo::DistributionSource) == m_distribution; } diff --git a/src/backend/bookshelfmodel/item.cpp b/src/backend/bookshelfmodel/item.cpp index 8556274..ec2dcab 100644 --- a/src/backend/bookshelfmodel/item.cpp +++ b/src/backend/bookshelfmodel/item.cpp @@ -16,6 +16,7 @@ #include "backend/bookshelfmodel/distributionitem.h" #include "backend/bookshelfmodel/languageitem.h" + namespace BookshelfModel { Item::Item(Type type) @@ -53,4 +54,12 @@ bool Item::operator<(const Item &other) const { return name().localeAwareCompare(other.name()) < 0; } +bool Item::isHidden() const { + if (m_children.empty()) return true; + Q_FOREACH(Item *child, m_children) { + if (!child->isHidden()) return false; + } + return true; +} + } // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/item.h b/src/backend/bookshelfmodel/item.h index b24b503..665343f 100644 --- a/src/backend/bookshelfmodel/item.h +++ b/src/backend/bookshelfmodel/item.h @@ -18,6 +18,7 @@ #include <QString> #include <QtGlobal> + class CSwordModuleInfo; namespace BookshelfModel { @@ -71,9 +72,9 @@ class Item { \brief Returns the index of this item under its parent. \retval -1 if this item has no parent. */ - inline int childIndex() { + inline int childIndex() const { if (m_parent == 0) return -1; - return m_parent->m_children.indexOf(this); + return m_parent->m_children.indexOf(const_cast<Item*>(this)); } /** @@ -149,7 +150,7 @@ class Item { \retval true If this item is a group and can contain the given module. \retval false This item is not a group or a wrong group. */ - inline virtual bool fitFor(CSwordModuleInfo *module) { + inline virtual bool fitFor(CSwordModuleInfo *module) const { Q_UNUSED(module); return false; } @@ -159,6 +160,8 @@ class Item { */ virtual bool operator<(const Item &other) const; + virtual bool isHidden() const; + protected: inline void setParent(Item *parent) { Q_ASSERT(parent != 0); diff --git a/src/backend/bookshelfmodel/languageitem.cpp b/src/backend/bookshelfmodel/languageitem.cpp index 6758178..8d37891 100644 --- a/src/backend/bookshelfmodel/languageitem.cpp +++ b/src/backend/bookshelfmodel/languageitem.cpp @@ -10,7 +10,8 @@ * **********/ -#include "languageitem.h" +#include "backend/bookshelfmodel/languageitem.h" + namespace BookshelfModel { diff --git a/src/backend/bookshelfmodel/languageitem.h b/src/backend/bookshelfmodel/languageitem.h index 262ca65..b5696d9 100644 --- a/src/backend/bookshelfmodel/languageitem.h +++ b/src/backend/bookshelfmodel/languageitem.h @@ -17,7 +17,8 @@ #include "backend/bookshelfmodel/btbookshelfmodel.h" #include "backend/drivers/cswordmoduleinfo.h" -#include "util/directoryutil.h" +#include "util/directory.h" + namespace BookshelfModel { @@ -36,10 +37,10 @@ class LanguageItem: public Item { } inline QIcon icon() const { - return util::filesystem::DirectoryUtil::getIcon("flag.svg"); + return util::directory::getIcon("flag.svg"); } - inline bool fitFor(CSwordModuleInfo *module) { + inline bool fitFor(CSwordModuleInfo *module) const { return module->language() == m_language; } diff --git a/src/backend/bookshelfmodel/moduleitem.cpp b/src/backend/bookshelfmodel/moduleitem.cpp index 8d02111..95e6f62 100644 --- a/src/backend/bookshelfmodel/moduleitem.cpp +++ b/src/backend/bookshelfmodel/moduleitem.cpp @@ -10,10 +10,11 @@ * **********/ -#include "moduleitem.h" +#include "backend/bookshelfmodel/moduleitem.h" #include "util/cresmgr.h" + namespace BookshelfModel { ModuleItem::ModuleItem(CSwordModuleInfo *module) diff --git a/src/backend/bookshelfmodel/moduleitem.h b/src/backend/bookshelfmodel/moduleitem.h index 40ecc79..9657423 100644 --- a/src/backend/bookshelfmodel/moduleitem.h +++ b/src/backend/bookshelfmodel/moduleitem.h @@ -18,6 +18,7 @@ #include "backend/bookshelfmodel/btbookshelfmodel.h" #include "backend/drivers/cswordmoduleinfo.h" + namespace BookshelfModel { class ModuleItem: public Item { @@ -28,12 +29,8 @@ class ModuleItem: public Item { return m_moduleInfo; } - inline QString name() const { - return m_moduleInfo->name(); - } - - inline QIcon icon() const { - return BtBookshelfModel::moduleIcon(m_moduleInfo); + inline bool isHidden() const { + return m_moduleInfo->isHidden(); } protected: |