BibleTime
btbookshelfwidget.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 "btbookshelfwidget.h"
14 
15 #include <QAction>
16 #include <QApplication>
17 #include <QHBoxLayout>
18 #include <QEvent>
19 #include <QKeyEvent>
20 #include <QLabel>
21 #include <QLineEdit>
22 #include <QMenu>
23 #include <QModelIndex>
24 #include <QToolButton>
25 #include <QVariant>
26 #include <QVBoxLayout>
27 #include <utility>
28 #include "../backend/bookshelfmodel/btbookshelffiltermodel.h"
29 #include "../backend/bookshelfmodel/btbookshelftreemodel.h"
30 #include "../backend/config/btconfig.h"
31 #include "../util/btassert.h"
32 #include "../util/btconnect.h"
33 #include "../util/cresmgr.h"
35 #include "btbookshelfview.h"
36 
37 
38 class CSwordModuleInfo;
39 class QPoint;
40 
41 BtBookshelfWidget::BtBookshelfWidget(QWidget *parent, Qt::WindowFlags flags)
42  : QWidget(parent, flags)
43  , m_treeModel(nullptr)
44  , m_leftCornerWidget(nullptr)
45  , m_rightCornerWidget(nullptr)
46 {
47  // Setup post-filter:
49 
50  // Init widgets and such:
51  initActions();
52  initMenus();
53  initWidgets();
54 
55  // Connect treeview to model:
56  m_treeView->setModel(m_postFilterModel);
57 
58  retranslateUi();
59 
60  BT_CONNECT(m_nameFilterEdit, &QLineEdit::textEdited,
64  [this](QPoint const & pos){ m_contextMenu->popup(pos); });
66  [this](CSwordModuleInfo * const module, QPoint const & pos) {
67  if (!m_itemContextMenu)
69  m_itemContextMenu->setProperty(
70  "BtModule",
71  QVariant::fromValue(
72  static_cast<void *>(module)));
73  m_itemContextMenu->popup(pos);
74  });
75 }
76 
77 void
78 BtBookshelfWidget::setSourceModel(std::shared_ptr<QAbstractItemModel> model) {
79  BT_ASSERT(model);
80  if (m_treeModel) {
81  m_sourceModel = model;
82  m_treeModel->setSourceModel(std::move(model));
83  } else {
84  m_sourceModel = std::move(model);
85  }
86 }
87 
89  BT_ASSERT(model);
91  m_treeModel = model;
92  if (m_sourceModel != nullptr) {
94  }
95  m_postFilterModel->setSourceModel(model);
96 }
97 
99  delete m_leftCornerWidget;
100  w->setParent(this);
101  m_toolBar->insertWidget(0, w, 0);
102 }
103 
105  delete m_rightCornerWidget;
106  w->setParent(this);
107  m_toolBar->insertWidget(m_toolBar->count(), w, 0);
108 }
109 
111  m_showHideAction = new QAction(this);
112  m_showHideAction->setIcon(CResMgr::mainIndex::showHide::icon());
113  m_showHideAction->setCheckable(true);
114  BT_CONNECT(m_showHideAction, &QAction::toggled,
116 }
117 
119  // Grouping menu:
123  [this](BtBookshelfTreeModel::Grouping const & grouping) {
124  m_treeModel->setGroupingOrder(grouping);
125  m_treeView->setRootIsDecorated(!grouping.isEmpty());
126  });
127 
128  // Context menu
129  m_contextMenu = new QMenu(this);
130  m_contextMenu->addMenu(m_groupingMenu);
131  m_contextMenu->addAction(m_showHideAction);
132 
133  // Item context menu
135 }
136 
138  QVBoxLayout *layout(new QVBoxLayout);
139  layout->setContentsMargins(0, 8, 0, 0);
140  m_toolBar = new QHBoxLayout;
141  // Add a small margin between the edge of the window and the label (looks better)
142  m_toolBar->setContentsMargins(3, 0, 0, 0);
143  m_nameFilterLabel = new QLabel(this);
144  m_toolBar->addWidget(m_nameFilterLabel);
145 
146  m_nameFilterEdit = new QLineEdit(this);
147  m_nameFilterEdit->installEventFilter(this);
149  m_toolBar->addWidget(m_nameFilterEdit);
150 
151  m_groupingButton = new QToolButton(this);
152  m_groupingButton->setPopupMode(QToolButton::InstantPopup);
154  m_groupingButton->setIcon(m_groupingMenu->icon());
155  m_groupingButton->setAutoRaise(true);
156  m_toolBar->addWidget(m_groupingButton);
157 
158  m_showHideButton = new QToolButton(this);
159  m_showHideButton->setDefaultAction(m_showHideAction);
160  m_showHideButton->setAutoRaise(true);
161  m_toolBar->addWidget(m_showHideButton);
162  layout->addLayout(m_toolBar);
163 
164  m_treeView = new BtBookshelfView(this);
165  layout->addWidget(m_treeView);
166  setLayout(layout);
167 }
168 
170  m_nameFilterLabel->setText(tr("Fi&lter:"));
171  m_groupingButton->setText(tr("Grouping"));
172  m_groupingButton->setToolTip(tr("Change the grouping of items in the bookshelf."));
173  m_groupingMenu->setTitle(tr("Grouping"));
174  m_showHideAction->setText(tr("Show/hide works"));
175 }
176 
177 bool BtBookshelfWidget::eventFilter(QObject *object, QEvent *event) {
178  BT_ASSERT(object == m_nameFilterEdit);
179  if (event->type() == QEvent::KeyPress) {
180  QKeyEvent *e = static_cast<QKeyEvent*>(event);
181  switch (e->key()) {
182  case Qt::Key_Up:
183  case Qt::Key_Down:
184  case Qt::Key_Enter:
185  case Qt::Key_Return:
186  QApplication::sendEvent(m_treeView, event);
187  return true;
188  default:
189  break;
190  }
191  }
192  return false;
193 }
194 
196  const QModelIndex& index,
197  QString prefix,
198  QStringList * expandedPaths) {
199  QString path = index.data(Qt::DisplayRole).toString();
200  if (m_treeView->isExpanded(index)) {
201  if (! prefix.isEmpty())
202  path = QStringLiteral("%1/%2").arg(prefix, path);
203  expandedPaths->append(path);
204  }
205  int rows = m_postFilterModel->rowCount(index);
206  for (int row = 0; row < rows; ++row) {
207  auto childIndex = m_postFilterModel->index(row, 0, index);
208  findExpanded(childIndex, path, expandedPaths);
209  }
210 }
211 
212 void BtBookshelfWidget::restoreExpanded(const QModelIndex& index, const QStringList& nodeList) {
213  if (nodeList.isEmpty())
214  return;
215  QString firstNode = nodeList.first();
216  QStringList remainingNodes = nodeList;
217  remainingNodes.removeFirst();
218  int rows = m_postFilterModel->rowCount(index);
219  for (int row = 0; row < rows; ++row) {
220  auto childIndex = m_postFilterModel->index(row, 0, index);
221  QString text = childIndex.data(Qt::DisplayRole).toString();
222  if (firstNode == text) {
223  m_treeView->expand(childIndex);
224  restoreExpanded(childIndex, remainingNodes);
225  break;
226  }
227  }
228 }
229 
231  auto const paths =
232  btConfig().value<QStringList>(
233  QStringLiteral("GUI/MainWindow/Docks/Bookshelf/expandPaths"));
234  auto rootIndex = m_treeView->rootIndex();
235  for (auto const & path : paths) {
236  QStringList nodeList = path.split('/');
237  restoreExpanded(rootIndex, nodeList);
238  }
239 }
240 
242  QStringList paths;
243  QString prefix;
244  auto rootIndex = m_treeView->rootIndex();
245  findExpanded(rootIndex, prefix, &paths);
246  btConfig().setValue(
247  QStringLiteral("GUI/MainWindow/Docks/Bookshelf/expandPaths"),
248  paths);
249 }
250 
#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
void setNameFilterFixedString(QString const &nameFilter)
void signalGroupingOrderChanged(const BtBookshelfTreeModel::Grouping &)
void setGroupingOrder(const BtBookshelfTreeModel::Grouping &groupingOrder, bool emitSignal=true)
void setSourceModel(std::shared_ptr< QAbstractItemModel > sourceModel)
void contextMenuActivated(QPoint pos)
void moduleContextMenuActivated(CSwordModuleInfo *item, QPoint pos)
BtBookshelfWidget(QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags())
QToolButton * m_showHideButton
void restoreExpanded(const QModelIndex &index, const QStringList &nodeList)
void setRightCornerWidget(QWidget *w)
QHBoxLayout * m_toolBar
QLineEdit * m_nameFilterEdit
QWidget * m_rightCornerWidget
bool eventFilter(QObject *object, QEvent *event) override
void setTreeModel(BtBookshelfTreeModel *model)
void setSourceModel(std::shared_ptr< QAbstractItemModel > model)
void findExpanded(const QModelIndex &index, QString prefix, QStringList *expandedPaths)
std::shared_ptr< QAbstractItemModel > m_sourceModel
BtBookshelfTreeModel * m_treeModel
void setLeftCornerWidget(QWidget *w)
BtBookshelfFilterModel * m_postFilterModel
BtBookshelfGroupingMenu * m_groupingMenu
QWidget * m_leftCornerWidget
BtBookshelfView * m_treeView
QToolButton * m_groupingButton
T value(QString const &key, T const &defaultValue=T()) const
Returns the settings value for the given global key.
Definition: btconfigcore.h:50
void setValue(QString const &key, T const &value)
Sets a value for a key.
Definition: btconfigcore.h:73