diff options
Diffstat (limited to 'src/backend/bookshelfmodel/btbookshelftreemodel.cpp')
-rw-r--r-- | src/backend/bookshelfmodel/btbookshelftreemodel.cpp | 205 |
1 files changed, 128 insertions, 77 deletions
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); } } |