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-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
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
39namespace {
40auto 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:
56 m_treeModel = new BtBookshelfTreeModel(btConfig(), groupingOrderKey, this);
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);
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,
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
215
#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)
static CSwordBackend & instance() noexcept
QList< CSwordModuleInfo * > const & moduleList() const
QString const & name() const