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 <utility>
22#include "../../backend/bookshelfmodel/btbookshelfmodel.h"
23#include "../../backend/bookshelfmodel/btbookshelftreemodel.h"
24#include "../../backend/config/btconfig.h"
25#include "../../backend/drivers/cswordmoduleinfo.h"
26#include "../../backend/managers/cswordbackend.h"
27#include "../../util/btassert.h"
28#include "../../util/btconnect.h"
29#include "../btmenuview.h"
30
31
32namespace {
33
34struct SortModel final: public QSortFilterProxyModel {
35
36// Methods:
37
39 QObject * parent = nullptr)
40 : QSortFilterProxyModel(parent)
41 , m_moduleType(moduleType)
42 , m_showHidden(btConfig().value<bool>(
43 QStringLiteral("GUI/bookshelfShowHidden"),
44 false))
45 , m_sourceModel(new BtBookshelfTreeModel(this))
46 {
47 m_sourceModel->setSourceModel(CSwordBackend::instance().model());
48 setSourceModel(m_sourceModel);
49 }
50
51 bool filterAcceptsRow(int sourceRow,
52 QModelIndex const & sourceParentIndex)
53 const final override
54 {
55 auto const & model = *sourceModel();
56 auto const itemIndex = model.index(sourceRow, 0, sourceParentIndex);
57
58 // Do recursive hidden check, if configured:
59 if (!m_showHidden
60 && model.data(itemIndex,
62 return false;
63
64 // Do other recursive checks:
65 return filterAcceptsRowNoHiddenCheck(sourceRow, sourceParentIndex);
66 }
67
69 QModelIndex const & sourceParentIndex)
70 const
71 {
72 auto const & model =
73 *static_cast<BtBookshelfTreeModel *>(sourceModel());
74 auto const itemIndex = model.index(sourceRow, 0, sourceParentIndex);
75
76 // Accept subtrees if it has any accepted children:
77 if (auto const numRows = model.rowCount(itemIndex)) {
78 for (int i = 0; i < numRows; ++i)
79 if (filterAcceptsRowNoHiddenCheck(i, itemIndex))
80 return true;
81 return false;
82 }
83
84 auto const * const module = model.module(itemIndex);
85 BT_ASSERT(module);
86 return (module->type() == m_moduleType)
87 || ((m_moduleType == CSwordModuleInfo::Bible)
88 && (module->type() == CSwordModuleInfo::Commentary));
89 }
90
91// Fields:
92
94 bool const m_showHidden;
96
97};
98
99} // anonymous namespace
100
101
103 QString const & title,
105 Flags flags,
106 QWidget * parent)
107 : BtMenuView(title, parent)
108 , m_moduleType(moduleType_)
109 , m_sortedModel(new SortModel(moduleType_, this))
110 , m_flags(flags)
111{
112 setModel(static_cast<SortModel *>(m_sortedModel));
114 [this](QModelIndex const itemIndex) {
115 if (itemIndex.isValid()) {
116 auto const & sortedModel =
117 *static_cast<SortModel *>(m_sortedModel);
118 Q_EMIT sigModuleChosen(
119 sortedModel.m_sourceModel->module(
120 sortedModel.mapToSource(itemIndex)));
121 } else {
122 Q_EMIT sigModuleChosen(nullptr);
123 }
124 });
125}
126
127void BtModuleChooserMenu::preBuildMenu(QActionGroup * actionGroup) {
128 BT_ASSERT(actionGroup);
129 actionGroup->setExclusive(true);
130
131 if (m_flags & AddNoneButton) {
132 QAction * noneAction = new QAction(this);
133 noneAction->setCheckable(true);
134 noneAction->setText(tr("NONE"));
135 noneAction->setChecked(!m_selectedModule);
136 noneAction->setDisabled(
137 m_newModulesToUse.size() <= 1
138 || (m_buttonIndex <= 0 && m_leftLikeModules <= 1));
139 noneAction->setActionGroup(actionGroup);
140 BT_CONNECT(noneAction, &QAction::triggered,
141 [this]{ Q_EMIT triggered(QModelIndex()); });
142 addAction(noneAction);
143
144 addSeparator();
145 }
146}
147
149 QModelIndex const & itemIndex)
150{
151 auto * const action = BtMenuView::newAction(parentMenu, itemIndex);
152
153 auto const & sortedModel = *static_cast<SortModel *>(m_sortedModel);
154
155 auto const sourceItemIndex = sortedModel.mapToSource(itemIndex);
156 auto * const module =
157 sortedModel.m_sourceModel->module(sourceItemIndex);
158 BT_ASSERT(module);
159 action->setCheckable(true);
160 action->setChecked(module == m_selectedModule);
161
163 action->setDisabled(module == m_selectedModule
164 || m_newModulesToUse.contains(module)
165 || module->isLocked());
166 } else {
167 action->setDisabled((module != m_selectedModule
168 && m_newModulesToUse.contains(module))
169 || module->isLocked());
170 }
171
172 // Disable non-Bible modules on first button:
174 && m_buttonIndex <= 0
175 && sortedModel.m_moduleType == CSwordModuleInfo::Bible
176 && module->category() != CSwordModuleInfo::Bibles)
177 action->setDisabled(true);
178
179 return action;
180}
181
183 CSwordModuleInfo * newSelectedModule,
184 int newButtonIndexIndex,
185 int newLeftLikeModules)
186{
187 m_newModulesToUse = newModulesToUse;
188 m_selectedModule = newSelectedModule;
189 m_buttonIndex = newButtonIndexIndex;
190 m_leftLikeModules = newLeftLikeModules;
191 rebuildMenu();
192}
193
195 CSwordModuleInfo * const newSelectedModule) noexcept
196{
197 m_selectedModule = newSelectedModule;
198 rebuildMenu();
199}
#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
static CSwordBackend & instance() noexcept
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