diff options
Diffstat (limited to 'src/backend/bookshelfmodel/btbookshelftreemodel.cpp')
-rw-r--r-- | src/backend/bookshelfmodel/btbookshelftreemodel.cpp | 196 |
1 files changed, 105 insertions, 91 deletions
diff --git a/src/backend/bookshelfmodel/btbookshelftreemodel.cpp b/src/backend/bookshelfmodel/btbookshelftreemodel.cpp index 5be1aec..a2a988c 100644 --- a/src/backend/bookshelfmodel/btbookshelftreemodel.cpp +++ b/src/backend/bookshelfmodel/btbookshelftreemodel.cpp @@ -14,7 +14,7 @@ #include <QSet> #include "backend/bookshelfmodel/categoryitem.h" -#include "backend/bookshelfmodel/distributionitem.h" +#include "backend/bookshelfmodel/indexingitem.h" #include "backend/bookshelfmodel/languageitem.h" #include "backend/bookshelfmodel/moduleitem.h" @@ -30,8 +30,7 @@ BtBookshelfTreeModel::BtBookshelfTreeModel(QObject *parent) BtBookshelfTreeModel::BtBookshelfTreeModel(const Grouping &g, QObject *parent) : QAbstractItemModel(parent), m_sourceModel(0), m_rootItem(new RootItem), - m_groupingOrder(g), m_defaultChecked(MODULE_HIDDEN), m_checkable(false) -{ + m_groupingOrder(g), m_defaultChecked(MODULE_HIDDEN), m_checkable(false) { // Intentionally empty } @@ -44,6 +43,8 @@ int BtBookshelfTreeModel::rowCount(const QModelIndex &parent) const { } int BtBookshelfTreeModel::columnCount(const QModelIndex &parent) const { + Q_UNUSED(parent); + return 1; } @@ -56,7 +57,7 @@ QModelIndex BtBookshelfTreeModel::index(int row, int column, if (!hasIndex(row, column, parent)) return QModelIndex(); Item *parentItem(getItem(parent)); - Item *childItem(parentItem->childAt(row)); + Item *childItem(parentItem->children().at(row)); if (childItem != 0) { return createIndex(row, column, childItem); } @@ -87,55 +88,56 @@ QVariant BtBookshelfTreeModel::data(const QModelIndex &index, int role) const { Item *i(static_cast<Item*>(index.internalPointer())); Q_ASSERT(i != 0); switch (role) { - case Qt::DisplayRole: - 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: - if (i->type() == Item::ITEM_MODULE) { - return parentData(static_cast<ModuleItem *>(i), role); - } else { - return i->icon(); - } case BtBookshelfModel::ModulePointerRole: + /* This case is just an optimization. */ if (i->type() == Item::ITEM_MODULE) { ModuleItem *mi(static_cast<ModuleItem *>(i)); return qVariantFromValue((void*) mi->moduleInfo()); } return 0; + case Qt::DisplayRole: + case Qt::DecorationRole: case BtBookshelfModel::ModuleHiddenRole: - return i->isHidden(); default: if (i->type() == Item::ITEM_MODULE) { - return parentData(static_cast<ModuleItem *>(i), role); + ModuleItem *item(static_cast<ModuleItem *>(i)); + CSwordModuleInfo* m(item->moduleInfo()); + return data(m, role); + } + else { + return i->data(role); } - break; } return QVariant(); } +QVariant BtBookshelfTreeModel::data(CSwordModuleInfo *module, int role) const { + Q_ASSERT(m_sourceIndexMap.contains(module)); + return m_sourceModel->data(m_sourceIndexMap.value(module), role); +} + bool BtBookshelfTreeModel::setData(const QModelIndex &itemIndex, const QVariant &value, int role) { typedef QPair<Item *, QModelIndex> IP; Qt::CheckState newState; - if (role == BtBookshelfModel::ModuleHiddenRole) { - newState = value.toBool() ? Qt::Checked : Qt::Unchecked; - } else if (role == Qt::CheckStateRole) { + if (role == Qt::CheckStateRole) { bool ok; newState = (Qt::CheckState) value.toInt(&ok); - if (!ok || newState == Qt::PartiallyChecked) return false; - } else { + if (!ok) return false; + } + else { return false; } + // Handle partially checked as checked here in setData(): + if (newState == Qt::PartiallyChecked) newState = Qt::Checked; + Item *item(static_cast<Item*>(itemIndex.internalPointer())); Q_ASSERT(item != 0); if (item->checkState() == newState) return false; @@ -148,9 +150,18 @@ bool BtBookshelfTreeModel::setData(const QModelIndex &itemIndex, 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 { + ModuleItem *mItem(static_cast<ModuleItem*>(item)); + CSwordModuleInfo *mInfo(mItem->moduleInfo()); + if (newState == Qt::Checked) { + m_checkedModulesCache.insert(mInfo); + emit moduleChecked(mInfo, true); + } + else { + m_checkedModulesCache.remove(mInfo); + emit moduleChecked(mInfo, false); + } + } + 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))); @@ -207,6 +218,7 @@ void BtBookshelfTreeModel::setSourceModel(QAbstractItemModel *sourceModel) { delete m_rootItem; m_modules.clear(); m_sourceIndexMap.clear(); + m_checkedModulesCache.clear(); m_rootItem = new RootItem; endRemoveRows(); } @@ -225,6 +237,8 @@ void BtBookshelfTreeModel::setSourceModel(QAbstractItemModel *sourceModel) { typedef BtBookshelfModel::ModuleRole MRole; static const MRole HR(BtBookshelfModel::ModuleHiddenRole); static const MRole PR(BtBookshelfModel::ModulePointerRole); + static const MRole IR(BtBookshelfModel::ModuleHasIndexRole); + QModelIndex moduleIndex(sourceModel->index(i, 0)); CSwordModuleInfo *module( static_cast<CSwordModuleInfo *>( @@ -235,7 +249,11 @@ void BtBookshelfTreeModel::setSourceModel(QAbstractItemModel *sourceModel) { bool checked; if (m_defaultChecked == MODULE_HIDDEN) { checked = !sourceModel->data(moduleIndex, HR).toBool(); - } else { + } + else if (m_defaultChecked == MODULE_INDEXED) { + checked = !sourceModel->data(moduleIndex, IR).toBool(); + } + else { checked = (m_defaultChecked == CHECKED); } m_sourceIndexMap[module] = moduleIndex; @@ -249,32 +267,28 @@ void BtBookshelfTreeModel::setGroupingOrder(const Grouping &groupingOrder) { m_groupingOrder = groupingOrder; if (m_sourceModel != 0) { - QSet<CSwordModuleInfo*> checked(checkedModules().toSet()); + QSet<CSwordModuleInfo*> checked(m_checkedModulesCache); + m_checkedModulesCache.clear(); + beginRemoveRows(QModelIndex(), 0, m_rootItem->children().size() - 1); delete m_rootItem; m_modules.clear(); m_rootItem = new RootItem; endRemoveRows(); - BtBookshelfModel *m(dynamic_cast<BtBookshelfModel*>(m_sourceModel)); - if (m != 0) { - Q_FOREACH(CSwordModuleInfo *module, m->modules()) { - addModule(module, checked.contains(module)); - } - } - else { - for (int i(0); i < m_sourceModel->rowCount(); i++) { - CSwordModuleInfo *module( - static_cast<CSwordModuleInfo *>( - m_sourceModel->data( - m_sourceModel->index(i, 0), - BtBookshelfModel::ModulePointerRole - ).value<void*>() - ) - ); - Q_ASSERT(module != 0); - addModule(module, checked.contains(module)); - } + for (int i(0); i < m_sourceModel->rowCount(); i++) { + QModelIndex sourceIndex(m_sourceModel->index(i, 0)); + CSwordModuleInfo *module( + static_cast<CSwordModuleInfo *>( + m_sourceModel->data( + sourceIndex, + BtBookshelfModel::ModulePointerRole + ).value<void*>() + ) + ); + Q_ASSERT(module != 0); + m_sourceIndexMap[module] = sourceIndex; + addModule(module, checked.contains(module)); } } } @@ -282,43 +296,24 @@ void BtBookshelfTreeModel::setGroupingOrder(const Grouping &groupingOrder) { void BtBookshelfTreeModel::setCheckable(bool checkable) { if (m_checkable == checkable) return; m_checkable = checkable; - if (m_sourceModel != 0) { - QModelIndexList queue; - queue.append(QModelIndex()); - do { - QModelIndex parent(queue.takeFirst()); - int numChildren(rowCount(parent)); - emit dataChanged(index(0, 0, parent), - index(numChildren - 1, 0, parent)); - for (int i(0); i < numChildren; i++) { - QModelIndex childIndex(index(i, 0, parent)); - if (rowCount(childIndex) > 0) { - queue.append(childIndex); - } + if (m_sourceModel == 0) return; + + // Notify views that flags changed for all items: + QModelIndexList queue; + queue.append(QModelIndex()); + do { + QModelIndex parent(queue.takeFirst()); + int numChildren(rowCount(parent)); + emit dataChanged(index(0, 0, parent), + index(numChildren - 1, 0, parent)); + for (int i(0); i < numChildren; i++) { + QModelIndex childIndex(index(i, 0, parent)); + if (rowCount(childIndex) > 0) { + queue.append(childIndex); } } - while (!queue.isEmpty()); - } -} - -QList<CSwordModuleInfo*> BtBookshelfTreeModel::checkedModules() const { - typedef ModuleItemMap::const_iterator MMCI; - - QList<CSwordModuleInfo*> modules; - for (MMCI it(m_modules.constBegin()); it != m_modules.constEnd(); it++) { - if (it.value()->checkState() == Qt::Checked) { - modules.append(it.key()); - } } - 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); + while (!queue.isEmpty()); } void BtBookshelfTreeModel::addModule(CSwordModuleInfo *module, bool checked) { @@ -344,28 +339,36 @@ void BtBookshelfTreeModel::addModule(CSwordModuleInfo *module, if (!intermediateGrouping.empty()) { QModelIndex newIndex; switch (intermediateGrouping.front()) { - case GROUP_DISTRIBUTION: - newIndex = getGroup<DistributionItem>(module, parentIndex); - break; case GROUP_CATEGORY: newIndex = getGroup<CategoryItem>(module, parentIndex); break; case GROUP_LANGUAGE: newIndex = getGroup<LanguageItem>(module, parentIndex); break; + case GROUP_INDEXING: + newIndex = getGroup<IndexingItem>(module, parentIndex); + break; } intermediateGrouping.pop_front(); addModule(module, newIndex, intermediateGrouping, checked); } else { Item *parentItem(getItem(parentIndex)); - ModuleItem *newItem(new ModuleItem(module)); + ModuleItem *newItem(new ModuleItem(module, this)); newItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked); const int newIndex(parentItem->indexFor(newItem)); + + // Actually do the insertion: beginInsertRows(parentIndex, newIndex, newIndex); parentItem->insertChild(newIndex, newItem); m_modules.insert(module, newItem); + if (checked) { + // Add to checked modules cache + m_checkedModulesCache.insert(module); + } endInsertRows(); + + // Reset parent item check states, if needed: resetParentCheckStates(parentIndex); } } @@ -383,13 +386,18 @@ void BtBookshelfTreeModel::removeModule(CSwordModuleInfo *module) { Q_ASSERT(i != 0); Q_ASSERT(i->parent() != 0); - // Remove item: + // Calculate item indexes: int index(i->childIndex()); QModelIndex parentIndex(getIndex(i->parent())); + + // Actually remove the item: beginRemoveRows(parentIndex, index, index); - i->parent()->deleteChildAt(index); + delete i->parent()->children().takeAt(index); m_modules.remove(module); + m_checkedModulesCache.remove(module); endRemoveRows(); + + // Reset parent item check states, if needed: resetParentCheckStates(parentIndex); } @@ -431,7 +439,7 @@ void BtBookshelfTreeModel::resetParentCheckStates(QModelIndex parentIndex) { bool haveCheckedChildren(false); bool haveUncheckedChildren(false); for (int i(0); i < parentItem->children().size(); i++) { - Qt::CheckState state(parentItem->childAt(i)->checkState()); + Qt::CheckState state(parentItem->children().at(i)->checkState()); if (state == Qt::PartiallyChecked) { haveCheckedChildren = true; haveUncheckedChildren = true; @@ -491,7 +499,8 @@ void BtBookshelfTreeModel::moduleDataChanged(const QModelIndex &topLeft, do { itemIndex = itemIndex.parent(); emit dataChanged(itemIndex, itemIndex); - } while (itemIndex.isValid()); + } + while (itemIndex.isValid()); } } @@ -500,6 +509,7 @@ void BtBookshelfTreeModel::moduleInserted(const QModelIndex &parent, int start, typedef BtBookshelfModel BM; static const BM::ModuleRole PR(BM::ModulePointerRole); static const BM::ModuleRole HR(BM::ModuleHiddenRole); + static const BM::ModuleRole IR(BM::ModuleHasIndexRole); for (int i(start); i <= end; i++) { QModelIndex moduleIndex(m_sourceModel->index(i, 0, parent)); @@ -509,7 +519,11 @@ void BtBookshelfTreeModel::moduleInserted(const QModelIndex &parent, int start, bool checked; if (m_defaultChecked == MODULE_HIDDEN) { checked = !m_sourceModel->data(moduleIndex, HR).toBool(); - } else { + } + else if (m_defaultChecked == MODULE_INDEXED) { + checked = !m_sourceModel->data(moduleIndex, IR).toBool(); + } + else { checked = (m_defaultChecked == CHECKED); } m_sourceIndexMap[module] = moduleIndex; |