BibleTime
btmodulechoosermenu.cpp
Go to the documentation of this file.
1/*********
2*
3* In the name of the Father, and of the Son, and of the Holy Spirit.
4*
5* This file is part of BibleTime's source code, https://bibletime.info/
6*
7* Copyright 1999-2025 by the BibleTime developers.
8* The BibleTime source code is licensed under the GNU General Public License
9* version 2.0.
10*
11**********/
12
13#include "btmodulechoosermenu.h"
14
15#include <QAbstractItemModel>
16#include <QAction>
17#include <QActionGroup>
18#include <QModelIndex>
19#include <QSortFilterProxyModel>
20#include <QVariant>
21#include "../../backend/bookshelfmodel/btbookshelfmodel.h"
22#include "../../backend/bookshelfmodel/btbookshelftreemodel.h"
23#include "../../backend/config/btconfig.h"
24#include "../../backend/drivers/cswordmoduleinfo.h"
25#include "../../backend/managers/cswordbackend.h"
26#include "../../util/btassert.h"
27#include "../../util/btconnect.h"
28#include "../btmenuview.h"
29
30
31namespace {
32
33struct SortModel final: public QSortFilterProxyModel {
34
35// Methods:
36
38 QObject * parent = nullptr)
39 : QSortFilterProxyModel(parent)
40 , m_moduleType(moduleType)
41 , m_showHidden(btConfig().value<bool>(
42 QStringLiteral("GUI/bookshelfShowHidden"),
43 false))
44 , m_sourceModel(new BtBookshelfTreeModel(this))
45 {
46 m_sourceModel->setSourceModel(CSwordBackend::instance().model());
47 setSourceModel(m_sourceModel);
48 }
49
50 bool filterAcceptsRow(int sourceRow,
51 QModelIndex const & sourceParentIndex)
52 const final override
53 {
54 auto const & model = *sourceModel();
55 auto const itemIndex = model.index(sourceRow, 0, sourceParentIndex);
56
57 // Do recursive hidden check, if configured:
58 if (!m_showHidden
59 && model.data(itemIndex,
61 return false;
62
63 // Do other recursive checks:
64 return filterAcceptsRowNoHiddenCheck(sourceRow, sourceParentIndex);
65 }
66
68 QModelIndex const & sourceParentIndex)
69 const
70 {
71 auto const & model =
72 *static_cast<BtBookshelfTreeModel *>(sourceModel());
73 auto const itemIndex = model.index(sourceRow, 0, sourceParentIndex);
74
75 // Accept subtrees if it has any accepted children:
76 if (auto const numRows = model.rowCount(itemIndex)) {
77 for (int i = 0; i < numRows; ++i)
78 if (filterAcceptsRowNoHiddenCheck(i, itemIndex))
79 return true;
80 return false;
81 }
82
83 auto const * const module = model.module(itemIndex);
84 BT_ASSERT(module);
85 return (module->type() == m_moduleType)
86 || ((m_moduleType == CSwordModuleInfo::Bible)
87 && (module->type() == CSwordModuleInfo::Commentary));
88 }
89
90// Fields:
91
93 bool const m_showHidden;
95
96};
97
98} // anonymous namespace
99
100
102 QString const & title,
104 Flags flags,
105 QWidget * parent)
106 : BtMenuView(title, parent)
107 , m_moduleType(moduleType_)
108 , m_sortedModel(new SortModel(moduleType_, this))
109 , m_flags(flags)
110{
111 setModel(static_cast<SortModel *>(m_sortedModel));
113 [this](QModelIndex const itemIndex) {
114 if (itemIndex.isValid()) {
115 auto const & sortedModel =
116 *static_cast<SortModel *>(m_sortedModel);
117 Q_EMIT sigModuleChosen(
118 sortedModel.m_sourceModel->module(
119 sortedModel.mapToSource(itemIndex)));
120 } else {
121 Q_EMIT sigModuleChosen(nullptr);
122 }
123 });
124}
125
126void BtModuleChooserMenu::preBuildMenu(QActionGroup * actionGroup) {
127 BT_ASSERT(actionGroup);
128 actionGroup->setExclusive(true);
129
130 if (m_flags & AddNoneButton) {
131 QAction * noneAction = new QAction(this);
132 noneAction->setCheckable(true);
133 noneAction->setText(tr("NONE"));
134 noneAction->setChecked(!m_selectedModule);
135 noneAction->setDisabled(
136 m_newModulesToUse.size() <= 1
137 || (m_buttonIndex <= 0 && m_leftLikeModules <= 1));
138 noneAction->setActionGroup(actionGroup);
139 BT_CONNECT(noneAction, &QAction::triggered,
140 [this]{ Q_EMIT triggered(QModelIndex()); });
141 addAction(noneAction);
142
143 addSeparator();
144 }
145}
146
148 QModelIndex const & itemIndex)
149{
150 auto * const action = BtMenuView::newAction(parentMenu, itemIndex);
151
152 auto const & sortedModel = *static_cast<SortModel *>(m_sortedModel);
153
154 auto const sourceItemIndex = sortedModel.mapToSource(itemIndex);
155 auto * const module =
156 sortedModel.m_sourceModel->module(sourceItemIndex);
157 BT_ASSERT(module);
158 action->setCheckable(true);
159 action->setChecked(module == m_selectedModule);
160
162 action->setDisabled(module == m_selectedModule
163 || m_newModulesToUse.contains(module)
164 || module->isLocked());
165 } else {
166 action->setDisabled((module != m_selectedModule
167 && m_newModulesToUse.contains(module))
168 || module->isLocked());
169 }
170
171 // Disable non-Bible modules on first button:
173 && m_buttonIndex <= 0
174 && sortedModel.m_moduleType == CSwordModuleInfo::Bible
175 && module->category() != CSwordModuleInfo::Category::Bibles)
176 action->setDisabled(true);
177
178 return action;
179}
180
182 CSwordModuleInfo * newSelectedModule,
183 int newButtonIndexIndex,
184 int newLeftLikeModules)
185{
186 m_newModulesToUse = newModulesToUse;
187 m_selectedModule = newSelectedModule;
188 m_buttonIndex = newButtonIndexIndex;
189 m_leftLikeModules = newLeftLikeModules;
190 rebuildMenu();
191}
192
198
200 CSwordModuleInfo * const newSelectedModule) noexcept
201{
202 m_selectedModule = newSelectedModule;
203 rebuildMenu();
204}
#define BT_ASSERT(...)
Definition btassert.h:17
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
Definition btconfig.h:305
#define BT_CONNECT(...)
Definition btconnect.h:20
QList< CSwordModuleInfo * > BtModuleList
QModelIndex index(int row, int column, QModelIndex const &parent=QModelIndex()) const override
void triggered(QModelIndex index)
void rebuildMenu()
Rebuilds the menu.
virtual QAction * newAction(QMenu *parentMenu, const QModelIndex &itemIndex)
void setModel(QAbstractItemModel *model)
QAction * newAction(QMenu *parentMenu, QModelIndex const &itemIndex) final override
void update(BtModuleList newModulesToUse, CSwordModuleInfo *newSelectedModule, int newButtonIndexIndex, int newLeftLikeModules)
void preBuildMenu(QActionGroup *actionGroup) final override
CSwordModuleInfo * m_selectedModule
BtModuleChooserMenu(QString const &title, CSwordModuleInfo::ModuleType moduleType, Flags flags, QWidget *parent=nullptr)
void setSelectedModule(CSwordModuleInfo *const newSelectedModule) noexcept
CSwordModuleInfo::ModuleType const m_moduleType
static CSwordBackend & instance() noexcept
static QIcon const & categoryIconAdd(CSwordModuleInfo::Category category)
static QIcon const & categoryIcon(CSwordModuleInfo::Category category)
CSwordModuleInfo::Category category() const
bool filterAcceptsRowNoHiddenCheck(int sourceRow, QModelIndex const &sourceParentIndex) const
SortModel(CSwordModuleInfo::ModuleType moduleType, QObject *parent=nullptr)
bool filterAcceptsRow(int sourceRow, QModelIndex const &sourceParentIndex) const final override