diff options
author | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:33 -0400 |
---|---|---|
committer | Roberto C. Sanchez <roberto@connexer.com> | 2014-10-21 22:48:33 -0400 |
commit | 4885bfcef4d89cf0cb391e00af617b9fd19c9cbb (patch) | |
tree | e8ba8579bd76a1b277231202ca6579eb19c1ab4b /src/backend | |
parent | 294b5ec5834affa57641475946b8d2aeca53c577 (diff) |
Imported Upstream version 2.5
Diffstat (limited to 'src/backend')
38 files changed, 886 insertions, 871 deletions
diff --git a/src/backend/bookshelfmodel/btbookshelffiltermodel.cpp b/src/backend/bookshelfmodel/btbookshelffiltermodel.cpp new file mode 100644 index 0000000..b896556 --- /dev/null +++ b/src/backend/bookshelfmodel/btbookshelffiltermodel.cpp @@ -0,0 +1,202 @@ +/********* +* +* 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/btbookshelffiltermodel.h" + +#include "backend/bookshelfmodel/btbookshelfmodel.h" + + +BtBookshelfFilterModel::BtBookshelfFilterModel(QObject *parent) + : QSortFilterProxyModel(parent), m_enabled(true), + m_nameFilterRole(BtBookshelfModel::ModuleNameRole), m_nameFilterColumn(0), + m_nameFilterCase(Qt::CaseInsensitive), + m_hiddenFilterRole(BtBookshelfModel::ModuleHiddenRole), + m_hiddenFilterColumn(0), m_showHidden(false), m_showShown(true), + m_categoryFilter(CSwordModuleInfo::AllCategories), + m_categoryFilterRole(BtBookshelfModel::ModuleCategoryRole), + m_categoryFilterColumn(0) +{ + // Intentionally empty +} + +BtBookshelfFilterModel::~BtBookshelfFilterModel() { + // Intentionally empty +} + +void BtBookshelfFilterModel::setEnabled(bool enable) { + if (enable == m_enabled) return; + m_enabled = enable; + invalidateFilter(); +} + +// Name filter: + +void BtBookshelfFilterModel::setNameFilterRole(int role) { + if (m_nameFilterRole == role) return; + m_nameFilterRole = role; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setNameFilterKeyColumn(int column) { + if (m_nameFilterColumn == column) return; + m_nameFilterColumn = column; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setNameFilterFixedString(const QString &filter) { + if (m_nameFilter == filter) return; + m_nameFilter = filter; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setNameFilterCase(Qt::CaseSensitivity value) { + if (m_nameFilterCase == value) return; + m_nameFilterCase = value; + invalidateFilter(); +} + +// Hidden filter: + +void BtBookshelfFilterModel::setHiddenFilterRole(int role) { + if (m_hiddenFilterRole == role) return; + m_hiddenFilterRole = role; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setHiddenFilterKeyColumn(int column) { + if (m_hiddenFilterColumn == column) return; + m_hiddenFilterColumn = column; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setShowHidden(bool show) { + if (m_showHidden == show) return; + m_showHidden = show; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setShowShown(bool show) { + if (m_showShown == show) return; + m_showShown = show; + invalidateFilter(); +} + +// Category filter: + +void BtBookshelfFilterModel::setCategoryFilterRole(int role) { + if (m_categoryFilterRole == role) return; + m_categoryFilterRole = role; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setCategoryFilterKeyColumn(int column) { + if (m_categoryFilterColumn == column) return; + m_categoryFilterColumn = column; + invalidateFilter(); +} + +void BtBookshelfFilterModel::setShownCategories( + const CSwordModuleInfo::Categories &categories) +{ + if (m_categoryFilter == categories) return; + m_categoryFilter = categories; + invalidateFilter(); +} + +// Filtering: + +bool BtBookshelfFilterModel::filterAcceptsRow(int row, + const QModelIndex &parent) const +{ + if (!m_enabled) return true; + + if (!hiddenFilterAcceptsRow(row, parent)) return false; + if (!nameFilterAcceptsRow(row, parent)) return false; + if (!categoryFilterAcceptsRow(row, parent)) return false; + return true; +} + +bool BtBookshelfFilterModel::nameFilterAcceptsRow(int row, const QModelIndex &p) + const +{ + if (!m_enabled) return true; + if (m_nameFilter.isEmpty()) return true; + + const QAbstractItemModel *m(sourceModel()); + Q_ASSERT(m != 0); + + QModelIndex itemIndex(m->index(row, m_nameFilterColumn, p)); + int numChildren(m->rowCount(itemIndex)); + if (numChildren == 0) { + QVariant data(m->data(itemIndex, m_nameFilterRole)); + return data.toString().contains(m_nameFilter, m_nameFilterCase); + } + else { + for (int i(0); i < numChildren; i++) { + if (filterAcceptsRow(i, itemIndex)) return true; + } + return false; + } +} + +bool BtBookshelfFilterModel::hiddenFilterAcceptsRow(int row, + const QModelIndex &parent) const +{ + if (m_showHidden && m_showShown) return true; + + typedef Qt::CheckState CS; + + QAbstractItemModel *m(sourceModel()); + + QModelIndex itemIndex(m->index(row, m_hiddenFilterColumn, parent)); + int numChildren(m->rowCount(itemIndex)); + if (numChildren == 0) { + if ((CS) m->data(itemIndex, m_hiddenFilterRole).toBool()) { + return m_showHidden; + } + else { + return m_showShown; + } + } + else { + for (int i(0); i < numChildren; i++) { + if (filterAcceptsRow(i, itemIndex)) return true; + } + return false; + } +} + +bool BtBookshelfFilterModel::categoryFilterAcceptsRow(int row, + const QModelIndex &parent) const +{ + if (m_categoryFilter == CSwordModuleInfo::AllCategories) return true; + + QAbstractItemModel *m(sourceModel()); + + QModelIndex itemIndex(m->index(row, m_categoryFilterColumn, parent)); + int numChildren(m->rowCount(itemIndex)); + if (numChildren == 0) { + int cat = m->data(itemIndex, m_categoryFilterRole).toInt(); + if (m_categoryFilter.testFlag((CSwordModuleInfo::Category) cat)) { + return true; + } + else { + return false; + } + } + else { + for (int i(0); i < numChildren; i++) { + if (filterAcceptsRow(i, itemIndex)) return true; + } + return false; + } +} diff --git a/src/backend/bookshelfmodel/btbookshelffiltermodel.h b/src/backend/bookshelfmodel/btbookshelffiltermodel.h new file mode 100644 index 0000000..e440c69 --- /dev/null +++ b/src/backend/bookshelfmodel/btbookshelffiltermodel.h @@ -0,0 +1,127 @@ +/********* +* +* 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 BTBOOKSHELFFILTERMODEL_H +#define BTBOOKSHELFFILTERMODEL_H + +#include <QSortFilterProxyModel> + +#include "backend/drivers/cswordmoduleinfo.h" + + +class BtBookshelfFilterModel: public QSortFilterProxyModel { + Q_OBJECT + public: + BtBookshelfFilterModel(QObject *parent = 0); + virtual ~BtBookshelfFilterModel(); + + // Common methods: + inline bool enabled() const { + return m_enabled; + } + + virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; + + // Name filter: + inline int nameFilterRole() const { + return m_nameFilterRole; + } + + inline int nameFilterKeyColumn() const { + return m_nameFilterColumn; + } + + inline const QString &nameFilter() const { + return m_nameFilter; + } + + inline const Qt::CaseSensitivity nameFilterCase() const { + return m_nameFilterCase; + } + + // Hidden filter: + int hiddenFilterRole() const { + return m_hiddenFilterRole; + } + + int hiddenFilterKeyColumn() const { + return m_hiddenFilterColumn; + } + + inline bool showHidden() const { + return m_showHidden; + } + + inline bool showShown() const { + return m_showShown; + } + + // Category filter: + int categoryFilterRole() const { + return m_categoryFilterRole; + } + + int categoryFilterKeyColumn() const { + return m_categoryFilterColumn; + } + + inline CSwordModuleInfo::Categories shownCategories() const { + return m_categoryFilter; + } + + public slots: + void setEnabled(bool enable); + + // Name filter: + void setNameFilterRole(int role); + void setNameFilterKeyColumn(int column); + void setNameFilterFixedString(const QString &nameFilter); + void setNameFilterCase(Qt::CaseSensitivity value); + + // Hidden filter: + void setHiddenFilterRole(int role); + void setHiddenFilterKeyColumn(int column); + void setShowHidden(bool show); + void setShowShown(bool show); + + // Category filter: + void setCategoryFilterRole(int role); + void setCategoryFilterKeyColumn(int column); + void setShownCategories(const CSwordModuleInfo::Categories &categories); + + protected: + bool nameFilterAcceptsRow(int row, const QModelIndex &parent) const; + bool hiddenFilterAcceptsRow(int row, const QModelIndex &parent) const; + bool categoryFilterAcceptsRow(int row, const QModelIndex &parent) const; + + protected: + bool m_enabled; + + // Name filter: + QString m_nameFilter; + int m_nameFilterRole; + int m_nameFilterColumn; + Qt::CaseSensitivity m_nameFilterCase; + + // Hidden filter: + int m_hiddenFilterRole; + int m_hiddenFilterColumn; + bool m_showHidden; + bool m_showShown; + + // Categories filter: + CSwordModuleInfo::Categories m_categoryFilter; + int m_categoryFilterRole; + int m_categoryFilterColumn; +}; + +#endif // BTBOOKSHELFFILTERMODEL_H diff --git a/src/backend/bookshelfmodel/btbookshelfmodel.cpp b/src/backend/bookshelfmodel/btbookshelfmodel.cpp index 6882b90..ccbb5a5 100644 --- a/src/backend/bookshelfmodel/btbookshelfmodel.cpp +++ b/src/backend/bookshelfmodel/btbookshelfmodel.cpp @@ -27,6 +27,8 @@ BtBookshelfModel::~BtBookshelfModel() { } int BtBookshelfModel::rowCount(const QModelIndex &parent) const { + if (parent.isValid()) return 0; + return m_data.size(); } @@ -44,6 +46,12 @@ QVariant BtBookshelfModel::data(CSwordModuleInfo *module, int role) const { return QVariant(); /// \todo Unimplemented case ModuleHiddenRole: return module->isHidden(); + case ModuleInstallPathRole: + return module->config(CSwordModuleInfo::AbsoluteDataPath); + case ModuleHasIndexRole: + return module->hasIndex(); + case ModuleIndexSizeRole: + return (qulonglong) module->indexSize(); default: return QVariant(); } @@ -73,8 +81,7 @@ 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) - { + && 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 @@ -97,25 +104,29 @@ QIcon BtBookshelfModel::moduleIcon(const CSwordModuleInfo *m) { case CSwordModuleInfo::Bibles: if (module->isLocked()) { return DU::getIcon(CResMgr::modules::bible::icon_locked); - } else { + } + else { return DU::getIcon(CResMgr::modules::bible::icon_unlocked); } case CSwordModuleInfo::Commentaries: if (module->isLocked()) { return DU::getIcon(CResMgr::modules::commentary::icon_locked); - } else { + } + else { return DU::getIcon(CResMgr::modules::commentary::icon_unlocked); } case CSwordModuleInfo::Lexicons: if (module->isLocked()) { return DU::getIcon(CResMgr::modules::lexicon::icon_locked); - } else { + } + else { return DU::getIcon(CResMgr::modules::lexicon::icon_unlocked); } case CSwordModuleInfo::Books: if (module->isLocked()) { return DU::getIcon(CResMgr::modules::book::icon_locked); - } else { + } + else { return DU::getIcon(CResMgr::modules::book::icon_unlocked); } case CSwordModuleInfo::Cult: @@ -204,6 +215,8 @@ void BtBookshelfModel::addModule(CSwordModuleInfo * const module) { m_data.append(module); connect(module, SIGNAL(hiddenChanged(bool)), this, SLOT(moduleHidden(bool))); + connect(module, SIGNAL(hasIndexChanged(bool)), + this, SLOT(moduleIndexed(bool))); endInsertRows(); } @@ -227,33 +240,34 @@ void BtBookshelfModel::addModules(const QSet<CSwordModuleInfo *> &modules) { m_data.append(module); connect(module, SIGNAL(hiddenChanged(bool)), this, SLOT(moduleHidden(bool))); + connect(module, SIGNAL(hasIndexChanged(bool)), + this, SLOT(moduleIndexed(bool))); } endInsertRows(); } void BtBookshelfModel::removeModule(CSwordModuleInfo * const module, - bool destroy) -{ + bool destroy) { const int index(m_data.indexOf(module)); if (index == -1) return; beginRemoveRows(QModelIndex(), index, index); disconnect(module, SIGNAL(hiddenChanged(bool)), this, SLOT(moduleHidden(bool))); + disconnect(module, SIGNAL(hasIndexChanged(bool)), + this, SLOT(moduleIndexed(bool))); m_data.removeAt(index); endRemoveRows(); if (destroy) delete module; } void BtBookshelfModel::removeModules(const QList<CSwordModuleInfo *> &modules, - bool destroy) -{ + bool destroy) { removeModules(modules.toSet(), destroy); } void BtBookshelfModel::removeModules(const QSet<CSwordModuleInfo *> &modules, - bool destroy) -{ + bool destroy) { // This is inefficient, since signals are emitted for each removed module: Q_FOREACH(CSwordModuleInfo *module, modules) { removeModule(module, destroy); @@ -270,7 +284,16 @@ CSwordModuleInfo* BtBookshelfModel::getModule(const QString &name) const { void BtBookshelfModel::moduleHidden(bool) { Q_ASSERT(qobject_cast<CSwordModuleInfo*>(sender()) != 0); - CSwordModuleInfo *module(static_cast<CSwordModuleInfo*>(sender())); + moduleDataChanged(static_cast<CSwordModuleInfo*>(sender())); +} + +void BtBookshelfModel::moduleIndexed(bool) { + Q_ASSERT(qobject_cast<CSwordModuleInfo*>(sender()) != 0); + + moduleDataChanged(static_cast<CSwordModuleInfo*>(sender())); +} + +void BtBookshelfModel::moduleDataChanged(CSwordModuleInfo *module) { Q_ASSERT(m_data.count(module) == 1); QModelIndex i(index(m_data.indexOf(module), 0)); diff --git a/src/backend/bookshelfmodel/btbookshelfmodel.h b/src/backend/bookshelfmodel/btbookshelfmodel.h index 16fdb13..735c655 100644 --- a/src/backend/bookshelfmodel/btbookshelfmodel.h +++ b/src/backend/bookshelfmodel/btbookshelfmodel.h @@ -28,6 +28,9 @@ class BtBookshelfModel: public QAbstractListModel { ModuleCategoryRole = Qt::UserRole + 1, ModuleLanguageRole = Qt::UserRole + 2, ModuleHiddenRole = Qt::UserRole + 3, + ModuleInstallPathRole = Qt::UserRole + 4, + ModuleHasIndexRole = Qt::UserRole + 5, + ModuleIndexSizeRole = Qt::UserRole + 6, UserRole = Qt::UserRole + 100 }; @@ -71,6 +74,10 @@ class BtBookshelfModel: public QAbstractListModel { protected slots: void moduleHidden(bool hidden); + void moduleIndexed(bool indexed); + + protected: + void moduleDataChanged(CSwordModuleInfo *module); protected: QList<CSwordModuleInfo *> m_data; 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; diff --git a/src/backend/bookshelfmodel/btbookshelftreemodel.h b/src/backend/bookshelfmodel/btbookshelftreemodel.h index e73b154..47ce672 100644 --- a/src/backend/bookshelfmodel/btbookshelftreemodel.h +++ b/src/backend/bookshelfmodel/btbookshelftreemodel.h @@ -15,8 +15,10 @@ #include <QAbstractItemModel> +#include <QList> #include <QMap> #include <QPersistentModelIndex> +#include <QSet> #include "backend/bookshelfmodel/btbookshelfmodel.h" #include "backend/bookshelfmodel/item.h" @@ -39,8 +41,17 @@ class BtBookshelfTreeModel: public QAbstractItemModel { CheckStateRole = BtBookshelfModel::UserRole, UserRole = BtBookshelfModel::UserRole + 100 }; - enum Group { GROUP_CATEGORY = 0, GROUP_LANGUAGE, GROUP_DISTRIBUTION }; - enum CheckedBehavior { CHECKED, UNCHECKED, MODULE_HIDDEN }; + enum Group { + GROUP_CATEGORY = 0, + GROUP_LANGUAGE = 1, + GROUP_INDEXING + }; + enum CheckedBehavior { + CHECKED, /**< Check all added modules by default. */ + UNCHECKED, /**< Uncheck all added modules by default. */ + MODULE_HIDDEN, /**< By default, check only added modules that are not hidden. */ + MODULE_INDEXED /**< By default, check only added modules that are indexed. */ + }; typedef QList<Group> Grouping; BtBookshelfTreeModel(QObject *parent = 0); @@ -56,7 +67,8 @@ class BtBookshelfTreeModel: public QAbstractItemModel { const QModelIndex &parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex &index) const; - virtual QVariant data(const QModelIndex &index, int role) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(CSwordModuleInfo *module, int role = Qt::DisplayRole) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; @@ -82,7 +94,9 @@ class BtBookshelfTreeModel: public QAbstractItemModel { return m_defaultChecked; } - QList<CSwordModuleInfo*> checkedModules() const; + inline const QSet<CSwordModuleInfo*> &checkedModules() const { + return m_checkedModulesCache; + } protected: QVariant parentData(BookshelfModel::ModuleItem *item, int role) const; @@ -100,7 +114,7 @@ class BtBookshelfTreeModel: public QAbstractItemModel { QModelIndex parentIndex) { BookshelfModel::Item *parentItem(getItem(parentIndex)); int groupIndex; - T *groupItem(parentItem->getGroupItem<T>(module, &groupIndex)); + T *groupItem(parentItem->getGroupItem<T>(module, groupIndex)); if (groupItem == 0) { groupItem = new T(module); @@ -129,6 +143,8 @@ class BtBookshelfTreeModel: public QAbstractItemModel { Grouping m_groupingOrder; CheckedBehavior m_defaultChecked; bool m_checkable; + + QSet<CSwordModuleInfo*> m_checkedModulesCache; }; QDataStream &operator<<(QDataStream &os, const BtBookshelfTreeModel::Grouping &o); diff --git a/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.cpp b/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.cpp deleted file mode 100644 index 184bd39..0000000 --- a/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/********* -* -* 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/btcheckstatefilterproxymodel.h" - -BtCheckStateFilterProxyModel::BtCheckStateFilterProxyModel(QObject *parent) - : QSortFilterProxyModel(parent), m_enabled(true), m_showChecked(true), - m_showUnchecked(false), m_showPartiallyChecked(true) { - setFilterRole(Qt::CheckStateRole); -} - -BtCheckStateFilterProxyModel::~BtCheckStateFilterProxyModel() { - // Intentionally empty -} - -void BtCheckStateFilterProxyModel::setEnabled(bool enable) { - if (enable == m_enabled) return; - m_enabled = enable; - invalidateFilter(); -} - -void BtCheckStateFilterProxyModel::setShowChecked(bool show) { - if (m_showChecked == show) return; - m_showChecked = show; - invalidateFilter(); -} - -void BtCheckStateFilterProxyModel::setShowUnchecked(bool show) { - if (m_showUnchecked == show) return; - m_showUnchecked = show; - invalidateFilter(); -} - -void BtCheckStateFilterProxyModel::setShowPartiallyChecked(bool show) { - if (m_showPartiallyChecked == show) return; - m_showPartiallyChecked = show; - invalidateFilter(); -} - -bool BtCheckStateFilterProxyModel::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)); - CS state((CS) m->data(i, filterRole()).toInt()); - Q_ASSERT(state == Qt::Checked || state == Qt::Unchecked || - state == Qt::PartiallyChecked); - if (state == Qt::Unchecked) { - return m_showUnchecked; - } - else if (state == Qt::Checked) { - return m_showChecked; - } - else { - return m_showPartiallyChecked; - } -} diff --git a/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.h b/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.h deleted file mode 100644 index 78d324d..0000000 --- a/src/backend/bookshelfmodel/btcheckstatefilterproxymodel.h +++ /dev/null @@ -1,53 +0,0 @@ -/********* -* -* 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 BTCHECKSTATEFILTERPROXYMODEL_H -#define BTCHECKSTATEFILTERPROXYMODEL_H - -#include <QSortFilterProxyModel> - -class BtCheckStateFilterProxyModel: public QSortFilterProxyModel { - Q_OBJECT - public: - BtCheckStateFilterProxyModel(QObject *parent = 0); - virtual ~BtCheckStateFilterProxyModel(); - - inline bool enabled() const { - return m_enabled; - } - void setEnabled(bool enable); - - inline bool showChecked() const { - return m_showChecked; - } - void setShowChecked(bool show); - - inline bool showUnchecked() const { - return m_showUnchecked; - } - void setShowUnchecked(bool show); - - inline bool showPartiallyChecked() const { - return m_showPartiallyChecked; - } - void setShowPartiallyChecked(bool show); - - virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; - - protected: - bool m_enabled; - bool m_showChecked; - bool m_showUnchecked; - bool m_showPartiallyChecked; -}; - -#endif // BTSELECTEDMODULESBOOKSHELFPROXYMODEL_H diff --git a/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp b/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp deleted file mode 100644 index a969218..0000000 --- a/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/********* -* -* 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 deleted file mode 100644 index 7517986..0000000 --- a/src/backend/bookshelfmodel/btmodulecategoryfilterproxymodel.h +++ /dev/null @@ -1,49 +0,0 @@ -/********* -* -* 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 deleted file mode 100644 index 3a50300..0000000 --- a/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/********* -* -* 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 deleted file mode 100644 index 8871930..0000000 --- a/src/backend/bookshelfmodel/btmodulehiddenfilterproxymodel.h +++ /dev/null @@ -1,48 +0,0 @@ -/********* -* -* 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 deleted file mode 100644 index 1d20cdb..0000000 --- a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/********* -* -* 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/btmodulenamefilterproxymodel.h" - -#include "backend/bookshelfmodel/btbookshelfmodel.h" - - -BtModuleNameFilterProxyModel::BtModuleNameFilterProxyModel(QObject *parent) - : QSortFilterProxyModel(parent), m_enabled(true) { - setFilterRole(BtBookshelfModel::ModuleNameRole); - setFilterCaseSensitivity(Qt::CaseInsensitive); -} - -BtModuleNameFilterProxyModel::~BtModuleNameFilterProxyModel() { - // Intentionally empty -} - -bool BtModuleNameFilterProxyModel::filterAcceptsRow(int row, - const QModelIndex &p) const { - if (!m_enabled) return true; - - const QAbstractItemModel *m(sourceModel()); - Q_ASSERT(m != 0); - - QModelIndex itemIndex(m->index(row, filterKeyColumn(), p)); - int numChildren(m->rowCount(itemIndex)); - if (numChildren == 0) { - return QSortFilterProxyModel::filterAcceptsRow(row, p); - } - else { - for (int i(0); i < numChildren; i++) { - if (filterAcceptsRow(i, itemIndex)) return true; - } - return false; - } -} diff --git a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h b/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h deleted file mode 100644 index 9b24dd6..0000000 --- a/src/backend/bookshelfmodel/btmodulenamefilterproxymodel.h +++ /dev/null @@ -1,37 +0,0 @@ -/********* -* -* 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 BTMODULENAMEFILTERPROXYMODEL_H -#define BTMODULENAMEFILTERPROXYMODEL_H - -#include <QSortFilterProxyModel> - - -class BtModuleNameFilterProxyModel: public QSortFilterProxyModel { - Q_OBJECT - public: - BtModuleNameFilterProxyModel(QObject *parent = 0); - virtual ~BtModuleNameFilterProxyModel(); - - inline bool enabled() const { - return m_enabled; - } - void setEnabled(bool enable); - - virtual bool filterAcceptsRow(int row, const QModelIndex &parent) const; - - protected: - QString m_filter; - bool m_enabled; -}; - -#endif // BTMODULENAMEFILTERPROXYMODEL_H diff --git a/src/backend/bookshelfmodel/categoryitem.cpp b/src/backend/bookshelfmodel/categoryitem.cpp index 1788dfc..46905d7 100644 --- a/src/backend/bookshelfmodel/categoryitem.cpp +++ b/src/backend/bookshelfmodel/categoryitem.cpp @@ -20,6 +20,17 @@ CategoryItem::CategoryItem(CSwordModuleInfo *module) // Intentionally empty } +QVariant CategoryItem::data(int role) const { + switch (role) { + case Qt::DisplayRole: + return BtBookshelfModel::categoryName(m_category); + case Qt::DecorationRole: + return BtBookshelfModel::categoryIcon(m_category); + default: + return Item::data(role); + } +} + bool CategoryItem::operator<(const Item &other) const { if (other.type() != ITEM_CATEGORY) { return ITEM_CATEGORY < other.type(); diff --git a/src/backend/bookshelfmodel/categoryitem.h b/src/backend/bookshelfmodel/categoryitem.h index fcff12b..879895f 100644 --- a/src/backend/bookshelfmodel/categoryitem.h +++ b/src/backend/bookshelfmodel/categoryitem.h @@ -34,13 +34,7 @@ class CategoryItem: public Item { return m_category; } - inline QString name() const { - return BtBookshelfModel::categoryName(m_category); - } - - inline QIcon icon() const { - return BtBookshelfModel::categoryIcon(m_category); - } + QVariant data(int role = Qt::DisplayRole) const; 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 deleted file mode 100644 index fee9c19..0000000 --- a/src/backend/bookshelfmodel/distributionitem.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/********* -* -* 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/distributionitem.h" - - -namespace BookshelfModel { - -DistributionItem::DistributionItem(CSwordModuleInfo *module) - : Item(ITEM_DISTRIBUTION) { - m_distribution = module->config(CSwordModuleInfo::DistributionSource); -} - -} // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/indexingitem.cpp b/src/backend/bookshelfmodel/indexingitem.cpp new file mode 100644 index 0000000..898096f --- /dev/null +++ b/src/backend/bookshelfmodel/indexingitem.cpp @@ -0,0 +1,37 @@ +/********* +* +* 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 "indexingitem.h" + + +namespace BookshelfModel { + +IndexingItem::IndexingItem(CSwordModuleInfo *module) + : Item(Item::ITEM_INDEXING), m_indexed(module->hasIndex()) { + // Intentionally empty +} + +QVariant IndexingItem::data(int role) const { + switch (role) { + case Qt::DisplayRole: + if (m_indexed) { + return QObject::tr("Indexed works"); + } + else { + return QObject::tr("Unindexed works"); + } + default: + return Item::data(role); + } +} + +} // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/distributionitem.h b/src/backend/bookshelfmodel/indexingitem.h index 4ae1197..f30fb2d 100644 --- a/src/backend/bookshelfmodel/distributionitem.h +++ b/src/backend/bookshelfmodel/indexingitem.h @@ -10,8 +10,8 @@ * **********/ -#ifndef DISTRIBUTIONITEM_H -#define DISTRIBUTIONITEM_H +#ifndef INDEXINGITEM_H +#define INDEXINGITEM_H #include "backend/bookshelfmodel/item.h" @@ -20,29 +20,22 @@ namespace BookshelfModel { -class DistributionItem: public Item { +class IndexingItem: public Item { public: - static const Item::Type GROUP_TYPE = Item::ITEM_DISTRIBUTION; + static const Item::Type GROUP_TYPE = Item::ITEM_INDEXING; - DistributionItem(CSwordModuleInfo *module); + IndexingItem(CSwordModuleInfo *module); - inline QString distribution() const { - return m_distribution; - } - - inline QString name() const { - return m_distribution; - } + QVariant data(int role = Qt::DisplayRole) const; inline bool fitFor(CSwordModuleInfo *module) const { - return module->config(CSwordModuleInfo::DistributionSource) - == m_distribution; + return module->hasIndex() == m_indexed; } protected: - QString m_distribution; + bool m_indexed; }; } // namespace BookshelfModel -#endif // DISTRIBUTIONITEM_H +#endif // INDEXINGITEM_H diff --git a/src/backend/bookshelfmodel/item.cpp b/src/backend/bookshelfmodel/item.cpp index ec2dcab..809021b 100644 --- a/src/backend/bookshelfmodel/item.cpp +++ b/src/backend/bookshelfmodel/item.cpp @@ -12,9 +12,7 @@ #include "backend/bookshelfmodel/item.h" -#include "backend/bookshelfmodel/categoryitem.h" -#include "backend/bookshelfmodel/distributionitem.h" -#include "backend/bookshelfmodel/languageitem.h" +#include "backend/bookshelfmodel/btbookshelfmodel.h" namespace BookshelfModel { @@ -47,19 +45,29 @@ int Item::indexFor(Item *newItem) { } } -bool Item::operator<(const Item &other) const { - if (m_type != other.type()) { - return m_type < other.type(); +QVariant Item::data(int role) const { + switch (role) { + case Qt::CheckStateRole: + return m_checkState; + case BtBookshelfModel::ModuleHiddenRole: + if (m_children.empty()) return true; + + foreach (Item *child, m_children) { + if (!child->data(role).toBool()) return false; + } + return true; + default: + return QVariant(); } - 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; +bool Item::operator<(const Item &other) const { + if (m_type != other.type()) { + return m_type < other.type(); } - return true; + QString first(data(Qt::DisplayRole).toString().toLower()); + QString second(other.data(Qt::DisplayRole).toString().toLower()); + return first.localeAwareCompare(second) < 0; } } // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/item.h b/src/backend/bookshelfmodel/item.h index 665343f..f10da04 100644 --- a/src/backend/bookshelfmodel/item.h +++ b/src/backend/bookshelfmodel/item.h @@ -17,6 +17,7 @@ #include <QList> #include <QString> #include <QtGlobal> +#include <QVariant> class CSwordModuleInfo; @@ -30,7 +31,7 @@ class Item { ITEM_CATEGORY = 1, ITEM_LANGUAGE = 2, ITEM_MODULE = 3, - ITEM_DISTRIBUTION = 4 + ITEM_INDEXING = 4 }; Item(Type type); @@ -54,21 +55,11 @@ class Item { /** \brief Returns the list of child items of this node. */ - inline const QList<Item*> &children() const { + inline QList<Item*> &children() { return m_children; } /** - \brief Returns a pointer to the child item at the given index. - \pre The given index is valid - \param[in] index Index of child item to return. - */ - Item *childAt(int index) const { - Q_ASSERT(index >= 0 && index < m_children.size()); - return m_children.at(index); - } - - /** \brief Returns the index of this item under its parent. \retval -1 if this item has no parent. */ @@ -97,18 +88,13 @@ class Item { newItem->setParent(this); } - inline void deleteChildAt(int index) { - Q_ASSERT(index >= 0 && index <= m_children.size()); - delete m_children.takeAt(index); - } - template <class T> - T *getGroupItem(CSwordModuleInfo *module, int *index) { + T *getGroupItem(CSwordModuleInfo *module, int &outIndex) { for (int i(0); i < m_children.size(); i++) { Q_ASSERT(m_children.at(i)->type() == T::GROUP_TYPE); T *item(static_cast<T*>(m_children.at(i))); if (item->fitFor(module)) { - if (index != 0) *index = i; + outIndex = i; return item; } } @@ -116,23 +102,14 @@ class Item { } /** - \brief Returns the visible name of the item. + \brief Returns data for this item. */ - inline virtual QString name() const { - return QString::null; - } - - /** - \brief Returns the visible icon of the item. - */ - inline virtual QIcon icon() const { - return QIcon(); - } + virtual QVariant data(int role = Qt::DisplayRole) const; /** \brief Returns the check state of this item. */ - inline const Qt::CheckState checkState() const { + inline Qt::CheckState checkState() const { return m_checkState; } @@ -148,7 +125,7 @@ class Item { \brief Returns whether this item is fit to contain the given module. \param[in] module The module to check with. \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. + \retval false This item is not a group or is a wrong group. */ inline virtual bool fitFor(CSwordModuleInfo *module) const { Q_UNUSED(module); @@ -160,8 +137,6 @@ 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 8d37891..547c953 100644 --- a/src/backend/bookshelfmodel/languageitem.cpp +++ b/src/backend/bookshelfmodel/languageitem.cpp @@ -20,4 +20,15 @@ LanguageItem::LanguageItem(CSwordModuleInfo *module) // Intentionally empty } +QVariant LanguageItem::data(int role) const { + switch (role) { + case Qt::DisplayRole: + return BtBookshelfModel::languageName(m_language); + case Qt::DecorationRole: + return util::directory::getIcon("flag.svg"); + default: + return Item::data(role); + } +} + } // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/languageitem.h b/src/backend/bookshelfmodel/languageitem.h index b5696d9..c6e4417 100644 --- a/src/backend/bookshelfmodel/languageitem.h +++ b/src/backend/bookshelfmodel/languageitem.h @@ -28,17 +28,7 @@ class LanguageItem: public Item { LanguageItem(CSwordModuleInfo *module); - inline const CLanguageMgr::Language *language() const { - return m_language; - } - - inline QString name() const { - return BtBookshelfModel::languageName(m_language); - } - - inline QIcon icon() const { - return util::directory::getIcon("flag.svg"); - } + QVariant data(int role = Qt::DisplayRole) const; 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 95e6f62..e7aff92 100644 --- a/src/backend/bookshelfmodel/moduleitem.cpp +++ b/src/backend/bookshelfmodel/moduleitem.cpp @@ -12,14 +12,22 @@ #include "backend/bookshelfmodel/moduleitem.h" +#include "backend/bookshelfmodel/btbookshelftreemodel.h" #include "util/cresmgr.h" namespace BookshelfModel { -ModuleItem::ModuleItem(CSwordModuleInfo *module) - : Item(ITEM_MODULE), m_moduleInfo(module) { +ModuleItem::ModuleItem(CSwordModuleInfo *module, + BtBookshelfTreeModel *parentModel) + : Item(ITEM_MODULE), m_moduleInfo(module), m_parentModel(parentModel) { Q_ASSERT(module != 0); + Q_ASSERT(parentModel != 0); +} + +QVariant ModuleItem::data(int role) const { + // Dispatch request to tree model: + return m_parentModel->data(m_moduleInfo, role); } } // namespace BookshelfModel diff --git a/src/backend/bookshelfmodel/moduleitem.h b/src/backend/bookshelfmodel/moduleitem.h index 9657423..006ae97 100644 --- a/src/backend/bookshelfmodel/moduleitem.h +++ b/src/backend/bookshelfmodel/moduleitem.h @@ -19,22 +19,27 @@ #include "backend/drivers/cswordmoduleinfo.h" +class BtBookshelfTreeModel; + namespace BookshelfModel { class ModuleItem: public Item { public: - ModuleItem(CSwordModuleInfo *module); + ModuleItem(CSwordModuleInfo *module, BtBookshelfTreeModel *parentModel); - CSwordModuleInfo *moduleInfo() const { - return m_moduleInfo; - } + /** + Reimplementation of \ref Item::data which dispatches all requests to + the \ref BtBookshelfTreeModel parent model. + */ + QVariant data(int role = Qt::DisplayRole) const; - inline bool isHidden() const { - return m_moduleInfo->isHidden(); + inline CSwordModuleInfo *moduleInfo() const { + return m_moduleInfo; } protected: - CSwordModuleInfo *m_moduleInfo; + CSwordModuleInfo *m_moduleInfo; + BtBookshelfTreeModel *m_parentModel; }; } // namespace BookshelfModel diff --git a/src/backend/config/cbtconfig.cpp b/src/backend/config/cbtconfig.cpp index 98a2967..39c3e0c 100644 --- a/src/backend/config/cbtconfig.cpp +++ b/src/backend/config/cbtconfig.cpp @@ -89,6 +89,8 @@ QString getKey(const bools ID) { return "autoTileVertical"; case autoTileHorizontal: return "autoTileHorizontal"; + case autoTile: + return "autoTile"; case autoCascade: return "autoCascade"; @@ -110,6 +112,15 @@ QString getKey(const bools ID) { return "bookshelfShowHidden"; case allowNetworkConnection: return "allowNetworkConnection"; + + case showTextWindowHeaders: + return "showTextWindowHeaders"; + case showTextWindowNavigator: + return "showTextWindowNavigator"; + case showTextWindowModuleSelectorButtons: + return "showTextWindowModuleSelectorButtons"; + case showTextWindowToolButtons: + return "showTextWindowToolButtons"; } Q_ASSERT(false); return false; @@ -305,6 +316,8 @@ bool getDefault(const bools ID) { return true; case autoTileHorizontal: return false; + case autoTile: + return false; case autoCascade: return false; @@ -325,6 +338,15 @@ bool getDefault(const bools ID) { return false; case allowNetworkConnection: return false; + + case showTextWindowHeaders: + return true; + case showTextWindowNavigator: + return true; + case showTextWindowModuleSelectorButtons: + return true; + case showTextWindowToolButtons: + return true; } return false; } diff --git a/src/backend/config/cbtconfig.h b/src/backend/config/cbtconfig.h index d4d075b..9f3a850 100644 --- a/src/backend/config/cbtconfig.h +++ b/src/backend/config/cbtconfig.h @@ -55,6 +55,7 @@ enum bools { autoTileVertical, autoTileHorizontal, + autoTile, autoCascade, lineBreaks, @@ -67,7 +68,12 @@ enum bools { bookshelfShowHidden, - allowNetworkConnection + allowNetworkConnection, + + showTextWindowHeaders, + showTextWindowNavigator, + showTextWindowToolButtons, + showTextWindowModuleSelectorButtons }; enum ints { footnotes, diff --git a/src/backend/drivers/cswordlexiconmoduleinfo.cpp b/src/backend/drivers/cswordlexiconmoduleinfo.cpp index 776be9c..c4a04de 100644 --- a/src/backend/drivers/cswordlexiconmoduleinfo.cpp +++ b/src/backend/drivers/cswordlexiconmoduleinfo.cpp @@ -13,6 +13,8 @@ #include <QFile> #include <QDataStream> #include <QTextCodec> +#include <QDebug> + #include "util/directory.h" // Sword includes: @@ -20,7 +22,7 @@ //Change it once the format changed to make all systems rebuild their caches -#define CACHE_FORMAT "2" +#define CACHE_FORMAT "3" CSwordLexiconModuleInfo::CSwordLexiconModuleInfo( sword::SWModule* module, CSwordBackend* const backend ) : CSwordModuleInfo(module, backend) { m_entryList = 0; @@ -49,111 +51,103 @@ QStringList* CSwordLexiconModuleInfo::entries() { return 0; } - sword::SWModule* my_module = module(); - bool is_unicode = isUnicode(); + if (m_entryList) return m_entryList; - if (!m_entryList) { - m_entryList = new QStringList(); - bool read = false; + m_entryList = new QStringList(); + + //Check for buggy modules! They will not be loaded any more. + if ( name() == QString("ZhEnglish")) { + qWarning() << "Module ZhEnglish is buggy and will not be loaded."; + return m_entryList; + } + if ( name() == QString("EReo_en")) { + qWarning() << "Module EReo_en is buggy and will not be loaded."; + return m_entryList; + } - //Check for buggy modules! They will not be loaded any more. + QString dir(DU::getUserCacheDir().absolutePath()); + QFile f1( QString(dir).append("/").append(name())); + + /* + * Try the module's cache + */ + if ( f1.open( QIODevice::ReadOnly ) ) { + QDataStream s( &f1 ); + QString ModuleVersion, CacheVersion, QDataStreamVersion; + s >> ModuleVersion; + s >> CacheVersion; + s >> QDataStreamVersion; + + qDebug() << "Lexicon cache metadata" + << "Name" << name() + << "ModuleVersion" << ModuleVersion + << "CacheVersion" << CacheVersion + << "QDataStreamVersion" << QDataStreamVersion; + + // Check if cache is valid + if (ModuleVersion == config(CSwordModuleInfo::ModuleVersion) + && CacheVersion == CACHE_FORMAT + && QDataStreamVersion == QString::number(s.version())) { + s >> *m_entryList; - if ( name() == QString("ZhEnglish")) { - qWarning("Module ZhEnglish is buggy and will not be loaded."); + f1.close(); + qDebug() << "Read" << m_entryList->count() << "entries from lexicon cache for module" << name(); return m_entryList; } - if ( name() == QString("EReo_en")) { - qWarning("Module EReo_en is buggy and will not be loaded."); - return m_entryList; + f1.close(); + } + + /* + * Ok, no cache or invalid. + */ + qDebug() << "Read all entries of lexicon" << name(); + + sword::SWModule* my_module = module(); + my_module->setSkipConsecutiveLinks(true); + (*my_module) = sword::TOP; + snap(); //snap to top entry + + do { + if ( isUnicode() ) { + m_entryList->append(QString::fromUtf8(my_module->KeyText())); + } + else { + //for latin1 modules use fromLatin1 because of speed + QTextCodec* codec = QTextCodec::codecForName("Windows-1252"); + m_entryList->append(codec->toUnicode(my_module->KeyText())); } - QString dir(DU::getUserCacheDir().absolutePath()); - QFile f1( - QString(dir) - .append("/") - .append(name()) - ); - - if ( f1.open( QIODevice::ReadOnly ) ) { - QDataStream s( &f1 ); - QString mod_ver, prog_ver; - s >> mod_ver; - s >> prog_ver; - - if ((mod_ver == config(ModuleVersion)) && (prog_ver == CACHE_FORMAT)) { - s >> *m_entryList; - read = true; - } + (*my_module)++; + } + while ( !my_module->Error() ); - f1.close(); - // qWarning("read entries %d",m_entryList->count()); + (*my_module) = sword::TOP; //back to the first entry + + my_module->setSkipConsecutiveLinks(false); + + if (m_entryList->count()) { + m_entryList->first().simplified(); + + if (m_entryList->first().trimmed().isEmpty()) { + m_entryList->erase( m_entryList->begin() ); } + } - // Q_ASSERT(read); - // Q_ASSERT(m_entryList->count()); - if (!read || !m_entryList->count()) { - my_module->setSkipConsecutiveLinks(true); - (*my_module) = sword::TOP; - snap(); //snap to top entry - - // qWarning("Reading in module" ); - int i = 0; - - do { - if ( is_unicode ) { - m_entryList->append(QString::fromUtf8(my_module->KeyText())); - // qWarning("Entry: %s", my_module->KeyText() ); - } - else { //for latin1 modules use fromLatin1 because of speed - // m_entryList->append(QString::fromLatin1(my_module->KeyText())); - QTextCodec* codec = QTextCodec::codecForName("Windows-1252"); - m_entryList->append(codec->toUnicode(my_module->KeyText())); - } - - (*my_module)++; - i++; - } - while ( !my_module->Error() ); - - // qWarning("Reading finished. Module has %d entries.", i ); - - (*my_module) = sword::TOP; //back to the first entry - - my_module->setSkipConsecutiveLinks(false); - - if (m_entryList->count()) { - m_entryList->first().simplified(); - - if (m_entryList->first().trimmed().isEmpty()) { - m_entryList->erase( m_entryList->begin() ); - } - - //now sort the list, this is necesssary because Sword doesn't do Unicode ordering - // qWarning("sorting"); - // QStringList::iterator start(m_entryList->begin()); - // QStringList::iterator end(m_entryList->end()); - // std::sort( start, end, myLocaleAwareCompare() ); //stl sort - // m_entryList->sort(); //make sure the module is sorted by utf-8 - } - - qWarning("Writing cache file."); - - if (m_entryList->count()) { - //create cache - QString dir(DU::getUserCacheDir().absolutePath()); - //QFile f2( QString::fromLatin1("%1/%2").arg(dir).arg( name() ) ); - QFile f2( QString(dir).append("/").append(name()) ); - - - if (f2.open( QIODevice::WriteOnly )) { - QDataStream s( &f2 ); - s << config(CSwordModuleInfo::ModuleVersion); //store module version - s << QString(CACHE_FORMAT); //store BT version -- format may change - s << *m_entryList; - f2.close(); - } - } + qDebug() << "Writing cache file for lexicon module" << name(); + + if (m_entryList->count()) { + //create cache + QString dir(DU::getUserCacheDir().absolutePath()); + QFile f2( QString(dir).append("/").append(name()) ); + + if (f2.open( QIODevice::WriteOnly )) { + QDataStream s( &f2 ); + s << config(CSwordModuleInfo::ModuleVersion) //store module version + << QString(CACHE_FORMAT) //store BT version -- format may change + << QString::number(s.version()) //store QDataStream version -- format may change + << *m_entryList; + f2.close(); } } diff --git a/src/backend/drivers/cswordmoduleinfo.cpp b/src/backend/drivers/cswordmoduleinfo.cpp index bafe098..6096af2 100644 --- a/src/backend/drivers/cswordmoduleinfo.cpp +++ b/src/backend/drivers/cswordmoduleinfo.cpp @@ -109,13 +109,7 @@ bool CSwordModuleInfo::isLocked() { //still works, but the cipherkey is stored in CBTConfig. //Works because it is set in sword on program startup. - if (isEncrypted()) { - if (unlockKeyIsValid()) { - return false; - } - return true; - } - return false; + return isEncrypted() && !unlockKeyIsValid(); } /** This functions returns true if this module is encrypted (locked or unlocked). */ @@ -129,11 +123,7 @@ bool CSwordModuleInfo::isEncrypted() const { sword::ConfigEntMap config = backend()->getConfig()->Sections.find(name().toUtf8().constData())->second; sword::ConfigEntMap::iterator it = config.find("CipherKey"); - if (it != config.end()) { - return true; - } - - return false; + return it != config.end(); } /** This function makes an estimate if a module was properly unlocked. @@ -194,12 +184,13 @@ bool CSwordModuleInfo::hasIndex() { //first check if the index version and module version are ok QSettings module_config(getModuleBaseIndexLocation() + QString("/bibletime-index.conf"), QSettings::IniFormat); - if (hasVersion()) { - if (module_config.value("module-version") != QString(config(CSwordModuleInfo::ModuleVersion)) ) { - return false; - } + if (hasVersion() && + module_config.value("module-version").toString() != config(CSwordModuleInfo::ModuleVersion)) + { + return false; } - if (module_config.value("index-version") != QString::number( INDEX_VERSION )) { + + if (module_config.value("index-version").toUInt() != INDEX_VERSION) { qDebug("%s: INDEX_VERSION is not compatible with this version of BibleTime.", name().toUtf8().constData()); return false; } @@ -397,24 +388,30 @@ void CSwordModuleInfo::buildIndex() { writer->close(); if (m_cancelIndexing) { - deleteIndexForModule(name()); + deleteIndex(); m_cancelIndexing = false; } else { QSettings module_config(getModuleBaseIndexLocation() + QString("/bibletime-index.conf"), QSettings::IniFormat); if (hasVersion()) module_config.setValue("module-version", config(CSwordModuleInfo::ModuleVersion) ); - module_config.setValue("index-version", INDEX_VERSION ); + module_config.setValue("index-version", INDEX_VERSION); + emit hasIndexChanged(true); } } catch (...) { qWarning("CLucene exception occurred while indexing"); util::showWarning(0, QCoreApplication::tr("Indexing aborted"), QCoreApplication::tr("An internal error occurred while building the index.")); - deleteIndexForModule(name()); + deleteIndex(); m_cancelIndexing = false; } } -void CSwordModuleInfo::deleteIndexForModule( QString name ) { +void CSwordModuleInfo::deleteIndex() { + deleteIndexForModule(name()); + emit hasIndexChanged(false); +} + +void CSwordModuleInfo::deleteIndexForModule(const QString &name) { util::directory::removeRecursive( getGlobalBaseIndexLocation() + "/" + name ); } @@ -927,7 +924,8 @@ bool CSwordModuleInfo::setHidden(bool hide) { if (hide) { Q_ASSERT(!hiddenModules.contains(name())); hiddenModules.append(name()); - } else { + } + else { Q_ASSERT(hiddenModules.contains(name())); hiddenModules.removeOne(name()); } diff --git a/src/backend/drivers/cswordmoduleinfo.h b/src/backend/drivers/cswordmoduleinfo.h index 9f32b12..a767c41 100644 --- a/src/backend/drivers/cswordmoduleinfo.h +++ b/src/backend/drivers/cswordmoduleinfo.h @@ -144,10 +144,17 @@ class CSwordModuleInfo: public QObject { * Returns the base directory for search indices */ static QString getGlobalBaseIndexLocation(); + /** - * Removes search index for this module, even if the module is not there any more + Removes the search index for this module (rm -rf). */ - static void deleteIndexForModule( QString name ); + void deleteIndex(); + + /** + Removes search index for a module, even if the module is not there any more. + \param[in] name name of the module. + */ + static void deleteIndexForModule(const QString &name); /** @@ -289,7 +296,9 @@ class CSwordModuleInfo: public QObject { /** * Returns true if this module is hidden (not to be shown with other modules in certain views). */ - inline bool isHidden() const { return m_hidden; } + inline bool isHidden() const { + return m_hidden; + } /** Shows or hides the module. @@ -336,6 +345,7 @@ class CSwordModuleInfo: public QObject { QString getFormattedConfigEntry(const QString& name) const; signals: + void hasIndexChanged(bool); void hiddenChanged(bool); void indexingFinished(); void indexingProgress(int); diff --git a/src/backend/filters/bt_teihtml.cpp b/src/backend/filters/bt_teihtml.cpp index 340e8af..b242f46 100644 --- a/src/backend/filters/bt_teihtml.cpp +++ b/src/backend/filters/bt_teihtml.cpp @@ -24,7 +24,7 @@ Filters::BT_TEIHTML::BT_TEIHTML() : sword::TEIHTMLHREF() { - setPassThruUnknownEscapeString(true); //the HTML widget will render the HTML escape codes + setPassThruUnknownEscapeString(true); //the HTML widget will render the HTML escape codes } bool Filters::BT_TEIHTML::handleToken(sword::SWBuf &buf, const char *token, sword::BasicFilterUserData *userData) { @@ -32,59 +32,59 @@ bool Filters::BT_TEIHTML::handleToken(sword::SWBuf &buf, const char *token, swor if (!substituteToken(buf, token)) { - sword::XMLTag tag(token); - - if (0) { - - } - else if (!strcmp(tag.getName(), "ref")) { - - if (!tag.isEndTag() && !tag.isEmpty()) { - - renderReference(tag.getAttribute("osisRef"), buf, userData); - - } - else if (tag.isEndTag()) { - buf.append("</a>"); - } - else { // empty reference marker - // -- what should we do? nothing for now. - } - } - // <hi> highlighted text - else if (!strcmp(tag.getName(), "hi")) { - const sword::SWBuf type = tag.getAttribute("rend"); - - if ((!tag.isEndTag()) && (!tag.isEmpty())) { - if (type == "bold") { - buf.append("<span class=\"bold\">"); - } - else if (type == "illuminated") { - buf.append("<span class=\"illuminated\">"); - } - else if (type == "italic") { - buf.append("<span class=\"italic\">"); - } - else if (type == "line-through") { - buf.append("<span class=\"line-through\">"); - } - else if (type == "normal") { - buf.append("<span class=\"normal\">"); - } - else if (type == "small-caps") { - buf.append("<span class=\"small-caps\">"); - } - else if (type == "underline") { - buf.append("<span class=\"underline\">"); - } - else { - buf.append("<span>"); //don't break markup, </span> is inserted later - } - } - else if (tag.isEndTag()) { //all hi replacements are html spans - buf.append("</span>"); - } - } + sword::XMLTag tag(token); + + if (0) { + + } + else if (!strcmp(tag.getName(), "ref")) { + + if (!tag.isEndTag() && !tag.isEmpty()) { + + renderReference(tag.getAttribute("osisRef"), buf, userData); + + } + else if (tag.isEndTag()) { + buf.append("</a>"); + } + else { // empty reference marker + // -- what should we do? nothing for now. + } + } + // <hi> highlighted text + else if (!strcmp(tag.getName(), "hi")) { + const sword::SWBuf type = tag.getAttribute("rend"); + + if ((!tag.isEndTag()) && (!tag.isEmpty())) { + if (type == "bold") { + buf.append("<span class=\"bold\">"); + } + else if (type == "illuminated") { + buf.append("<span class=\"illuminated\">"); + } + else if (type == "italic") { + buf.append("<span class=\"italic\">"); + } + else if (type == "line-through") { + buf.append("<span class=\"line-through\">"); + } + else if (type == "normal") { + buf.append("<span class=\"normal\">"); + } + else if (type == "small-caps") { + buf.append("<span class=\"small-caps\">"); + } + else if (type == "underline") { + buf.append("<span class=\"underline\">"); + } + else { + buf.append("<span>"); //don't break markup, </span> is inserted later + } + } + else if (tag.isEndTag()) { //all hi replacements are html spans + buf.append("</span>"); + } + } else { //all tokens handled by OSISHTMLHref will run through the filter now return sword::TEIHTMLHREF::handleToken(buf, token, userData); } diff --git a/src/backend/keys/cswordversekey.cpp b/src/backend/keys/cswordversekey.cpp index 84c0b29..a7e16c5 100644 --- a/src/backend/keys/cswordversekey.cpp +++ b/src/backend/keys/cswordversekey.cpp @@ -32,7 +32,7 @@ CSwordVerseKey::CSwordVerseKey( CSwordModuleInfo* const module ) : } CSwordVerseKey::CSwordVerseKey( const CSwordVerseKey& k ) : CSwordKey(k), VerseKey(k) { - this->VerseKey::setAutoNormalize(true); + this->VerseKey::setAutoNormalize(true); } CSwordVerseKey::CSwordVerseKey( const VerseKey* const k, CSwordModuleInfo* const module ) : CSwordKey(module), VerseKey(*k) {} @@ -163,7 +163,7 @@ bool CSwordVerseKey::next( const JumpType type ) { m_module->module()->setSkipConsecutiveLinks(true); //disable headings for next verse - const bool useHeaders = (Verse() == 0); + const bool useHeaders = 1; //(Verse() == 0); const bool oldHeadingsStatus = ((VerseKey*)(m_module->module()->getKey()))->Headings( useHeaders ); //don't use setKey(), that would create a new key without Headings set m_module->module()->getKey()->setText( key().toUtf8().constData() ); @@ -243,7 +243,7 @@ bool CSwordVerseKey::previous( const JumpType type ) { case UseVerse: { if (m_module && m_module->module()) { - const bool useHeaders = (Verse() == 0); + const bool useHeaders = 1; //(Verse() == 0); const bool oldHeadingsStatus = ((VerseKey*)(m_module->module()->getKey()))->Headings( useHeaders ); m_module->module()->getKey()->setText( key().toUtf8().constData() ); diff --git a/src/backend/managers/cswordbackend.cpp b/src/backend/managers/cswordbackend.cpp index ee74e4a..4596a61 100644 --- a/src/backend/managers/cswordbackend.cpp +++ b/src/backend/managers/cswordbackend.cpp @@ -47,8 +47,7 @@ using namespace Rendering; CSwordBackend::CSwordBackend() : sword::SWMgr(0, 0, false, new sword::EncodingFilterMgr( sword::ENC_UTF8 ), true), - m_dataModel(this) -{ + m_dataModel(this) { m_filters.gbf = new BT_GBFHTML(); m_filters.plain = new BT_PLAINHTML(); m_filters.thml = new BT_ThMLHTML(); @@ -126,6 +125,18 @@ QList<CSwordModuleInfo*> CSwordBackend::takeModulesFromList(QStringList names) { return list; } +QList<CSwordModuleInfo*> CSwordBackend::getPointerList(QStringList names) { + QList<CSwordModuleInfo*> list; + foreach(QString name, names) { + CSwordModuleInfo* mInfo = findModuleByName(name); + if (mInfo) { + list.append(mInfo); + } + } + return list; +} + + /** Initializes the Sword modules. */ CSwordBackend::LoadError CSwordBackend::initModules(SetupChangedReason reason) { // qWarning("globalSwordConfigPath is %s", globalConfPath); @@ -513,29 +524,26 @@ void CSwordBackend::reloadModules(SetupChangedReason reason) { } // Get one or more shared sword config (sword.conf) files -QStringList CSwordBackend::getSharedSwordConfigFiles() const -{ - QStringList configPath; +QStringList CSwordBackend::getSharedSwordConfigFiles() const { + QStringList configPath; #ifdef Q_WS_WIN - // %ALLUSERSPROFILE%\Sword\sword.conf - QString tmp = util::directory::getSharedSwordDir().filePath("sword.conf"); - QString globalPath = util::directory::convertDirSeparators(QString(getenv("SWORD_PATH"))); - configPath << globalPath.append("/Sword/sword.conf"); + // %ALLUSERSPROFILE%\Sword\sword.conf + QString tmp = util::directory::getSharedSwordDir().filePath("sword.conf"); + QString globalPath = util::directory::convertDirSeparators(QString(getenv("SWORD_PATH"))); + configPath << globalPath.append("/Sword/sword.conf"); #else - // /etc/sword.conf, /usr/local/etc/sword.conf + // /etc/sword.conf, /usr/local/etc/sword.conf configPath = QString(globalConfPath).split(":"); #endif - return configPath; + return configPath; } // Get the private sword directory -QString CSwordBackend::getPrivateSwordConfigPath() const -{ +QString CSwordBackend::getPrivateSwordConfigPath() const { return util::directory::getUserHomeSwordDir().absolutePath(); } -QString CSwordBackend::getPrivateSwordConfigFile() const -{ +QString CSwordBackend::getPrivateSwordConfigFile() const { QString file(getPrivateSwordConfigPath() + "/sword.conf"); return util::directory::convertDirSeparators(file); } @@ -553,7 +561,8 @@ QStringList CSwordBackend::swordDirList() const { if (QFile(getPrivateSwordConfigFile()).exists()) { // Use the private sword.conf file: configs << getPrivateSwordConfigFile(); - } else { + } + else { /* Did not find private sword.conf, will use shared sword.conf files to build the private one. Once the private sword.conf exist, the shared diff --git a/src/backend/managers/cswordbackend.h b/src/backend/managers/cswordbackend.h index 3120694..c8b4f77 100644 --- a/src/backend/managers/cswordbackend.h +++ b/src/backend/managers/cswordbackend.h @@ -211,6 +211,11 @@ class CSwordBackend : public QObject, public sword::SWMgr { */ QList<CSwordModuleInfo*> takeModulesFromList(QStringList names); + /** + * Returns a list of pointers to modules, created from a list of module names. + */ + QList<CSwordModuleInfo*> getPointerList(QStringList names); + /** Sword prefix list. * @return A list of all known Sword prefix dirs */ @@ -254,6 +259,9 @@ class CSwordBackend : public QObject, public sword::SWMgr { QMap<QString, QString> m_moduleDescriptionMap; }; +Q_DECLARE_METATYPE(CSwordBackend::FilterOptions) +Q_DECLARE_METATYPE(CSwordBackend::DisplayOptions) + /**Returns The list of modules managed by this backend*/ inline const QList<CSwordModuleInfo*> &CSwordBackend::moduleList() const { return m_dataModel.modules(); diff --git a/src/backend/managers/referencemanager.h b/src/backend/managers/referencemanager.h index a038130..fdef8b2 100644 --- a/src/backend/managers/referencemanager.h +++ b/src/backend/managers/referencemanager.h @@ -19,15 +19,15 @@ */ namespace ReferenceManager { enum Type { - Bible, /**< Bibles */ - Commentary, /**< Commentary */ - Lexicon, /**< Lexicon */ - GenericBook, /**< Generic Book */ - MorphHebrew, /**< Module for hebrew morphology*/ - MorphGreek, /**< Module for greek morphology */ - StrongsHebrew, /**< Module for hebrew strongs */ - StrongsGreek, /**< Module for greek strongs */ - Unknown /**< Unknown */ + Bible, /**< Bibles */ + Commentary, /**< Commentary */ + Lexicon, /**< Lexicon */ + GenericBook, /**< Generic Book */ + MorphHebrew, /**< Module for hebrew morphology*/ + MorphGreek, /**< Module for greek morphology */ + StrongsHebrew, /**< Module for hebrew strongs */ + StrongsGreek, /**< Module for greek strongs */ + Unknown /**< Unknown */ }; /** Turn a hyperlink into module, key and type. @@ -82,14 +82,14 @@ ReferenceManager::Type typeFromModule( const CSwordModuleInfo::ModuleType type ) struct ParseOptions { - QString refDestinationModule; - QString refBase; /* only valid for verse based destination modules*/ - QString sourceLanguage; /* only valid for verse based destination modules*/ - QString destinationLanguage; /* only valid for verse based destination modules*/ + QString refDestinationModule; + QString refBase; /* only valid for verse based destination modules*/ + QString sourceLanguage; /* only valid for verse based destination modules*/ + QString destinationLanguage; /* only valid for verse based destination modules*/ - ParseOptions() { - destinationLanguage = "en"; - }; + ParseOptions() { + destinationLanguage = "en"; + }; }; /** Parses the given verse references using the given language and the module. diff --git a/src/backend/rendering/cbookdisplay.cpp b/src/backend/rendering/cbookdisplay.cpp index f640628..9da57f2 100644 --- a/src/backend/rendering/cbookdisplay.cpp +++ b/src/backend/rendering/cbookdisplay.cpp @@ -95,7 +95,7 @@ const QString Rendering::CBookDisplay::text( const QList<CSwordModuleInfo*>& mod const QString renderedText = render.renderKeyTree(tree); key->setOffset( offset ); - qDeleteAll(tree); // Dispose of the heap allocated objects pointed to in tree. + qDeleteAll(tree); // Dispose of the heap allocated objects pointed to in tree. return renderedText; }; }; diff --git a/src/backend/rendering/centrydisplay.cpp b/src/backend/rendering/centrydisplay.cpp index d3a6aac..b6c7a27 100644 --- a/src/backend/rendering/centrydisplay.cpp +++ b/src/backend/rendering/centrydisplay.cpp @@ -58,12 +58,12 @@ const QString CEntryDisplay::text( const QList<CSwordModuleInfo*>& modules, cons } k1.Verse(0); if ( k1.rawText().length() > 0 ) { - tree.append( new Rendering::CTextRendering::KeyTreeItem(k1.key(), modules, preverse_settings) ); + tree.append( new Rendering::CTextRendering::KeyTreeItem(k1.key(), modules, preverse_settings) ); } } } - tree.append( new Rendering::CTextRendering::KeyTreeItem(keyName, modules, normal_settings) ); + tree.append( new Rendering::CTextRendering::KeyTreeItem(keyName, modules, normal_settings) ); QString result(render.renderKeyTree(tree)); qDeleteAll(tree); - return result; + return result; } diff --git a/src/backend/rendering/chtmlexportrendering.cpp b/src/backend/rendering/chtmlexportrendering.cpp index e6d0ff6..6a571c6 100644 --- a/src/backend/rendering/chtmlexportrendering.cpp +++ b/src/backend/rendering/chtmlexportrendering.cpp @@ -11,6 +11,8 @@ #include <boost/scoped_ptr.hpp> #include <iostream> +#include <QDebug> + #include "backend/drivers/cswordmoduleinfo.h" #include "backend/keys/cswordkey.h" #include "backend/keys/cswordversekey.h" @@ -132,7 +134,10 @@ const QString CHTMLExportRendering::renderEntry( const KeyTreeItem& i, CSwordKey key_renderedText = key->renderedText(); if (m_filterOptions.headings) { - (*mod_Itr)->module()->RenderText(); + + // only process EntryAttributes, do not render, this might destroy the EntryAttributes again + (*mod_Itr)->module()->RenderText(0, -1, 0); + sword::AttributeValue::const_iterator it = (*mod_Itr)->module()->getEntryAttributes()["Heading"]["Preverse"].begin(); const sword::AttributeValue::const_iterator end = |