BibleTime
btbookshelfdockwidget.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 "btbookshelfdockwidget.h"
14 
15 #include <memory>
16 #include <QAction>
17 #include <QLabel>
18 #include <QMenu>
19 #include <QPushButton>
20 #include <QStackedWidget>
21 #include <QVariant>
22 #include <QVBoxLayout>
23 #include <QWidget>
24 #include <utility>
25 #include "../backend/bookshelfmodel/btbookshelfmodel.h"
26 #include "../backend/bookshelfmodel/btbookshelftreemodel.h"
27 #include "../backend/config/btconfig.h"
28 #include "../backend/drivers/cswordmoduleinfo.h"
29 #include "../backend/managers/cswordbackend.h"
30 #include "../util/btassert.h"
31 #include "../util/btconnect.h"
32 #include "../util/cresmgr.h"
33 #include "bibletime.h"
34 #include "btbookshelfview.h"
35 #include "btbookshelfwidget.h"
36 #include "messagedialog.h"
37 
38 
39 namespace {
40 auto const groupingOrderKey =
41  QStringLiteral("GUI/MainWindow/Docks/Bookshelf/grouping");
42 }
43 
45 
47  : QDockWidget(parent, f)
48 {
50  m_instance = this;
51 
52  // Setup actions and menus:
53  initMenus();
54 
55  // Setup tree model:
57 
58  // Get backend model:
59  auto bookshelfModelPtr(CSwordBackend::instance().model());
60 
61  // Setup bookshelf widgets:
64  m_bookshelfWidget->setSourceModel(bookshelfModelPtr);
66  m_bookshelfWidget->treeView()->setMouseTracking(true); // required for moduleHovered
67  /// \bug The correct grouping action is not selected on startup.
68 
69  // Setup welcome widgets:
70  m_welcomeWidget = new QWidget(this);
71  QVBoxLayout *welcomeLayout = new QVBoxLayout;
72  m_installLabel = new QLabel(this);
73  m_installLabel->setWordWrap(true);
74  m_installLabel->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
75  welcomeLayout->addWidget(m_installLabel, 0, Qt::AlignHCenter | Qt::AlignBottom);
76  m_installButton = new QPushButton(this);
77  welcomeLayout->addWidget(m_installButton, 0, Qt::AlignHCenter | Qt::AlignTop);
78  m_welcomeWidget->setLayout(welcomeLayout);
79 
80  // Setup stacked widget:
81  m_stackedWidget = new QStackedWidget(this);
83  m_stackedWidget->addWidget(m_welcomeWidget);
84  m_stackedWidget->setCurrentWidget(bookshelfModelPtr->moduleList().empty()
87  setWidget(m_stackedWidget);
88 
89  // Connect signals:
91  [this](CSwordModuleInfo * module) {
92  if (!module->isLocked()) {
93  Q_EMIT moduleOpenTriggered(module);
94  } else {
95  /**
96  \todo Implement a better unlock dialog, which could
97  incorporate the following warning message.
98  Actually the whole case when the user tries to
99  open a locked module needs to be rethought and
100  refactored.
101  */
102  message::showWarning(
103  this,
104  tr("Warning: Module locked!"),
105  tr("You are trying to access an encrypted "
106  "module. Please provide an unlock key in "
107  "the following dialog to open the "
108  "module."));
109 
110  /** \todo We need to keep the module name because
111  unlocking currently reloads sword. */
112  auto const moduleName(module->name());
113  if (BibleTime::moduleUnlock(module)) {
114  // Re-initialize module pointer:
115  auto const & backend = CSwordBackend::instance();
116  module = backend.findModuleByName(moduleName);
117  BT_ASSERT(module);
118  Q_EMIT moduleOpenTriggered(module);
119  }
120  }
121  });
122  BT_CONNECT(m_bookshelfWidget->treeView(), &BtBookshelfView::moduleHovered,
125  [](CSwordModuleInfo * const module, bool const checked)
126  { module->setHidden(!checked); });
128  [this](BtBookshelfTreeModel::Grouping const & g) {
130  Q_EMIT groupingOrderChanged(g);
131  });
132  BT_CONNECT(m_bookshelfWidget->showHideAction(), &QAction::toggled,
133  m_treeModel, &BtBookshelfTreeModel::setCheckable);
134  auto modulesChangedSlot =
135  [this]{
136  auto const & moduleList =
138  m_stackedWidget->setCurrentWidget(moduleList.empty()
139  ? m_welcomeWidget
140  : m_bookshelfWidget);
141  };
142  BT_CONNECT(bookshelfModelPtr.get(), &BtBookshelfModel::rowsInserted,
143  this/*needed*/, modulesChangedSlot);
144  BT_CONNECT(bookshelfModelPtr.get(), &BtBookshelfModel::rowsRemoved,
145  this/*needed*/, std::move(modulesChangedSlot));
146  BT_CONNECT(m_installButton, &QPushButton::clicked,
148 
149  retranslateUi();
150 }
151 
153  namespace RM = CResMgr::mainIndex;
154 
155  m_itemContextMenu = new QMenu(this);
156  auto const addMenuAction =
157  [this](void (BtBookshelfDockWidget::* signal)(CSwordModuleInfo *)) {
158  auto * const action = new QAction(this);
159  BT_CONNECT(action, &QAction::triggered,
160  [this, signal] {
161  if (CSwordModuleInfo * const module =
162  static_cast<CSwordModuleInfo *>(
163  m_itemContextMenu->property("BtModule")
164  .value<void *>()))
165  Q_EMIT (this->*signal)(module);
166  });
167  m_itemContextMenu->addAction(action);
168  return action;
169  };
170 
173 
176  m_itemSearchAction->setIcon(RM::search::icon());
177 
180  m_itemUnlockAction->setIcon(RM::unlockModule::icon());
181 
184  m_itemAboutAction->setIcon(RM::aboutModule::icon());
185 
186  BT_CONNECT(m_itemContextMenu, &QMenu::aboutToShow,
187  [this]{
188  void * v =
189  m_itemContextMenu->property("BtModule")
190  .value<void*>();
191  CSwordModuleInfo *module = static_cast<CSwordModuleInfo*>(v);
192  m_itemOpenAction->setEnabled(!module->isLocked());
193  m_itemSearchAction->setText(
194  tr("&Search in %1...").arg(module->name()));
195  m_itemSearchAction->setEnabled(!module->isLocked());
196  m_itemUnlockAction->setEnabled(module->isLocked());
197  });
198 }
199 
201  setWindowTitle(tr("Bookshelf"));
202 
203  m_itemOpenAction->setText(tr("&Open"));
204  m_itemUnlockAction->setText(tr("&Unlock..."));
205  m_itemAboutAction->setText(tr("&About..."));
206 
207  m_installLabel->setText(tr("There are currently no works installed. Please "
208  "click the button below to install new works."));
209  m_installButton->setText(tr("&Install works..."));
210 }
211 
214 }
215 
218 }
#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 moduleUnlockTriggered(CSwordModuleInfo *module)
static BtBookshelfDockWidget * m_instance
void moduleHovered(CSwordModuleInfo *module)
BtBookshelfDockWidget(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
BtBookshelfWidget * m_bookshelfWidget
void moduleOpenTriggered(CSwordModuleInfo *module)
QStackedWidget * m_stackedWidget
BtBookshelfTreeModel * m_treeModel
void moduleAboutTriggered(CSwordModuleInfo *module)
void moduleSearchTriggered(CSwordModuleInfo *module)
void saveTo(BtConfigCore &config, QString const &key) const
void groupingOrderChanged(BtBookshelfTreeModel::Grouping newGrouping)
void setCheckable(bool checkable)
void moduleChecked(CSwordModuleInfo *module, bool checked)
void moduleHovered(CSwordModuleInfo *item)
void moduleActivated(CSwordModuleInfo *item)
BtBookshelfView * treeView() const
void setTreeModel(BtBookshelfTreeModel *model)
void setSourceModel(std::shared_ptr< QAbstractItemModel > model)
void setItemContextMenu(QMenu *newMenu)
QList< CSwordModuleInfo * > const & moduleList() const
static CSwordBackend & instance() noexcept
Definition: cswordbackend.h:98
QString const & name() const
bool setHidden(bool hide)