summaryrefslogtreecommitdiff
path: root/src/backend/bookshelfmodel/btbookshelftreemodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/bookshelfmodel/btbookshelftreemodel.cpp')
-rw-r--r--src/backend/bookshelfmodel/btbookshelftreemodel.cpp205
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);
}
}