BibleTime
btbookshelfmodel.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 "btbookshelfmodel.h"
14 
15 #include <QIcon>
16 #include <QSet>
17 #include <QtAlgorithms>
18 #include <QtGlobal>
19 #include "../../util/btassert.h"
20 #include "../../util/btconnect.h"
21 #include "../../util/macros.h"
22 #include "../drivers/cswordmoduleinfo.h"
23 #include "../drivers/btconstmoduleset.h"
24 
25 
27 
28 std::shared_ptr<BtBookshelfModel> BtBookshelfModel::newInstance()
29 { return std::make_shared<BtBookshelfModel>(ConstructInPrivate()); }
30 
31 BtBookshelfModel::~BtBookshelfModel() noexcept = default;
32 
33 int BtBookshelfModel::rowCount(const QModelIndex & parent) const {
34  if (parent.isValid())
35  return 0;
36 
37  return m_data.size();
38 }
39 
40 QVariant BtBookshelfModel::data(CSwordModuleInfo * module, int role) const {
42  switch (role) {
43  case Qt::DisplayRole:
44  case ModuleNameRole:
45  return module->name();
46  case Qt::DecorationRole:
47  case ModuleIconRole:
49  case ModulePointerRole:
50  return QVariant::fromValue(static_cast<void *>(module));
51  case ModuleCategoryRole:
52  return QVariant::fromValue(module->category());
53  case ModuleLanguageRole:
54  return QVariant(); /// \todo Unimplemented
55  case ModuleHiddenRole:
56  return module->isHidden();
59  case ModuleHasIndexRole:
60  return module->hasIndex();
62  return module->indexSize();
65  case Qt::ToolTipRole:
66  return QStringLiteral("<b>%1:</b><br/>%2")
67  .arg(module->name())
69  default:
70  return QVariant();
71  }
72 }
73 
74 QVariant BtBookshelfModel::data(const QModelIndex &index, int role) const {
75  if (!index.isValid() || index.column() != 0 || index.parent().isValid())
76  return QVariant();
77 
78  int row = index.row();
79  if (row >= m_data.size())
80  return QVariant();
81 
82  return data(m_data.at(row), role);
83 }
84 
85 QVariant BtBookshelfModel::headerData(int section,
86  Qt::Orientation orientation,
87  int role) const
88 {
89  if (role == Qt::DisplayRole
90  && orientation == Qt::Horizontal
91  && section == 0)
92  {
93  return tr("Module");
94  }
95 
96  return QVariant();
97 }
98 
99 bool BtBookshelfModel::setData(const QModelIndex & index,
100  const QVariant & value,
101  int role)
102 {
103  int row = index.row();
104  if (role == ModuleHiddenRole
105  && row >= 0
106  && row < m_data.size()
107  && index.column() == 0)
108  {
109  /*
110  Emitting dataChanged here is actually mandatory, but were not doing it
111  directly. Since we're connected to the module, changing its hidden
112  state will emit a signal we catch in moduleHidden(), which in turn is
113  what will actually emit dataChanged().
114  */
115  return m_data.at(row)->setHidden(value.toBool());
116  }
117  return false;
118 }
119 
120 void BtBookshelfModel::clear(bool destroy) {
121  if (m_data.size() <= 0)
122  return;
123 
124  beginRemoveRows(QModelIndex(), 0, m_data.size() - 1);
125  if (destroy)
126  qDeleteAll(m_data);
127  m_data.clear();
128  endRemoveRows();
129 }
130 
132  BT_ASSERT(module);
133 
134  if (m_data.contains(module))
135  return;
136 
137  const int index(m_data.size());
138  beginInsertRows(QModelIndex(), index, index);
139  m_data.append(module);
146  endInsertRows();
147 }
148 
150  bool destroy) {
151  const int index = m_data.indexOf(module);
152  if (index == -1)
153  return;
154 
155  beginRemoveRows(QModelIndex(), index, index);
162  m_data.removeAt(index);
163  endRemoveRows();
164  if (destroy)
165  delete module;
166 }
167 
169  bool destroy)
170 {
171  QSet<CSwordModuleInfo *> moduleSet;
172  for (auto module: modules)
173  moduleSet.insert(module);
174  removeModules(moduleSet, destroy);
175 }
176 
177 void BtBookshelfModel::removeModules(BtConstModuleSet const & modules, bool destroy){
178  // This is inefficient, since signals are emitted for each removed module:
179  for (auto const * const module : modules)
180  removeModule(const_cast<CSwordModuleInfo *>(module), destroy);
181 }
182 
183 CSwordModuleInfo * BtBookshelfModel::getModule(const QString & name) const {
184  for (auto * const module : m_data)
185  if (UNLIKELY(module->name() == name))
186  return module;
187  return nullptr;
188 }
189 
191  BT_ASSERT(qobject_cast<CSwordModuleInfo *>(sender()));
192 
193  moduleDataChanged(static_cast<CSwordModuleInfo *>(sender()));
194 }
195 
197  BT_ASSERT(qobject_cast<CSwordModuleInfo *>(sender()));
198 
199  moduleDataChanged(static_cast<CSwordModuleInfo *>(sender()));
200 }
201 
203  BT_ASSERT(qobject_cast<CSwordModuleInfo *>(sender()));
204 
205  moduleDataChanged(static_cast<CSwordModuleInfo *>(sender()));
206 }
207 
209  BT_ASSERT(m_data.count(module) == 1);
210 
211  QModelIndex i(index(m_data.indexOf(module), 0));
212  Q_EMIT dataChanged(i, i);
213 }
#define BT_ASSERT(...)
Definition: btassert.h:17
#define BT_CONNECT(...)
Definition: btconnect.h:20
static std::shared_ptr< BtBookshelfModel > newInstance()
void removeModule(CSwordModuleInfo *const module, bool destroy=false)
void addModule(CSwordModuleInfo *const module)
void moduleIndexed(bool indexed)
CSwordModuleInfo * module(QModelIndex const &index) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=ModuleHiddenRole) override
~BtBookshelfModel() noexcept override
QList< CSwordModuleInfo * > m_data
QVariant data(CSwordModuleInfo *module, int role) const
void moduleHidden(bool hidden)
CSwordModuleInfo * getModule(const QString &name) const
void moduleUnlocked(bool unlocked)
void moduleDataChanged(CSwordModuleInfo *module)
BtBookshelfModel(BtBookshelfModel &&)=delete
void removeModules(BtConstModuleSet const &modules, bool destroy=false)
void clear(bool destroy=false)
bool isHidden() const
QString config(const CSwordModuleInfo::ConfigEntry entry) const
QIcon moduleIcon() const
void hasIndexChanged(bool hasIndex)
QString const & name() const
void hiddenChanged(bool hidden)
void unlockedChanged(bool unlocked)
::qint64 indexSize() const
CSwordModuleInfo::Category category() const
#define UNLIKELY(c)
Gives the compiler a hint that the given conditional is likely to evaluate to false.
Definition: macros.h:44
Used to restrict construction to newInstance() only.