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#include <QTimer>
27#include <QToolBar>
28#include <utility>
29#include "../../backend/keys/cswordkey.h"
30#include "../../backend/drivers/cswordbiblemoduleinfo.h"
31#include "../../backend/managers/cswordbackend.h"
32#include "../../backend/managers/referencemanager.h"
33#include "../../util/btassert.h"
34#include "../../util/btconnect.h"
35#include "../../util/tool.h"
36#include "../bibletime.h"
37#include "../btcopybyreferencesdialog.h"
38#include "../BtMimeData.h"
39#include "../cexportmanager.h"
40#include "../displaywindow/cdisplaywindow.h"
41#include "../keychooser/ckeychooser.h"
44
45
47 CDisplayWindow * const displayWindow,
48 QWidget * const parentWidget)
49 : QWidget(parentWidget)
50 , m_parentWindow(displayWindow)
51 , m_quickWidget(new BtQuickWidget(this))
52 , m_qmlInterface(m_quickWidget->qmlInterface())
53 , m_scrollBar(new QScrollBar(this))
54{
55 auto * const layout = new QHBoxLayout(this);
56 layout->setContentsMargins(0, 0, 0, 0);
57
58 m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
59 m_quickWidget->show();
61 [this](QString const & reference) { /// \todo Fix me
62 auto key(m_parentWindow->swordKey());
63 key->setKey(reference);
64 m_parentWindow->lookupKey(reference);
65 });
66 layout->addWidget(m_quickWidget);
67
68 m_scrollBar->setRange(-100,100);
69 m_scrollBar->setValue(0);
70 BT_CONNECT(m_scrollBar, &QScrollBar::sliderMoved,
72 BT_CONNECT(m_scrollBar, &QScrollBar::sliderPressed,
74 BT_CONNECT(m_scrollBar, &QScrollBar::sliderReleased,
76 layout->addWidget(m_scrollBar);
77
79 [this](QString const & reference) {
80 auto * const key = m_parentWindow->swordKey();
81 key->setKey(reference);
82 m_parentWindow->keyChooser()->updateKey(key);
84 });
86 [this](const QString& moduleName, const QString& keyName) {
87 auto & drag = *new QDrag(this);
88 auto mimedata =
89 std::make_unique<BTMimeData>(
90 BTMimeData::ItemList{{moduleName, keyName, {}}});
91 //add real Bible text from module/key
92 if (auto * const module =
93 CSwordBackend::instance().findModuleByName(moduleName))
94 {
95 drag.setPixmap(
96 module->moduleIcon().pixmap(
97 m_parentWindow->mainToolBar()->iconSize()));
98 std::unique_ptr<CSwordKey> key(module->createKey());
99 key->setKey(keyName);
100 // This works across applications:
101 mimedata->setText(key->strippedText());
102 }
103 drag.setMimeData(mimedata.release());
104 drag.exec(Qt::CopyAction, Qt::CopyAction);
105 });
111 [this](QString const & newLink) {
112 auto newAnchor = m_qmlInterface->getBibleUrlFromLink(newLink);
113 if (m_activeAnchor != newAnchor) {
114 m_activeAnchor = newAnchor;
115 activeAnchorChanged(std::move(newAnchor));
116 }
118 });
119
120 setLayout(layout);
121}
122
124
125void BtModelViewReadDisplay::setBibleReference(const QString& reference) {
127}
128
130 int speed = 25 * (1 + std::abs(value/30));
131 int relative = value - m_scrollBarPosition;
132 m_quickWidget->scroll(relative * speed);
133 m_scrollBarPosition = value;
135}
136
140
145
147{ QGuiApplication::clipboard()->setText(text(part)); }
148
149void BtModelViewReadDisplay::contextMenuEvent(QContextMenuEvent * event) {
150 if (m_popup)
151 m_popup->exec(event->globalPos());
152}
153
155{ QGuiApplication::clipboard()->setText(qmlInterface()->getSelectedText()); }
156
158 auto const & qml = *qmlInterface();
159 BtCopyByReferencesDialog dlg(qml.textModel(),
160 qml.selection(),
162 if (dlg.exec() != QDialog::Accepted)
163 return;
164
165 auto const & result = dlg.result();
166 BT_ASSERT(result.module);
167 auto const & module = *result.module;
168 if (module.type() == CSwordModuleInfo::Bible
169 || module.type() == CSwordModuleInfo::Commentary)
170 {
171 qml.copyVerseRange(static_cast<CSwordVerseKey const &>(*result.key1),
172 static_cast<CSwordVerseKey const &>(*result.key2));
173 } else {
174 qml.copyRange(result.index1, result.index2);
175 }
176}
177
179 auto const filename =
180 QFileDialog::getSaveFileName(
181 nullptr,
182 QObject::tr("Save document ..."),
183 "",
184 QObject::tr("Text files") + " (*.txt);;"
185 + QObject::tr("All files") + " (*)");
186 if (!filename.isEmpty())
187 util::tool::savePlainFile(filename, text(part));
188}
189
191 DisplayOptions const & displayOptions,
192 FilterOptions const & filterOptions)
193{
194 using CSBiMI = CSwordBibleModuleInfo;
195 CSwordKey* const key = m_parentWindow->swordKey();
196 const CSwordModuleInfo *module = key->module();
197
198 CExportManager mgr(false,
199 QString(),
202
203 switch (type) {
204 case Document: {
205 if (module->type() == CSwordModuleInfo::Bible) {
206 CSwordVerseKey* vk = dynamic_cast<CSwordVerseKey*>(key);
207
208 CSwordVerseKey startKey(*vk);
209 startKey.setVerse(1);
210
211 CSwordVerseKey stopKey(*vk);
212
213 const CSBiMI *bible = dynamic_cast<const CSBiMI*>(module);
214 if (bible) {
215 stopKey.setVerse(bible->verseCount(bible->bookNumber(startKey.bookName()), startKey.chapter()));
216 }
217
218 mgr.printKey(module, startKey.key(), stopKey.key(), displayOptions, filterOptions);
219 }
220 else if (module->type() == CSwordModuleInfo::Lexicon || module->type() == CSwordModuleInfo::Commentary ) {
221 mgr.printKey(module, key->key(), key->key(), displayOptions, filterOptions);
222 }
223 else if (module->type() == CSwordModuleInfo::GenericBook) {
224 CSwordTreeKey* tree = dynamic_cast<CSwordTreeKey*>(key);
225
226 CSwordTreeKey startKey(*tree);
227 // while (startKey.previousSibling()) { // go to first sibling on this level!
228 // }
229
230 CSwordTreeKey stopKey(*tree);
231 // if (CSwordBookModuleInfo* book = dynamic_cast<CSwordBookModuleInfo*>(module)) {
232 // while ( stopKey.nextSibling() ) { //go to last displayed sibling!
233 // }
234 // }
235 mgr.printKey(module, startKey.key(), stopKey.key(), displayOptions, filterOptions);
236 }
237 break;
238 }
239
240 case AnchorWithText: {
241 if (!m_activeAnchor.isEmpty())
242 mgr.printByHyperlink(m_activeAnchor, displayOptions, filterOptions);
243 break;
244 }
245
246 default:
247 break;
248 }
249}
250
252 qmlInterface()->textModel()->reloadModules();
253}
254
255QString
257 QString text;
258 switch (part) {
259 case Document: {
260 CSwordKey* const key = m_parentWindow->swordKey();
261 const CSwordModuleInfo *module = key->module();
262 //This is never used for Bibles, so it is not implemented for
263 //them. If it should be, see CReadDisplay::print() for example
264 //code.
265 BT_ASSERT(module->type() == CSwordModuleInfo::Lexicon ||
266 module->type() == CSwordModuleInfo::Commentary ||
267 module->type() == CSwordModuleInfo::GenericBook);
268 FilterOptions filterOptions;
270
271 text = QStringLiteral("%1\n(%2, %3)")
272 .arg(key->strippedText(), key->key(), key->module()->name());
273 break;
274 }
275
276 case AnchorOnly: {
277 if (auto const decodedLink =
279 return decodedLink->key;
280 return {};
281 }
282
283 case AnchorTextOnly: {
284 auto const decodedLink(
286 if (decodedLink && decodedLink->module) {
287 std::unique_ptr<CSwordKey> key(decodedLink->module->createKey());
288 key->setKey(decodedLink->key);
289 return key->strippedText();
290 }
291 return {};
292 }
293
294 case AnchorWithText: {
295 auto const decodedLink(
297 if (decodedLink && decodedLink->module) {
298 std::unique_ptr<CSwordKey> key(decodedLink->module->createKey());
299 key->setKey(decodedLink->key);
300
301 FilterOptions filterOptions;
303
304 return QStringLiteral("%1\n(%2, %3)")
305 .arg(key->strippedText(), key->key(), key->module()->name());
306 }
307 return {};
308 }
309 default:
310 break;
311 }
312 return QString();
313
314}
315
317
319 FilterOptions const & filterOptions)
320{ m_qmlInterface->textModel()->setOptions(displayOptions, filterOptions); }
321
322void BtModelViewReadDisplay::setModules(const QStringList &modules) {
323 m_qmlInterface->setModules(modules);
324}
325
329
331
335
339
341
343
344void BtModelViewReadDisplay::highlightText(const QString& text, bool caseSensitive) {
345 m_qmlInterface->setHighlightWords(text, caseSensitive);
346}
347
348void BtModelViewReadDisplay::findText(bool const backward)
349{ m_qmlInterface->findText(backward); }
350
351// Save the Lemma (Strongs number) attribute
352void BtModelViewReadDisplay::setNodeInfo(QString const & newNodeInfo) {
353 if (m_nodeInfo != newNodeInfo) {
354 m_nodeInfo = newNodeInfo;
355 Q_EMIT nodeInfoChanged(newNodeInfo);
356 }
357}
#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:222
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)
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:35