Okular

bookmarkmanager.cpp
1/*
2 SPDX-FileCopyrightText: 2006 Pino Toscano <pino@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "bookmarkmanager.h"
8
9// qt/kde includes
10#include <KBookmarkAction>
11#include <KBookmarkManager>
12#include <KBookmarkMenu>
13#include <KBookmarkOwner>
14#include <QDebug>
15#include <QFileInfo>
16#include <QGuiApplication>
17#include <QHash>
18#include <QSet>
19#include <QStandardPaths>
20#include <QUrl>
21
22// local includes
23#include "document_p.h"
24#include "observer.h"
25
26using namespace Okular;
27
28#define foreachObserver(cmd) \
29 { \
30 QSet<DocumentObserver *>::const_iterator it = d->document->m_observers.constBegin(), end = d->document->m_observers.constEnd(); \
31 for (; it != end; ++it) { \
32 (*it)->cmd; \
33 } \
34 }
35
36#define foreachObserverD(cmd) \
37 { \
38 QSet<DocumentObserver *>::const_iterator it = document->m_observers.constBegin(), end = document->m_observers.constEnd(); \
39 for (; it != end; ++it) { \
40 (*it)->cmd; \
41 } \
42 }
43
44class OkularBookmarkAction : public KBookmarkAction
45{
47public:
48 OkularBookmarkAction(const Okular::DocumentViewport &vp, const KBookmark &bk, KBookmarkOwner *owner, QObject *parent)
49 : KBookmarkAction(bk, owner, parent)
50 {
51 if (vp.isValid()) {
52 setText(QString::number(vp.pageNumber + 1) + QStringLiteral(" - ") + text());
53 }
54 setProperty("pageNumber", vp.pageNumber + 1);
56 }
57
58 inline int pageNumber() const
59 {
60 return property("pageNumber").toInt();
61 }
62
63 inline QString htmlRef() const
64 {
65 return property("htmlRef").toString();
66 }
67};
68
69static inline bool documentViewportFuzzyCompare(const DocumentViewport &vp1, const DocumentViewport &vp2)
70{
71 bool equal = vp1.isValid() && vp2.isValid() && (vp1.pageNumber == vp2.pageNumber) && (vp1.rePos.pos == vp2.rePos.pos);
72
73 if (!equal) {
74 return false;
75 }
76
77 if (qAbs(vp1.rePos.normalizedX - vp2.rePos.normalizedX) >= 0.000001) {
78 return false;
79 }
80
81 if (qAbs(vp1.rePos.normalizedY - vp2.rePos.normalizedY) >= 0.000001) {
82 return false;
83 }
84
85 return true;
86}
87
88static inline bool bookmarkLessThan(const KBookmark &b1, const KBookmark &b2)
89{
92
93 return vp1 < vp2;
94}
95
96static inline bool okularBookmarkActionLessThan(QAction *a1, QAction *a2)
97{
98 DocumentViewport vp1(static_cast<OkularBookmarkAction *>(a1)->htmlRef());
99 DocumentViewport vp2(static_cast<OkularBookmarkAction *>(a2)->htmlRef());
100
101 return vp1 < vp2;
102}
103
104static QUrl mostCanonicalUrl(const QUrl &url)
105{
106 if (!url.isLocalFile()) {
107 return url;
108 }
109
110 const QFileInfo fi(url.toLocalFile());
111 return QUrl::fromLocalFile(fi.canonicalFilePath());
112}
113
114class BookmarkManager::Private : public KBookmarkOwner
115{
116public:
117 explicit Private(BookmarkManager *qq)
119 , q(qq)
120 , document(nullptr)
121 , file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/okular/bookmarks.xml"))
122 , manager(KBookmarkManager(file))
123 {
124 }
125
126 ~Private() override
127 {
128 knownFiles.clear();
129 // no need to delete the manager, it's automatically done by KBookmarkManager
130 // delete manager;
131 }
132
133 Private(const Private &) = delete;
134 Private &operator=(const Private &) = delete;
135
136 QUrl currentUrl() const override;
137 QString currentTitle() const override;
138 bool enableOption(BookmarkOption option) const override;
139 void openBookmark(const KBookmark &bm, Qt::MouseButtons, Qt::KeyboardModifiers) override;
140
141 QHash<QUrl, QString>::iterator bookmarkFind(const QUrl &url, bool doCreate, KBookmarkGroup *result = nullptr);
142
143 // slots
144 void _o_changed(const QString &groupAddress);
145
147 QUrl url;
148 QHash<int, int> urlBookmarks;
149 DocumentPrivate *document;
150 QString file;
151 KBookmarkManager manager;
152 QHash<QUrl, QString> knownFiles;
153};
154
155static inline QUrl urlForGroup(const KBookmark &group)
156{
157 if (group.url().isValid()) {
158 return group.url();
159 } else {
160 return QUrl::fromUserInput(group.fullText());
161 }
162}
163
164BookmarkManager::BookmarkManager(DocumentPrivate *document)
165 : QObject(document->m_parent)
166 , d(new Private(this))
167{
168 setObjectName(QStringLiteral("Okular::BookmarkManager"));
169
170 d->document = document;
171
172 connect(&d->manager, &KBookmarkManager::changed, this, [this](const QString &groupAddress) { d->_o_changed(groupAddress); });
173}
174
175BookmarkManager::~BookmarkManager()
176{
177 delete d;
178}
179
180// BEGIN Reimplementations from KBookmarkOwner
181QUrl BookmarkManager::Private::currentUrl() const
182{
183 return url;
184}
185
186QString BookmarkManager::Private::currentTitle() const
187{
188 return url.toDisplayString();
189}
190
191bool BookmarkManager::Private::enableOption(BookmarkOption option) const
192{
193 Q_UNUSED(option)
194 return false;
195}
196
197void BookmarkManager::Private::openBookmark(const KBookmark &bm, Qt::MouseButtons, Qt::KeyboardModifiers)
198{
199 Q_EMIT q->openUrl(bm.url());
200}
201// END Reimplementations from KBookmarkOwner
202
203void BookmarkManager::Private::_o_changed(const QString &groupAddress)
204{
205 if (groupAddress.isEmpty()) {
206 return;
207 }
208
209 QUrl referurl;
210 // first, try to find the bookmark group whom change notification was just received
211 QHash<QUrl, QString>::iterator it = knownFiles.begin(), itEnd = knownFiles.end();
212 for (; it != itEnd; ++it) {
213 if (it.value() == groupAddress) {
214 referurl = it.key();
215 knownFiles.erase(it);
216 break;
217 }
218 }
219 if (!referurl.isValid()) {
220 const KBookmark bm = manager.findByAddress(groupAddress);
221 // better be safe than sorry
222 if (bm.isNull()) {
223 return;
224 }
225 Q_ASSERT(bm.isGroup());
226 referurl = urlForGroup(bm);
227 }
228 Q_ASSERT(referurl.isValid());
229 Q_EMIT q->bookmarksChanged(referurl);
230 // case for the url representing the current document
231 // (this might happen if the same document is open in another place;
232 // in such case, make really sure to be in sync)
233 if (referurl == url) {
234 // save the old bookmarks for the current url
235 const QHash<int, int> oldUrlBookmarks = urlBookmarks;
236 // set the same url again, so we reload the information we have about it
237 q->setUrl(referurl);
238 // then notify the observers about the changes in the bookmarks
239 for (int i = 0; i < qMax(oldUrlBookmarks.size(), urlBookmarks.size()); i++) {
240 bool oldContains = oldUrlBookmarks.contains(i) && oldUrlBookmarks[i] > 0;
241 bool curContains = urlBookmarks.contains(i) && urlBookmarks[i] > 0;
242
243 if (oldContains != curContains) {
244 foreachObserverD(notifyPageChanged(i, DocumentObserver::Bookmark));
245 } else if (oldContains && oldUrlBookmarks[i] != urlBookmarks[i]) {
246 foreachObserverD(notifyPageChanged(i, DocumentObserver::Bookmark));
247 }
248 }
249 }
250 Q_EMIT q->saved();
251}
252
254{
255 QList<QUrl> ret;
256 KBookmarkGroup group = d->manager.root();
257 for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
258 if (bm.isSeparator() || !bm.isGroup()) {
259 continue;
260 }
261
262 ret.append(urlForGroup(bm));
263 }
264 return ret;
265}
266
268{
269 const QUrl url = mostCanonicalUrl(documentUrl);
270 KBookmark::List ret;
271 KBookmarkGroup group = d->manager.root();
272 for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
273 if (!bm.isGroup() || urlForGroup(bm) != url) {
274 continue;
275 }
276
277 KBookmarkGroup group = bm.toGroup();
278 for (KBookmark b = group.first(); !b.isNull(); b = group.next(b)) {
279 if (b.isSeparator() || b.isGroup()) {
280 continue;
281 }
282
283 ret.append(b);
284 }
285 break;
286 }
287
288 return ret;
289}
290
292{
293 return bookmarks(d->url);
294}
295
297{
298 const KBookmark::List bmarks = bookmarks();
299 KBookmark::List ret;
300 for (const KBookmark &bm : bmarks) {
302 if (vp.isValid() && vp.pageNumber == page) {
303 ret.append(bm);
304 }
305 }
306
307 return ret;
308}
309
311{
312 const KBookmark::List bmarks = bookmarks();
313 for (const KBookmark &bm : bmarks) {
315 if (vp.isValid() && vp.pageNumber == page) {
316 return bm;
317 }
318 }
319 return KBookmark();
320}
321
323{
324 if (!viewport.isValid() || !isBookmarked(viewport.pageNumber)) {
325 return KBookmark();
326 }
327
328 KBookmarkGroup thebg;
329 QHash<QUrl, QString>::iterator it = d->bookmarkFind(d->url, false, &thebg);
330 if (it == d->knownFiles.end()) {
331 return KBookmark();
332 }
333
334 for (KBookmark bm = thebg.first(); !bm.isNull(); bm = thebg.next(bm)) {
335 if (bm.isSeparator() || bm.isGroup()) {
336 continue;
337 }
338
340 if (documentViewportFuzzyCompare(vp, viewport)) {
341 return bm;
342 }
343 }
344
345 return KBookmark();
346}
347
349{
350 d->manager.emitChanged();
351 Q_EMIT const_cast<BookmarkManager *>(this)->saved();
352}
353
354QHash<QUrl, QString>::iterator BookmarkManager::Private::bookmarkFind(const QUrl &url, bool doCreate, KBookmarkGroup *result)
355{
356 QHash<QUrl, QString>::iterator it = knownFiles.find(url);
357 if (it == knownFiles.end()) {
358 // if the url we want to add a new entry for is not in the hash of the
359 // known files, then first try to find the file among the top-level
360 // "folder" names
361 bool found = false;
362 KBookmarkGroup root = manager.root();
363 for (KBookmark bm = root.first(); !found && !bm.isNull(); bm = root.next(bm)) {
364 if (bm.isSeparator() || !bm.isGroup()) {
365 continue;
366 }
367
368 QUrl tmpurl(urlForGroup(bm));
369 if (tmpurl == url) {
370 // got it! place it the hash of known files
371 KBookmarkGroup bg = bm.toGroup();
372 it = knownFiles.insert(url, bg.address());
373 found = true;
374 if (result) {
375 *result = bg;
376 }
377 break;
378 }
379 }
380 if (!found && doCreate) {
381 // folder not found :(
382 // then, in a single step create a new folder and add it in our cache :)
383 QString purl = url.isLocalFile() ? url.toLocalFile() : url.toDisplayString();
384 KBookmarkGroup newbg = root.createNewFolder(purl);
385 newbg.setUrl(url);
386 it = knownFiles.insert(url, newbg.address());
387 if (result) {
388 *result = newbg;
389 }
390 }
391 } else if (result) {
392 const KBookmark bm = manager.findByAddress(it.value());
393 Q_ASSERT(bm.isGroup());
394 *result = bm.toGroup();
395 }
396 return it;
397}
398
400{
401 if (page >= 0 && page < (int)d->document->m_pagesVector.count()) {
402 if (setPageBookmark(page))
403 foreachObserver(notifyPageChanged(page, DocumentObserver::Bookmark));
404 }
405}
406
408{
409 addBookmark(d->url, vp);
410}
411
412bool BookmarkManager::addBookmark(const QUrl &documentUrl, const Okular::DocumentViewport &vp, const QString &title)
413{
414 if (!documentUrl.isValid() || !vp.isValid()) {
415 return false;
416 }
417
418 if (vp.pageNumber < 0 || vp.pageNumber >= d->document->m_pagesVector.count()) {
419 return false;
420 }
421
422 const QUrl referurl = mostCanonicalUrl(documentUrl);
423
424 KBookmarkGroup thebg;
425 QHash<QUrl, QString>::iterator it = d->bookmarkFind(referurl, true, &thebg);
426 Q_ASSERT(it != d->knownFiles.end());
427
428 int count = 0; // Number of bookmarks in the current page
429 bool found = false;
430 // Check if the bookmark already exists
431 for (KBookmark bm = thebg.first(); !found && !bm.isNull(); bm = thebg.next(bm)) {
432 if (bm.isSeparator() || bm.isGroup()) {
433 continue;
434 }
435
437 if (bmViewport.isValid() && bmViewport.pageNumber == vp.pageNumber) {
438 ++count;
439
440 if (documentViewportFuzzyCompare(bmViewport, vp)) {
441 found = true;
442 }
443 }
444 }
445
446 if (found) {
447 return false;
448 }
449
450 QString newtitle;
451 if (title.isEmpty()) {
452 // if we have no title specified for the new bookmark, then give it the
453 // name '#p' where p is the page number where the bookmark is located.
454 // if there's more than one bookmark per page, give the name '#p-n'
455 // where n is the index of this bookmark among the ones of its page.
456 if (count > 0) {
457 newtitle = QStringLiteral("#%1-%2").arg(vp.pageNumber + 1).arg(count);
458 } else {
459 newtitle = QStringLiteral("#%1").arg(vp.pageNumber + 1);
460 }
461 } else {
462 newtitle = title;
463 }
464
465 QUrl newurl = referurl;
467 thebg.addBookmark(newtitle, newurl, QString());
468 if (referurl == d->document->m_url) {
469 d->urlBookmarks[vp.pageNumber]++;
470 foreachObserver(notifyPageChanged(vp.pageNumber, DocumentObserver::Bookmark));
471 }
472 d->manager.emitChanged(thebg);
473 return true;
474}
475
477{
478 if (page >= 0 && page < (int)d->document->m_pagesVector.count()) {
479 if (removePageBookmark(page))
480 foreachObserver(notifyPageChanged(page, DocumentObserver::Bookmark));
481 }
482}
483
485{
486 int page = vp.pageNumber;
487 if (page >= 0 && page < d->document->m_pagesVector.count()) {
488 removeBookmark(d->url, bookmark(vp));
489 }
490}
491
493{
494 KBookmarkGroup thebg;
495 QHash<QUrl, QString>::iterator it = d->bookmarkFind(d->url, false, &thebg);
496 Q_ASSERT(it != d->knownFiles.end());
497 if (it == d->knownFiles.end()) {
498 return;
499 }
500
501 bm->setFullText(newName);
502 d->manager.emitChanged(thebg);
503}
504
505void BookmarkManager::renameBookmark(const QUrl &documentUrl, const QString &newName)
506{
507 if (!documentUrl.isValid()) {
508 return;
509 }
510
511 const QUrl referurl = mostCanonicalUrl(documentUrl);
512
513 KBookmarkGroup thebg;
514 QHash<QUrl, QString>::iterator it = d->bookmarkFind(referurl, false, &thebg);
515 Q_ASSERT(it != d->knownFiles.end());
516 if (it == d->knownFiles.end()) {
517 return;
518 }
519
520 thebg.setFullText(newName);
521 d->manager.emitChanged(thebg);
522}
523
525{
526 KBookmarkGroup thebg;
527 QHash<QUrl, QString>::iterator it = d->bookmarkFind(mostCanonicalUrl(documentUrl), false, &thebg);
528 Q_ASSERT(it != d->knownFiles.end());
529
530 return thebg.fullText();
531}
532
533int BookmarkManager::removeBookmark(const QUrl &documentUrl, const KBookmark &bm)
534{
535 if (!documentUrl.isValid() || bm.isNull() || bm.isGroup() || bm.isSeparator()) {
536 return -1;
537 }
538
540 if (!vp.isValid()) {
541 return -1;
542 }
543
544 const QUrl referurl = mostCanonicalUrl(documentUrl);
545
546 KBookmarkGroup thebg;
547 QHash<QUrl, QString>::iterator it = d->bookmarkFind(referurl, false, &thebg);
548 if (it == d->knownFiles.end()) {
549 return -1;
550 }
551
552 thebg.deleteBookmark(bm);
553
554 if (referurl == d->document->m_url) {
555 d->urlBookmarks[vp.pageNumber]--;
556 foreachObserver(notifyPageChanged(vp.pageNumber, DocumentObserver::Bookmark));
557 }
558 d->manager.emitChanged(thebg);
559
560 return vp.pageNumber;
561}
562
563void BookmarkManager::removeBookmarks(const QUrl &documentUrl, const KBookmark::List &list)
564{
565 if (!documentUrl.isValid() || list.isEmpty()) {
566 return;
567 }
568
569 const QUrl referurl = mostCanonicalUrl(documentUrl);
570
571 KBookmarkGroup thebg;
572 QHash<QUrl, QString>::iterator it = d->bookmarkFind(referurl, false, &thebg);
573 if (it == d->knownFiles.end()) {
574 return;
575 }
576
577 const QHash<int, int> oldUrlBookmarks = d->urlBookmarks;
578 bool deletedAny = false;
579 for (const KBookmark &bm : list) {
580 if (bm.parentGroup() == thebg) {
581 thebg.deleteBookmark(bm);
582 deletedAny = true;
583
585 if (referurl == d->document->m_url) {
586 d->urlBookmarks[vp.pageNumber]--;
587 }
588 }
589 }
590
591 if (referurl == d->document->m_url) {
592 for (int i = 0; i < qMax(oldUrlBookmarks.size(), d->urlBookmarks.size()); i++) {
593 bool oldContains = oldUrlBookmarks.contains(i) && oldUrlBookmarks[i] > 0;
594 bool curContains = d->urlBookmarks.contains(i) && d->urlBookmarks[i] > 0;
595
596 if (oldContains != curContains) {
597 foreachObserver(notifyPageChanged(i, DocumentObserver::Bookmark));
598 } else if (oldContains && oldUrlBookmarks[i] != d->urlBookmarks[i]) {
599 foreachObserver(notifyPageChanged(i, DocumentObserver::Bookmark));
600 }
601 }
602 }
603 if (deletedAny) {
604 d->manager.emitChanged(thebg);
605 }
606}
607
609{
610 const QUrl url = mostCanonicalUrl(documentUrl);
612 KBookmarkGroup group = d->manager.root();
613 for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
614 if (!bm.isGroup() || urlForGroup(bm) != url) {
615 continue;
616 }
617
618 KBookmarkGroup group = bm.toGroup();
619 for (KBookmark b = group.first(); !b.isNull(); b = group.next(b)) {
620 if (b.isSeparator() || b.isGroup()) {
621 continue;
622 }
623
624 ret.append(new OkularBookmarkAction(DocumentViewport(b.url().fragment(QUrl::FullyDecoded)), b, d, nullptr));
625 }
626 break;
627 }
628 std::sort(ret.begin(), ret.end(), okularBookmarkActionLessThan);
629 return ret;
630}
631
632void BookmarkManager::setUrl(const QUrl &url)
633{
634 d->url = mostCanonicalUrl(url);
635 d->urlBookmarks.clear();
636 KBookmarkGroup thebg;
637 QHash<QUrl, QString>::iterator it = d->bookmarkFind(d->url, false, &thebg);
638 if (it != d->knownFiles.end()) {
639 for (KBookmark bm = thebg.first(); !bm.isNull(); bm = thebg.next(bm)) {
640 if (bm.isSeparator() || bm.isGroup()) {
641 continue;
642 }
643
645 if (!vp.isValid()) {
646 continue;
647 }
648
649 d->urlBookmarks[vp.pageNumber]++;
650 }
651 }
652}
653
654bool BookmarkManager::setPageBookmark(int page)
655{
656 KBookmarkGroup thebg;
657 QHash<QUrl, QString>::iterator it = d->bookmarkFind(d->url, true, &thebg);
658 Q_ASSERT(it != d->knownFiles.end());
659
660 bool found = false;
661 bool added = false;
662 for (KBookmark bm = thebg.first(); !found && !bm.isNull(); bm = thebg.next(bm)) {
663 if (bm.isSeparator() || bm.isGroup()) {
664 continue;
665 }
666
668 if (vp.isValid() && vp.pageNumber == page) {
669 found = true;
670 }
671 }
672 if (!found) {
673 d->urlBookmarks[page]++;
675 vp.pageNumber = page;
676 QUrl newurl = d->url;
678 thebg.addBookmark(QLatin1String("#") + QString::number(vp.pageNumber + 1), newurl, QString());
679 added = true;
680 d->manager.emitChanged(thebg);
681 }
682 return added;
683}
684
685bool BookmarkManager::removePageBookmark(int page)
686{
687 KBookmarkGroup thebg;
688 QHash<QUrl, QString>::iterator it = d->bookmarkFind(d->url, false, &thebg);
689 if (it == d->knownFiles.end()) {
690 return false;
691 }
692
693 bool found = false;
694 for (KBookmark bm = thebg.first(); !found && !bm.isNull(); bm = thebg.next(bm)) {
695 if (bm.isSeparator() || bm.isGroup()) {
696 continue;
697 }
698
700 if (vp.isValid() && vp.pageNumber == page) {
701 found = true;
702 thebg.deleteBookmark(bm);
703 d->urlBookmarks[page]--;
704 d->manager.emitChanged(thebg);
705 }
706 }
707 return found;
708}
709
711{
712 return d->urlBookmarks.contains(page) && d->urlBookmarks[page] > 0;
713}
714
716{
717 KBookmark bm = bookmark(viewport);
718
719 return !bm.isNull();
720}
721
723{
724 KBookmark::List bmarks = bookmarks();
725 std::sort(bmarks.begin(), bmarks.end(), bookmarkLessThan);
726
728 for (const KBookmark &bm : std::as_const(bmarks)) {
730 if (viewport < vp) {
731 bookmark = bm;
732 break;
733 }
734 }
735
736 return bookmark;
737}
738
740{
741 KBookmark::List bmarks = bookmarks();
742 std::sort(bmarks.begin(), bmarks.end(), bookmarkLessThan);
743
745 for (KBookmark::List::const_iterator it = bmarks.constEnd(); it != bmarks.constBegin(); --it) {
746 KBookmark bm = *(it - 1);
748 if (vp < viewport) {
749 bookmark = bm;
750 break;
751 }
752 }
753
754 return bookmark;
755}
756
757#undef foreachObserver
758#undef foreachObserverD
759
760#include "bookmarkmanager.moc"
761
762/* kate: replace-tabs on; indent-width 4; */
KBookmark next(const KBookmark &current) const
KBookmark first() const
void deleteBookmark(const KBookmark &bk)
KBookmark addBookmark(const KBookmark &bm)
KBookmarkGroup createNewFolder(const QString &text)
void changed(const QString &groupAddress)
KBookmarkGroup parentGroup() const
bool isNull() const
bool isGroup() const
QString fullText() const
KBookmarkGroup toGroup() const
bool isSeparator() const
void setUrl(const QUrl &url)
void setFullText(const QString &fullText)
QString address() const
QUrl url() const
Bookmarks manager utility.
void renameBookmark(KBookmark *bm, const QString &newName)
Returns the bookmark given bookmark of the document.
KBookmark bookmark(int page) const
Returns the bookmark for the given page of the document.
KBookmark previousBookmark(const DocumentViewport &viewport) const
Given a viewport, returns the previous bookmark.
void removeBookmark(int page)
Remove a bookmark for the given page.
KBookmark::List bookmarks() const
Returns the list of bookmarks for document.
void saved()
This signal is emitted whenever bookmarks have been saved.
KBookmark nextBookmark(const DocumentViewport &viewport) const
Given a viewport, returns the next bookmark.
void removeBookmarks(const QUrl &documentUrl, const KBookmark::List &list)
Removes the bookmarks in list for the documentUrl specified.
bool isBookmarked(int page) const
Returns whether the given page is bookmarked.
QList< QUrl > files() const
Returns the list of documents with bookmarks.
QString titleForUrl(const QUrl &documentUrl) const
Returns title for the documentUrl.
QList< QAction * > actionsForUrl(const QUrl &documentUrl) const
Returns a list of actions for the bookmarks of the specified url.
void addBookmark(int page)
Adds a bookmark for the given page.
void save() const
Forces to save the list of bookmarks.
@ Bookmark
Bookmarks has been changed.
Definition observer.h:46
A view on the document.
Definition document.h:1350
int pageNumber
The number of the page nearest the center of the viewport.
Definition document.h:1381
struct Okular::DocumentViewport::@0 rePos
If 'rePos.enabled == true' then this structure contains the viewport center or top left depending on ...
bool isValid() const
Returns whether the viewport is valid.
QString toString() const
Returns the viewport as xml description.
global.h
Definition action.h:17
void setText(const QString &text)
void clear()
bool contains(const Key &key) const const
qsizetype size() const const
void append(QList< T > &&value)
iterator begin()
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator end()
bool isEmpty() const const
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
QObject * parent() const const
QVariant property(const char *name) const const
bool setProperty(const char *name, QVariant &&value)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString number(double n, char format, int precision)
typedef KeyboardModifiers
typedef MouseButtons
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
FullyDecoded
QString fragment(ComponentFormattingOptions options) const const
QUrl fromLocalFile(const QString &localFile)
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
bool isLocalFile() const const
bool isValid() const const
void setFragment(const QString &fragment, ParsingMode mode)
QString toDisplayString(FormattingOptions options) const const
QString toLocalFile() const const
QString url(FormattingOptions options) const const
int toInt(bool *ok) const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:35 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.