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-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
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 this}.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 util::tool::mWidth(*this, 1));
404 halfPixHeight = pix.height() / 2;
405 }
406
407 // Find the place for the arrow:
408 QModelIndex const index = indexAt(m_dragMovementPosition);
409 int xCoord, yCoord;
410 if (m_bookmarksModel->isBookmark(index)) {
411 QRect const rect = visualRect(index);
412 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
413 if (m_dragMovementPosition.y() > rect.bottom() - rect.height() / 2) {
414 yCoord = rect.bottom() - halfPixHeight; // bottom
415 } else {
416 yCoord = rect.top() - halfPixHeight - 1; // top
417 }
418 } else {
419 if (m_bookmarksModel->isFolder(index)) {
420 QRect const rect = visualRect(index);
422 > rect.bottom() - (2 * rect.height() / 3))
423 {
424 yCoord = rect.bottom() - halfPixHeight; // bottom
425 xCoord = QApplication::isRightToLeft()
426 ? (rect.right() - indentation())
427 : (rect.left() + indentation());
428 } else {
429 yCoord = rect.top() - halfPixHeight - 1; // top
430 xCoord = QApplication::isRightToLeft()
431 ? rect.right()
432 : rect.left();
433 }
434 } else if (index.isValid()) { // the extra item
435 QRect const rect = visualRect(index);
436 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
437 yCoord = rect.top() - halfPixHeight - 1;
438 } else { // empty area
439 QRect const rect = visualRect(m_extraItem);
440 yCoord = rect.top() - halfPixHeight - 1;
441 xCoord = QApplication::isRightToLeft() ? rect.right() : rect.left();
442 }
443 }
444 QPainter{this->viewport()}.drawPixmap(xCoord, yCoord, pix);
445}
446
447
448void CBookmarkIndex::dropEvent(QDropEvent * event) {
449 // Try to prevent annoying timed autocollapsing:
450 auto const connection =
451 BT_CONNECT(this, &CBookmarkIndex::collapsed,
452 [this](QModelIndex const & index) { expand(index); });
453 auto cleanup = qScopeGuard([&connection]() noexcept
454 { disconnect(connection); });
455 auto const pos = event->position().toPoint();
456 auto const index = indexAt(pos);
457 QModelIndex parentIndex;
458 int indexUnderParent = 0;
459
460 // Find the place where the drag is dropped
461 if (index.isValid()) {
462 if (m_bookmarksModel->isFolder(index)) {
463 QRect const rect = visualRect(index);
464 if (pos.y() > rect.bottom() - (2 * rect.height() / 3)) {
465 parentIndex = index;
466 } else {
467 parentIndex = index.parent();
468 indexUnderParent = index.row(); // before the current folder
469 }
470 } else {
471 if (m_bookmarksModel->isBookmark(index)) {
472 parentIndex = index.parent();
473 indexUnderParent = index.row(); // before the current bookmark
474 QRect const rect = visualRect(index);
475 if (pos.y() > rect.bottom() - rect.height() / 2)
476 indexUnderParent++; // after the current bookmark
477 } else { // item is the extra item
478 parentIndex = index.parent();
479 indexUnderParent = index.row(); // before the current bookmark
480 }
481 }
482 } else { // no item under event point: drop to the end
483 indexUnderParent = m_bookmarksModel->rowCount() - 1;
484 }
485
486 if (event->source() != this) {
487 // Take the bookmark data from the mime source
488 if (BTMimeData const * const mdata =
489 dynamic_cast<BTMimeData const *>(event->mimeData()))
490 {
491 //create the new bookmark
492 auto const & bookmark = mdata->bookmarks().first();
493 QString moduleName(bookmark.module());
494 QString keyText(bookmark.key());
495 QString description(bookmark.description());
496 auto * const minfo =
498 std::move(moduleName));
499 BT_ASSERT(minfo);
500
501 /// \todo add title
502 m_bookmarksModel->addBookmark(indexUnderParent,
503 parentIndex,
504 *minfo,
505 std::move(keyText),
506 std::move(description));
507 }
508 } else {
509 event->accept();
510
511 bool bookmarksOnly = true;
512 bool targetIncluded = false;
513 bool moreThanOneFolder = false;
514
515 QModelIndexList const list = selectedIndexes();
516 QModelIndexList newList;
517
518 for (auto const & index : list) {
519 if (m_bookmarksModel->isFolder(index)) {
520 bookmarksOnly = false;
521 // Only one item allowed if a folder is selected:
522 if (list.count() > 1) {
523 moreThanOneFolder = true;
524 break;
525 }
526 // Dropping to self or descendand not allowed:
527 if (m_bookmarksModel->hasDescendant(index, parentIndex)) {
528 targetIncluded = true;
529 break;
530 }
531 } else {
532 newList.append(index);
533 }
534 }
535
536 if (!bookmarksOnly && list.count() == 1) {
537 newList.append(list[0]); // list contain only one folder item
538 } else if (!bookmarksOnly && list.count() > 1) {
539 moreThanOneFolder = true; // wrong amount of items
540 }
541
542 if (moreThanOneFolder) {
543 QToolTip::showText(QCursor::pos(), tr("Can drop only bookmarks or one folder"));
544 return;
545 }
546 if (targetIncluded) {
547 QToolTip::showText(QCursor::pos(), tr("Can't drop folder into the folder itself or into its subfolder"));
548 return;
549 }
550
551 // Ask whether to copy or move with a popup menu
552 std::unique_ptr<QMenu> dropPopupMenu{new QMenu{this}};
553 dropPopupMenu->setEnabled(!newList.empty());
554 QAction * const copy = dropPopupMenu->addAction(tr("Copy"));
555 QAction * const move = dropPopupMenu->addAction(tr("Move"));
556 QAction * const dropAction = dropPopupMenu->exec(QCursor::pos());
557 dropPopupMenu.reset();
558
559 if (dropAction == copy) {
560 m_bookmarksModel->copyItems(indexUnderParent, parentIndex, newList);
561 } else if (dropAction == move) {
562 m_bookmarksModel->copyItems(indexUnderParent, parentIndex, newList);
564 } else { // user canceled
565 return;
566 }
567 }
568 setState(QAbstractItemView::NoState);
569}
570
571bool CBookmarkIndex::enableAction(QModelIndex const & index,
572 CBookmarkIndex::MenuAction const type) const
573{
574 switch (type) {
575 case NewFolder:
576 case ChangeFolder:
578 case ImportBookmarks:
579 case ExportBookmarks:
580 return m_bookmarksModel->isFolder(index);
581 case DeleteEntries:
582 return true;
583 case PrintBookmarks:
584 return hasBookmarksRecursively(QModelIndexList{} << index);
585 case EditBookmark:
586 return m_bookmarksModel->isBookmark(index);
587 default:
588 return false;
589 }
590}
591
592bool CBookmarkIndex::hasBookmarksRecursively(QModelIndexList items) const {
593 while (!items.empty()) {
594 QModelIndex const index = items.takeFirst();
595 if (m_bookmarksModel->isBookmark(index))
596 return true;
597 if (m_bookmarksModel->isFolder(index)) {
598 int const numChildren = m_bookmarksModel->rowCount(index);
599 for (int i = 0; i < numChildren; i++)
600 items.append(index.model()->index(i, 0, index));
601 }
602 }
603 return false;
604}
605
607 model()->setData(m_extraItem,
608 tr("Drag references from text views to this view"));
609}
610
612{ model()->setData(m_extraItem, QVariant()); }
613
614void CBookmarkIndex::leaveEvent(QEvent * event) {
616 update();
617 QTreeView::leaveEvent(event);
618}
619
621 /* We need to use QPersistentModelIndex because after removeRows QModelIndex
622 will be invalidated. Need to delete per index because selected indexes
623 might be under different parents. */
624 QList<QPersistentModelIndex> list;
625 for (auto const & i : selectedIndexes())
626 list.append(i);
627
628 for (auto const & i : list)
629 model()->removeRows(i.row(), 1, i.parent());
630}
631
632
633/*
634Reimplementation from QAbstractItemView/QTreeWidget. Takes care of movable items.
635It's easier to use this than to start drag with mouse event handlers.
636The default implementation would drag items, but we don't call it. Instead we create
637a BibleTime mimedata object. It can be dragged and dropped to a text view or somewhere else.
638The internal drag is handled differently, it doesn't use the mimedata (see dropEvent()).
639*/
640void CBookmarkIndex::startDrag(Qt::DropActions) {
641 // Create the data which can be used in other widgets:
642 QMimeData * const mData = dragObject();
643 QDrag * const drag = new QDrag{this};
644 drag->setMimeData(mData);
645 drag->exec();
646
647 viewport()->update(); // because of the arrow
648}
649
650void CBookmarkIndex::mouseMoveEvent(QMouseEvent * event) {
651 /* Restart the mag timer if we have moved to another item and shift was not
652 pressed: */
653 QModelIndex const itemUnderPointer = indexAt(event->pos());
654 if (itemUnderPointer.isValid()
655 && (itemUnderPointer != m_previousEventItem)
656 && !(event->modifiers() & Qt::ShiftModifier))
657 m_magTimer.start();
658 m_previousEventItem = itemUnderPointer;
659
660 if (!itemUnderPointer.isValid() || itemUnderPointer == m_extraItem) {
662 } else {
664 }
665 update();
666
667 QTreeView::mouseMoveEvent(event);
668}
#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.
RegularIcon const icon_pointing_arrow
Definition bticons.h:99
static BtIcons & instance()
Definition bticons.h:44
Manages the print item queue and printing.
Definition btprinter.h:20
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
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:155