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-2021 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 
32 namespace {
33 
34 struct 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 
68  bool filterAcceptsRowNoHiddenCheck(int sourceRow,
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,
104  CSwordModuleInfo::ModuleType moduleType_,
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 
127 void 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
Definition: btmodulelist.h:20
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
void triggered(QModelIndex index)
void rebuildMenu()
Rebuilds the menu.
Definition: btmenuview.cpp:180
virtual QAction * newAction(QMenu *parentMenu, const QModelIndex &itemIndex)
Definition: btmenuview.cpp:93
void setModel(QAbstractItemModel *model)
Definition: btmenuview.cpp:50
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)
BtModuleList m_newModulesToUse
void setSelectedModule(CSwordModuleInfo *const newSelectedModule) noexcept
static CSwordBackend & instance() noexcept
Definition: cswordbackend.h:98
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