BibleTime
btmodelviewreaddisplay.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 <QClipboard>
17#include <QDebug>
18#include <QDrag>
19#include <QFileDialog>
20#include <QGuiApplication>
21#include <QHBoxLayout>
22#include <QMenu>
23#include <QQuickItem>
24#include <QScrollBar>
25#include <QString>
26#ifdef BUILD_TEXT_TO_SPEECH
27#include <QTextToSpeech>
28#endif
29#include <QTimer>
30#include <QToolBar>
31#include <utility>
32#include "../../backend/keys/cswordkey.h"
33#include "../../backend/drivers/cswordbiblemoduleinfo.h"
34#include "../../backend/managers/cswordbackend.h"
35#include "../../backend/managers/referencemanager.h"
36#include "../../util/btassert.h"
37#include "../../util/btconnect.h"
38#include "../../util/tool.h"
39#include "../bibletime.h"
40#include "../btcopybyreferencesdialog.h"
41#include "../BtMimeData.h"
42#include "../cexportmanager.h"
43#include "../displaywindow/cdisplaywindow.h"
44#include "../keychooser/ckeychooser.h"
47
48
50 CDisplayWindow * const displayWindow,
51 QWidget * const parentWidget)
52 : QWidget(parentWidget)
53 , m_parentWindow(displayWindow)
54 , m_quickWidget(new BtQuickWidget(this))
55 , m_qmlInterface(m_quickWidget->qmlInterface())
56 , m_scrollBar(new QScrollBar(this))
57{
58 auto * const layout = new QHBoxLayout(this);
59 layout->setContentsMargins(0, 0, 0, 0);
60
61 m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
62 m_quickWidget->show();
64 [this](QString const & reference) { /// \todo Fix me
65 auto key(m_parentWindow->swordKey());
66 key->setKey(reference);
67 m_parentWindow->lookupKey(reference);
68 });
69 layout->addWidget(m_quickWidget);
70
71 m_scrollBar->setRange(-100,100);
72 m_scrollBar->setValue(0);
73 BT_CONNECT(m_scrollBar, &QScrollBar::sliderMoved,
75 BT_CONNECT(m_scrollBar, &QScrollBar::sliderPressed,
77 BT_CONNECT(m_scrollBar, &QScrollBar::sliderReleased,
79 layout->addWidget(m_scrollBar);
80
82 [this](QString const & reference) {
83 auto * const key = m_parentWindow->swordKey();
84 key->setKey(reference);
85 m_parentWindow->keyChooser()->updateKey(key);
87 });
89 [this](const QString& moduleName, const QString& keyName) {
90 auto & drag = *new QDrag(this);
91 auto mimedata =
92 std::make_unique<BTMimeData>(
93 BTMimeData::ItemList{{moduleName, keyName, {}}});
94 //add real Bible text from module/key
95 if (auto * const module =
96 CSwordBackend::instance().findModuleByName(moduleName))
97 {
98 drag.setPixmap(
99 module->moduleIcon().pixmap(
100 m_parentWindow->mainToolBar()->iconSize()));
101 std::unique_ptr<CSwordKey> key(module->createKey());
102 key->setKey(keyName);
103 // This works across applications:
104 mimedata->setText(key->strippedText());
105 }
106 drag.setMimeData(mimedata.release());
107 drag.exec(Qt::CopyAction, Qt::CopyAction);
108 });
114 [this](QString const & newLink) {
115 auto newAnchor = m_qmlInterface->getBibleUrlFromLink(newLink);
116 if (m_activeAnchor != newAnchor) {
117 m_activeAnchor = newAnchor;
118 activeAnchorChanged(std::move(newAnchor));
119 }
121 });
122
123 setLayout(layout);
124}
125
127
128void BtModelViewReadDisplay::setBibleReference(const QString& reference) {
130}
131
133 int speed = 25 * (1 + std::abs(value/30));
134 int relative = value - m_scrollBarPosition;
135 m_quickWidget->scroll(relative * speed);
136 m_scrollBarPosition = value;
138}
139
143
148
150{ QGuiApplication::clipboard()->setText(text(part)); }
151
152void BtModelViewReadDisplay::contextMenuEvent(QContextMenuEvent * event) {
153 if (m_popup)
154 m_popup->exec(event->globalPos());
155}
156
158{ QGuiApplication::clipboard()->setText(qmlInterface()->getSelectedText()); }
159
161 auto const & qml = *qmlInterface();
162 BtCopyByReferencesDialog dlg(qml.textModel(),
163 qml.selection(),
165 if (dlg.exec() != QDialog::Accepted)
166 return;
167
168 auto const & result = dlg.result();
169 BT_ASSERT(result.module);
170 auto const & module = *result.module;
171 if (module.type() == CSwordModuleInfo::Bible
172 || module.type() == CSwordModuleInfo::Commentary)
173 {
174 qml.copyVerseRange(static_cast<CSwordVerseKey const &>(*result.key1),
175 static_cast<CSwordVerseKey const &>(*result.key2));
176 } else {
177 qml.copyRange(result.index1, result.index2);
178 }
179}
180
182 auto const filename =
183 QFileDialog::getSaveFileName(
184 nullptr,
185 QObject::tr("Save document ..."),
186 "",
187 QObject::tr("Text files") + " (*.txt);;"
188 + QObject::tr("All files") + " (*)");
189 if (!filename.isEmpty())
190 util::tool::savePlainFile(filename, text(part));
191}
192
194 DisplayOptions const & displayOptions,
195 FilterOptions const & filterOptions)
196{
197 using CSBiMI = CSwordBibleModuleInfo;
198 CSwordKey* const key = m_parentWindow->swordKey();
199 const CSwordModuleInfo *module = key->module();
200
201 CExportManager mgr(false,
202 QString(),
205
206 switch (type) {
207 case Document: {
208 if (module->type() == CSwordModuleInfo::Bible) {
209 CSwordVerseKey* vk = dynamic_cast<CSwordVerseKey*>(key);
210
211 CSwordVerseKey startKey(*vk);
212 startKey.setVerse(1);
213
214 CSwordVerseKey stopKey(*vk);
215
216 const CSBiMI *bible = dynamic_cast<const CSBiMI*>(module);
217 if (bible) {
218 stopKey.setVerse(bible->verseCount(bible->bookNumber(startKey.bookName()), startKey.chapter()));
219 }
220
221 mgr.printKey(module, startKey.key(), stopKey.key(), displayOptions, filterOptions);
222 }
223 else if (module->type() == CSwordModuleInfo::Lexicon || module->type() == CSwordModuleInfo::Commentary ) {
224 mgr.printKey(module, key->key(), key->key(), displayOptions, filterOptions);
225 }
226 else if (module->type() == CSwordModuleInfo::GenericBook) {
227 CSwordTreeKey* tree = dynamic_cast<CSwordTreeKey*>(key);
228
229 CSwordTreeKey startKey(*tree);
230 // while (startKey.previousSibling()) { // go to first sibling on this level!
231 // }
232
233 CSwordTreeKey stopKey(*tree);
234 // if (CSwordBookModuleInfo* book = dynamic_cast<CSwordBookModuleInfo*>(module)) {
235 // while ( stopKey.nextSibling() ) { //go to last displayed sibling!
236 // }
237 // }
238 mgr.printKey(module, startKey.key(), stopKey.key(), displayOptions, filterOptions);
239 }
240 break;
241 }
242
243 case AnchorWithText: {
244 if (!m_activeAnchor.isEmpty())
245 mgr.printByHyperlink(m_activeAnchor, displayOptions, filterOptions);
246 break;
247 }
248
249 default:
250 break;
251 }
252}
253
254#ifdef BUILD_TEXT_TO_SPEECH
255void BtModelViewReadDisplay::speakSelectedText() {
256 if (auto const * const qml = qmlInterface(); qml && qml->selection())
257 BibleTime::instance()->speakText(qml->getSelectedText());
258}
259#endif
260
262 qmlInterface()->textModel()->reloadModules();
263}
264
265QString
267 QString text;
268 switch (part) {
269 case Document: {
270 CSwordKey* const key = m_parentWindow->swordKey();
271 const CSwordModuleInfo *module = key->module();
272 //This is never used for Bibles, so it is not implemented for
273 //them. If it should be, see CReadDisplay::print() for example
274 //code.
275 BT_ASSERT(module->type() == CSwordModuleInfo::Lexicon ||
276 module->type() == CSwordModuleInfo::Commentary ||
277 module->type() == CSwordModuleInfo::GenericBook);
278 FilterOptions filterOptions;
280
281 text = QStringLiteral("%1\n(%2, %3)")
282 .arg(key->strippedText(), key->key(), key->module()->name());
283 break;
284 }
285
286 case AnchorOnly: {
287 if (auto const decodedLink =
289 return decodedLink->key;
290 return {};
291 }
292
293 case AnchorTextOnly: {
294 auto const decodedLink(
296 if (decodedLink && decodedLink->module) {
297 std::unique_ptr<CSwordKey> key(decodedLink->module->createKey());
298 key->setKey(decodedLink->key);
299 return key->strippedText();
300 }
301 return {};
302 }
303
304 case AnchorWithText: {
305 auto const decodedLink(
307 if (decodedLink && decodedLink->module) {
308 std::unique_ptr<CSwordKey> key(decodedLink->module->createKey());
309 key->setKey(decodedLink->key);
310
311 FilterOptions filterOptions;
313
314 return QStringLiteral("%1\n(%2, %3)")
315 .arg(key->strippedText(), key->key(), key->module()->name());
316 }
317 return {};
318 }
319 default:
320 break;
321 }
322 return QString();
323
324}
325
327
329 FilterOptions const & filterOptions)
330{ m_qmlInterface->textModel()->setOptions(displayOptions, filterOptions); }
331
332void BtModelViewReadDisplay::setModules(const QStringList &modules) {
333 m_qmlInterface->setModules(modules);
334}
335
339
341
345
349
351
353
354void BtModelViewReadDisplay::highlightText(const QString& text, bool caseSensitive) {
355 m_qmlInterface->setHighlightWords(text, caseSensitive);
356}
357
358void BtModelViewReadDisplay::findText(bool const backward)
359{ m_qmlInterface->findText(backward); }
360
361// Save the Lemma (Strongs number) attribute
362void BtModelViewReadDisplay::setNodeInfo(QString const & newNodeInfo) {
363 if (m_nodeInfo != newNodeInfo) {
364 m_nodeInfo = newNodeInfo;
365 Q_EMIT nodeInfoChanged(newNodeInfo);
366 }
367}
#define BT_ASSERT(...)
Definition btassert.h:17
#define BT_CONNECT(...)
Definition btconnect.h:20
QList< BookmarkItem > ItemList
Definition BtMimeData.h:38
void colorThemeChanged()
static BibleTime * instance() noexcept
Definition bibletime.h:225
void autoScrollStop()
Result const & result() const noexcept
void findText(bool const backward)
void highlightText(const QString &text, bool caseSensitive)
void copySelectedText()
Copies the currently selected text.
void setModules(QStringList const &modules)
void setNodeInfo(QString const &newNodeInfo)
QString text(TextPart const part=Document)
void activeAnchorChanged(QString newActiveAnchor)
void copyAsPlainText(TextPart const part)
void copyByReferences()
Copies the given text specified by asking user for first and last references.
void save(TextPart const part)
Saves the given text with the specified format into the applications clipboard.
void setOptions(DisplayOptions const &displayOptions, FilterOptions const &filterOptions)
BtQmlInterface * qmlInterface() const noexcept
BtQuickWidget *const m_quickWidget
BtQmlInterface *const m_qmlInterface
void nodeInfoChanged(QString newNodeInfo)
BtModelViewReadDisplay(CDisplayWindow *displayWindow, QWidget *parent=nullptr)
void print(TextPart const, DisplayOptions const &displayOptions, FilterOptions const &filterOptions)
void contextMenuEvent(QContextMenuEvent *event) final override
void setBibleReference(const QString &reference)
~BtModelViewReadDisplay() override
void scrollToSwordKey(CSwordKey *key)
QString getBibleUrlFromLink(const QString &url)
void dragOccuring(const QString &moduleName, const QString &keyName)
void setBibleReference(const QString &reference)
void activeLinkChanged(QString newActiveLink)
std::optional< Selection > const & selection() const noexcept
void updateReference(const QString &reference)
void setModules(const QStringList &modules)
void setHighlightWords(const QString &words, bool caseSensitivy)
void findText(bool backward)
QString getLemmaFromLink(const QString &url)
void referenceDropped(const QString &reference)
void scroll(int pixels)
void updateReferenceText()
The base class for all display windows of BibleTime.
QToolBar * mainToolBar() const noexcept
FilterOptions const & filterOptions() const noexcept
CKeyChooser * keyChooser() const noexcept
void lookupKey(QString const &key)
DisplayOptions const & displayOptions() const noexcept
CSwordKey * swordKey() const noexcept
void setBibleReference(const QString &reference)
static CSwordBackend & instance() noexcept
void setFilterOptions(const FilterOptions &options)
Implementation for Sword Bibles.
QString strippedText()
CSwordModuleInfo const * module() const
Definition cswordkey.h:68
virtual bool setKey(const QString &key)=0
virtual QString key() const =0
QString const & name() const
CSwordKey implementation for Sword's TreeKey.
QString key() const final override
CSwordKey implementation for Sword's VerseKey.
QString bookName() const
QString key() const final override
int chapter() const
void setVerse(int v)
std::optional< DecodedHyperlink > decodeHyperlink(QString const &hyperlink)
bool savePlainFile(const QString &filename, void(&writer)(QTextStream &, void *), void *userPtr)
Definition tool.cpp:33