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

KDE's Doxygen guidelines are available online.