BibleTime
cbookmarkindex.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-2026 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 <memory>
14#include <QAction>
15#include <QApplication>
16#include <QCursor>
17#include <QDrag>
18#include <QDragLeaveEvent>
19#include <QDragMoveEvent>
20#include <QDropEvent>
21#include <QFileDialog>
22#include <QMenu>
23#include <QMouseEvent>
24#include <QPainter>
25#include <QPaintEvent>
26#include <QScopeGuard>
27#include <QTimer>
28#include <QToolTip>
29#include "../../backend/btbookmarksmodel.h"
30#include "../../backend/config/btconfig.h"
31#include "../../backend/drivers/cswordmoduleinfo.h"
32#include "../../backend/managers/cswordbackend.h"
33#include "../../util/btassert.h"
34#include "../../util/btconnect.h"
35#include "../../util/bticons.h"
36#include "../../util/cresmgr.h"
37#include "../../util/tool.h"
38#include "../bookmarks/bteditbookmarkdialog.h"
39#include "../bookmarks/cbookmarkindex.h"
40#include "../btprinter.h"
41#include "../BtMimeData.h"
42#include "../messagedialog.h"
43
44
45namespace {
46
48 return QStringLiteral("%1 (*.btb);;%2 (*)")
49 .arg(QObject::tr("BibleTime bookmark files"),
50 QObject::tr("All files"));
51}
52
53} // anonymous namespace
54
56 : QTreeView{parent}
57 , m_magTimer{this}
58 , m_bookmarksModel{nullptr}
59{
60 setMouseTracking(true);
61 m_magTimer.setSingleShot(true);
62 m_magTimer.setInterval(
63 btConfig().value<int>(QStringLiteral("GUI/magDelay"), 400));
64 setContextMenuPolicy(Qt::CustomContextMenu);
65 setHeaderHidden(true);
66
67 //--------------------------------------------------------------------------
68 // Initialize view:
69
70 setHeaderHidden(true);
71
72 setFocusPolicy(Qt::WheelFocus);
73
74 //d'n'd related settings
75 setDragEnabled(true);
76 setAcceptDrops(true);
77 setDragDropMode(QAbstractItemView::DragDrop);
78 viewport()->setAcceptDrops(true);
79 setAutoScroll(true);
80 setAutoExpandDelay(800);
81
82 setItemsExpandable(true);
83 setRootIsDecorated(true);
84 setAllColumnsShowFocus(true);
85 setSelectionMode(QAbstractItemView::ExtendedSelection);
86
87 //setExpandsOnDoubleClick(true);
88 setEditTriggers(editTriggers() ^ QAbstractItemView::DoubleClicked);
89
90 //setup the popup menu
91 m_popup = new QMenu{viewport()};
92 m_popup->setTitle(tr("Bookmarks"));
93 auto const addMenuAction =
94 [this](MenuAction const menuAction,
95 QString const & text,
96 QIcon const & pix,
97 auto && slot)
98 {
99 auto * const action = new QAction(pix, text, this);
100 BT_CONNECT(action, &QAction::triggered,
101 std::forward<decltype(slot)>(slot));
102 m_actions[menuAction] = action;
103 m_popup->addAction(action);
104 };
105 namespace MI = CResMgr::mainIndex;
106 addMenuAction(NewFolder, tr("New folder"), MI::newFolder::icon(),
107 [this]{
108 if (!selectedIndexes().empty()) {
109 if (m_bookmarksModel->isFolder(currentIndex()))
110 setCurrentIndex(
113 currentIndex()),
114 currentIndex()));
115 } else { // create a top level folder
116 setCurrentIndex(
119 QModelIndex()));
120 }
121 });
122 addMenuAction(ChangeFolder, tr("Rename folder"), MI::changeFolder::icon(),
123 [this]{
124 BT_ASSERT(m_bookmarksModel->isFolder(currentIndex()));
125 edit(currentIndex());
126 });
127 m_popup->addSeparator();
128 addMenuAction(EditBookmark, tr("Edit bookmark..."),
129 MI::editBookmark::icon(),
130 [this]{
131 QModelIndex const index = currentIndex();
133 auto * const module = m_bookmarksModel->module(index);
135 QStringLiteral("%1 (%2)")
136 .arg(m_bookmarksModel->key(index))
137 .arg(module
138 ? module->name()
139 : QObject::tr("unknown")),
140 index.data().toString(),
142 this);
143 if (d.exec() == QDialog::Accepted) {
144 m_bookmarksModel->setData(index, d.titleText());
146 d.descriptionText());
147 }
148 });
149 addMenuAction(SortFolderBookmarks, tr("Sort folder bookmarks..."),
150 MI::sortFolderBookmarks::icon(),
151 [this]{
152 BT_ASSERT(m_bookmarksModel->isFolder(currentIndex()));
153 m_bookmarksModel->sortItems(currentIndex());
154 });
155 addMenuAction(SortAllBookmarks, tr("Sort all bookmarks..."),
156 MI::sortAllBookmarks::icon(),
157 [this]{
159 auto const numRows = m_bookmarksModel->rowCount();
160 if (m_extraItem.row() != numRows - 1) {
161 m_bookmarksModel->removeRow(m_extraItem.row(),
162 m_extraItem.parent());
163 if (m_bookmarksModel->insertRows(numRows - 1, 1))
164 m_extraItem =
165 m_bookmarksModel->index(numRows - 1, 0);
166 }
167 });
168 addMenuAction(ImportBookmarks, tr("Import to folder..."),
169 MI::importBookmarks::icon(),
170 [this]{
171 BT_ASSERT(m_bookmarksModel->isFolder(currentIndex()));
172 QString const fileName =
173 QFileDialog::getOpenFileName(
174 nullptr,
175 QObject::tr("Import bookmarks"),
176 QString(),
177 fileDialogFilter());
178 if (!fileName.isEmpty())
179 m_bookmarksModel->load(fileName, currentIndex());
180 });
181 addMenuAction(ExportBookmarks, tr("Export from folder..."),
182 MI::exportBookmarks::icon(),
183 [this]{
184 BT_ASSERT(m_bookmarksModel->isFolder(currentIndex()));
185 QString const fileName =
186 QFileDialog::getSaveFileName(
187 nullptr,
188 QObject::tr("Export Bookmarks"),
189 QString(),
190 fileDialogFilter());
191 if (!fileName.isEmpty())
192 m_bookmarksModel->save(fileName, currentIndex());
193 });
194 addMenuAction(PrintBookmarks, tr("Print bookmarks..."),
195 MI::printBookmarks::icon(),
196 [this]{
197 BT_ASSERT(hasBookmarksRecursively(selectedIndexes()));
199 {
201 false,
202 BtPrinter::KeyTreeItem::Settings::CompleteShort};
203 QModelIndexList items(selectedIndexes());
204 while (!items.empty()) {
205 QModelIndex const index(items.takeFirst());
206 if (m_bookmarksModel->isBookmark(index)) {
207 tree.emplace_back(
208 m_bookmarksModel->key(index),
209 m_bookmarksModel->module(index),
210 settings);
211 } else if (m_bookmarksModel->isFolder(index)) {
212 int const numChildren =
214 for (int i = 0; i < numChildren; i++)
215 items.append(index.model()->index(i,
216 0,
217 index));
218 }
219 }
220 }
221 BT_ASSERT(!tree.empty());
222
225 .printKeyTree(tree);
226 });
227 m_popup->addSeparator();
228 addMenuAction(DeleteEntries, tr("Remove selected items..."),
229 MI::deleteItems::icon(),
230 [this]{
232 this,
233 tr("Delete Items"),
234 tr("Do you really want to delete the selected "
235 "items and folders?"),
236 QMessageBox::Yes | QMessageBox::No,
237 QMessageBox::No) == QMessageBox::Yes)
239 });
240
241 //--------------------------------------------------------------------------
242 // Initialize connections:
243
244 BT_CONNECT(this, &CBookmarkIndex::activated,
245 [this](QModelIndex const & index) {
246 /** \note HACK: checking the modifier keys from the last
247 mouseReleaseEvent depends on executing order:
248 mouseReleaseEvent first, then itemClicked signal.*/
249 auto const modifiers = m_mouseReleaseEventModifiers;
250 m_mouseReleaseEventModifiers = Qt::NoModifier;
251 if (modifiers != Qt::NoModifier || !index.isValid())
252 return;
253
254 // Clicked on a bookmark:
255 if (m_bookmarksModel->isBookmark(index))
256 if (auto * const mod = m_bookmarksModel->module(index))
258 QList<CSwordModuleInfo *>() << mod,
259 m_bookmarksModel->key(index));
260 });
261 BT_CONNECT(this, &CBookmarkIndex::customContextMenuRequested,
262 [this](QPoint const & p) {
263 // Enable actions based on the selected items (if any):
264 QModelIndex const i(indexAt(p));
265 QModelIndexList const items(selectedIndexes());
266 if (items.isEmpty()) { // Special handling for no selection:
267 for (int index = ActionBegin; index < ActionEnd; ++index)
268 m_actions[index]->setEnabled(
269 (index == NewFolder)
270 || (index == SortAllBookmarks));
271 } else if (items.count() == 1) {
272 // Special handling for one selected item:
273 for (int index = ActionBegin; index < ActionEnd; ++index)
274 m_actions[index]->setEnabled(
275 enableAction(items.at(0),
276 static_cast<MenuAction>(index)));
277 } else if (!i.isValid()) {
278 // Disable all actions for invalid index:
279 for (int index = ActionBegin; index < ActionEnd; ++index)
280 m_actions[index]->setEnabled(false);
281 } else {
282 // Enable actions depending on the the selected items:
283 for (int index = ActionBegin; index < ActionEnd; ++index)
284 m_actions[index]->setEnabled(
285 (index == DeleteEntries)
286 || ((index == PrintBookmarks)
287 && hasBookmarksRecursively(items)));
288 }
289 m_popup->exec(mapToGlobal(p));
290 });
291 BT_CONNECT(&m_magTimer, &QTimer::timeout,
292 [this]{
293 if (!underMouse())
294 return;
295
296 /* Update the Mag only if the mouse pointer have been over
297 the same item since the timer was started. */
298 QModelIndex const itemUnderPointer(
299 indexAt(mapFromGlobal(QCursor::pos())));
300 if (itemUnderPointer.isValid()
301 && m_previousEventItem == itemUnderPointer
302 && m_bookmarksModel->isBookmark(itemUnderPointer))
303 {
304 if (CSwordModuleInfo const * const module =
305 m_bookmarksModel->module(itemUnderPointer))
306 {
307 Q_EMIT magInfoProvided(
309 QStringLiteral("%1:%2")
310 .arg(module->name(),
312 itemUnderPointer)));
313 } else {
314 Q_EMIT magInfoProvided(
316 tr("The work to which the bookmark "
317 "points to is not installed."));
318 }
319 }
320 });
321
322 //--------------------------------------------------------------------------
323 // Initialize tree:
324
326 setModel(m_bookmarksModel);
327
328 // add the invisible extra item at the end
332}
333
334/** \note Hack to get single click and selection working. See slotExecuted. */
335void CBookmarkIndex::mouseReleaseEvent(QMouseEvent* event) {
336 m_mouseReleaseEventModifiers = event->modifiers();
337 QTreeView::mouseReleaseEvent(event);
338}
339
340/** Creates a drag mime data object for the current selection. */
342 BTMimeData::ItemList bookmarks;
343 for (auto const & widgetItem : selectedIndexes()) {
344 if (!widgetItem.isValid())
345 break;
346 if (m_bookmarksModel->isBookmark(widgetItem)) {
347 /* Take care of bookmarks which have no valid module any more, e.g.
348 if these were uninstalled: */
349 CSwordModuleInfo * const module =
350 m_bookmarksModel->module(widgetItem);
351 const QString moduleName = module ? module->name() : QString();
352 bookmarks.append({moduleName,
353 m_bookmarksModel->key(widgetItem),
354 m_bookmarksModel->description(widgetItem)});
355 }
356 }
357 return new BTMimeData(std::move(bookmarks));
358}
359
360void CBookmarkIndex::dragEnterEvent(QDragEnterEvent * event) {
361 if (event->mimeData()->hasFormat(QStringLiteral("BibleTime/Bookmark"))) {
362 event->acceptProposedAction();
363 setState(DraggingState);
364 } else {
365 QAbstractItemView::dragEnterEvent(event);
366 }
367}
368
369void CBookmarkIndex::dragMoveEvent(QDragMoveEvent * event) {
370 // Do this first, otherwise the event may be ignored:
371 QTreeView::dragMoveEvent(event);
372
373 event->acceptProposedAction();
374 event->accept();
375
376 // Do this to paint the arrow:
377 m_dragMovementPosition = event->position().toPoint();
378 viewport()->update();
379}
380
381void CBookmarkIndex::dragLeaveEvent(QDragLeaveEvent *) {
382 setState(QAbstractItemView::NoState); // Not dragging anymore
383 viewport()->update(); // Clear the arrow
384}
385
386void CBookmarkIndex::paintEvent(QPaintEvent * event) {
387 // Do the normal painting first
388 QTreeView::paintEvent(event);
389
390 // Don't paint the arrow if not dragging:
391 if (state() != QAbstractItemView::DraggingState)
392 return;
393
394 static QPixmap pix;
395 static int halfPixHeight;
396 static bool arrowInitialized = false;
397
398 // Initialize the static variables, including the arrow pixmap
399 if (!arrowInitialized) {
400 arrowInitialized = true;
401 pix =
403 halfPixHeight = pix.height() / 2;
404 }
405
406 // Find the place for the arrow:
407 QModelIndex const index = indexAt(m_dragMovementPosition);
408 int xCoord, yCoord;
409 if (m_bookmarksModel->isBookmark(index)) {
410 QRect const rect = visualRect(index);
411 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
412 if (m_dragMovementPosition.y() > rect.bottom() - rect.height() / 2) {
413 yCoord = rect.bottom() - halfPixHeight; // bottom
414 } else {
415 yCoord = rect.top() - halfPixHeight - 1; // top
416 }
417 } else {
418 if (m_bookmarksModel->isFolder(index)) {
419 QRect const rect = visualRect(index);
421 > rect.bottom() - (2 * rect.height() / 3))
422 {
423 yCoord = rect.bottom() - halfPixHeight; // bottom
424 xCoord = QApplication::isRightToLeft()
425 ? (rect.right() - indentation())
426 : (rect.left() + indentation());
427 } else {
428 yCoord = rect.top() - halfPixHeight - 1; // top
429 xCoord = QApplication::isRightToLeft()
430 ? rect.right()
431 : rect.left();
432 }
433 } else if (index.isValid()) { // the extra item
434 QRect const rect = visualRect(index);
435 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
436 yCoord = rect.top() - halfPixHeight - 1;
437 } else { // empty area
438 QRect const rect = visualRect(m_extraItem);
439 yCoord = rect.top() - halfPixHeight - 1;
440 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
441 }
442 }
443 QPainter{this->viewport()}.drawPixmap(xCoord, yCoord, pix);
444}
445
446
447void CBookmarkIndex::dropEvent(QDropEvent * event) {
448 // Try to prevent annoying timed autocollapsing:
449 auto const connection =
450 BT_CONNECT(this, &CBookmarkIndex::collapsed,
451 [this](QModelIndex const & index) { expand(index); });
452 auto cleanup = qScopeGuard([&connection]() noexcept
453 { disconnect(connection); });
454 auto const pos = event->position().toPoint();
455 auto const index = indexAt(pos);
456 QModelIndex parentIndex;
457 int indexUnderParent = 0;
458
459 // Find the place where the drag is dropped
460 if (index.isValid()) {
461 if (m_bookmarksModel->isFolder(index)) {
462 QRect const rect = visualRect(index);
463 if (pos.y() > rect.bottom() - (2 * rect.height() / 3)) {
464 parentIndex = index;
465 } else {
466 parentIndex = index.parent();
467 indexUnderParent = index.row(); // before the current folder
468 }
469 } else {
470 if (m_bookmarksModel->isBookmark(index)) {
471 parentIndex = index.parent();
472 indexUnderParent = index.row(); // before the current bookmark
473 QRect const rect = visualRect(index);
474 if (pos.y() > rect.bottom() - rect.height() / 2)
475 indexUnderParent++; // after the current bookmark
476 } else { // item is the extra item
477 parentIndex = index.parent();
478 indexUnderParent = index.row(); // before the current bookmark
479 }
480 }
481 } else { // no item under event point: drop to the end
482 indexUnderParent = m_bookmarksModel->rowCount() - 1;
483 }
484
485 if (event->source() != this) {
486 // Take the bookmark data from the mime source
487 if (BTMimeData const * const mdata =
488 dynamic_cast<BTMimeData const *>(event->mimeData()))
489 {
490 //create the new bookmark
491 auto const & bookmark = mdata->bookmarks().first();
492 QString moduleName(bookmark.module());
493 QString keyText(bookmark.key());
494 QString description(bookmark.description());
495 auto * const minfo =
497 std::move(moduleName));
498 BT_ASSERT(minfo);
499
500 /// \todo add title
501 m_bookmarksModel->addBookmark(indexUnderParent,
502 parentIndex,
503 *minfo,
504 std::move(keyText),
505 std::move(description));
506 }
507 } else {
508 event->accept();
509
510 bool bookmarksOnly = true;
511 bool targetIncluded = false;
512 bool moreThanOneFolder = false;
513
514 QModelIndexList const list = selectedIndexes();
515 QModelIndexList newList;
516
517 for (auto const & index : list) {
518 if (m_bookmarksModel->isFolder(index)) {
519 bookmarksOnly = false;
520 // Only one item allowed if a folder is selected:
521 if (list.count() > 1) {
522 moreThanOneFolder = true;
523 break;
524 }
525 // Dropping to self or descendand not allowed:
526 if (m_bookmarksModel->hasDescendant(index, parentIndex)) {
527 targetIncluded = true;
528 break;
529 }
530 } else {
531 newList.append(index);
532 }
533 }
534
535 if (!bookmarksOnly && list.count() == 1) {
536 newList.append(list[0]); // list contain only one folder item
537 } else if (!bookmarksOnly && list.count() > 1) {
538 moreThanOneFolder = true; // wrong amount of items
539 }
540
541 if (moreThanOneFolder) {
542 QToolTip::showText(QCursor::pos(), tr("Can drop only bookmarks or one folder"));
543 return;
544 }
545 if (targetIncluded) {
546 QToolTip::showText(QCursor::pos(), tr("Can't drop folder into the folder itself or into its subfolder"));
547 return;
548 }
549
550 // Ask whether to copy or move with a popup menu
551 std::unique_ptr<QMenu> dropPopupMenu{new QMenu{this}};
552 dropPopupMenu->setEnabled(!newList.empty());
553 QAction * const copy = dropPopupMenu->addAction(tr("Copy"));
554 QAction * const move = dropPopupMenu->addAction(tr("Move"));
555 QAction * const dropAction = dropPopupMenu->exec(QCursor::pos());
556 dropPopupMenu.reset();
557
558 if (dropAction == copy) {
559 m_bookmarksModel->copyItems(indexUnderParent, parentIndex, newList);
560 } else if (dropAction == move) {
561 m_bookmarksModel->copyItems(indexUnderParent, parentIndex, newList);
563 } else { // user canceled
564 return;
565 }
566 }
567 setState(QAbstractItemView::NoState);
568}
569
570bool CBookmarkIndex::enableAction(QModelIndex const & index,
571 CBookmarkIndex::MenuAction const type) const
572{
573 switch (type) {
574 case NewFolder:
575 case ChangeFolder:
577 case ImportBookmarks:
578 case ExportBookmarks:
579 return m_bookmarksModel->isFolder(index);
580 case DeleteEntries:
581 return true;
582 case PrintBookmarks:
583 return hasBookmarksRecursively(QModelIndexList{} << index);
584 case EditBookmark:
585 return m_bookmarksModel->isBookmark(index);
586 default:
587 return false;
588 }
589}
590
591bool CBookmarkIndex::hasBookmarksRecursively(QModelIndexList items) const {
592 while (!items.empty()) {
593 QModelIndex const index = items.takeFirst();
594 if (m_bookmarksModel->isBookmark(index))
595 return true;
596 if (m_bookmarksModel->isFolder(index)) {
597 int const numChildren = m_bookmarksModel->rowCount(index);
598 for (int i = 0; i < numChildren; i++)
599 items.append(index.model()->index(i, 0, index));
600 }
601 }
602 return false;
603}
604
606 model()->setData(m_extraItem,
607 tr("Drag references from text views to this view"));
608}
609
611{ model()->setData(m_extraItem, QVariant()); }
612
613void CBookmarkIndex::leaveEvent(QEvent * event) {
615 update();
616 QTreeView::leaveEvent(event);
617}
618
620 /* We need to use QPersistentModelIndex because after removeRows QModelIndex
621 will be invalidated. Need to delete per index because selected indexes
622 might be under different parents. */
623 QList<QPersistentModelIndex> list;
624 for (auto const & i : selectedIndexes())
625 list.append(i);
626
627 for (auto const & i : list)
628 model()->removeRows(i.row(), 1, i.parent());
629}
630
631
632/*
633Reimplementation from QAbstractItemView/QTreeWidget. Takes care of movable items.
634It's easier to use this than to start drag with mouse event handlers.
635The default implementation would drag items, but we don't call it. Instead we create
636a BibleTime mimedata object. It can be dragged and dropped to a text view or somewhere else.
637The internal drag is handled differently, it doesn't use the mimedata (see dropEvent()).
638*/
639void CBookmarkIndex::startDrag(Qt::DropActions) {
640 // Create the data which can be used in other widgets:
641 QMimeData * const mData = dragObject();
642 QDrag * const drag = new QDrag{this};
643 drag->setMimeData(mData);
644 drag->exec();
645
646 viewport()->update(); // because of the arrow
647}
648
649void CBookmarkIndex::mouseMoveEvent(QMouseEvent * event) {
650 /* Restart the mag timer if we have moved to another item and shift was not
651 pressed: */
652 QModelIndex const itemUnderPointer = indexAt(event->pos());
653 if (itemUnderPointer.isValid()
654 && (itemUnderPointer != m_previousEventItem)
655 && !(event->modifiers() & Qt::ShiftModifier))
656 m_magTimer.start();
657 m_previousEventItem = itemUnderPointer;
658
659 if (!itemUnderPointer.isValid() || itemUnderPointer == m_extraItem) {
661 } else {
663 }
664 update();
665
666 QTreeView::mouseMoveEvent(event);
667}
#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
QList< BookmarkItem > ItemList
Definition BtMimeData.h:38
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void copyItems(int row, const QModelIndex &parent, const QModelIndexList &toCopy)
Copies item to target position.
bool isBookmark(const QModelIndex &index) const
bool hasDescendant(const QModelIndex &baseIndex, const QModelIndex &testIndex) const
bool isFolder(const QModelIndex &index) const
void sortItems(QModelIndex const &parent=QModelIndex(), Qt::SortOrder const order=Qt::AscendingOrder)
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QString description(const QModelIndex &index) const
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
void setDescription(const QModelIndex &index, const QString &description)
set descritpion for index.
bool load(QString fileName=QString(), const QModelIndex &rootItem=QModelIndex())
Import bookmarks from file.
CSwordModuleInfo * module(const QModelIndex &index) const
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QModelIndex addFolder(int row, const QModelIndex &parent, const QString &name=QString())
add new folder.
bool save(QString fileName=QString(), const QModelIndex &rootItem=QModelIndex())
Save bookmarks or specified branch to file.
QModelIndex addBookmark(int const row, QModelIndex const &parent, CSwordModuleInfo const &module, QString const &key, QString const &description=QString(), QString const &title=QString())
add new item with given parameters
QString key(const QModelIndex &index) const
DisplayOptions getDisplayOptions() const
Definition btconfig.h:176
FilterOptions getFilterOptions() const
Definition btconfig.h:160
A dialog box for editing bookmarks.
Manages the print item queue and printing.
Definition btprinter.h:19
void createReadDisplayWindow(QList< CSwordModuleInfo * >, QString const &)
Emitted when a module should be opened.
void startDrag(Qt::DropActions supportedActions) override
QPoint m_dragMovementPosition
BtBookmarksModel * m_bookmarksModel
void mouseReleaseEvent(QMouseEvent *event) override
void leaveEvent(QEvent *event) override
QMimeData * dragObject()
int m_mouseReleaseEventModifiers
void dragEnterEvent(QDragEnterEvent *event) override
void mouseMoveEvent(QMouseEvent *event) override
void magInfoProvided(Rendering::InfoType const, QString const &data)
QModelIndex m_previousEventItem
void paintEvent(QPaintEvent *event) override
CBookmarkIndex(QWidget *const parent=nullptr)
QAction * m_actions[ActionCount]
void dragLeaveEvent(QDragLeaveEvent *event) override
void dragMoveEvent(QDragMoveEvent *event) override
bool hasBookmarksRecursively(QModelIndexList selected) const
QPersistentModelIndex m_extraItem
void dropEvent(QDropEvent *event) override
bool enableAction(QModelIndex const &index, MenuAction const type) const
CSwordModuleInfo * findModuleByName(const QString &name) const
Searches for a module with the given name.
static CSwordBackend & instance() noexcept
std::list< KeyTreeItem > KeyTree
QIcon const & icon_pointing_arrow()
QMessageBox::StandardButton showQuestion(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
int mWidth(QWidget const &widget, int const mCount)
Calculates a maximum rendered text width for a widget and a string with the a given length.
Definition tool.cpp:117