Messagelib

item.cpp
1/******************************************************************************
2 *
3 * SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 *
7 *******************************************************************************/
8
9#include "core/item.h"
10#include "core/item_p.h"
11#include "core/manager.h"
12#include "core/model.h"
13
14#include <KFormat>
15#include <KMime/DateFormatter>
16
17#include <KLocalizedString>
18
19using namespace MessageList::Core;
20
21Item::Item(Type type)
22 : d_ptr(new ItemPrivate(this))
23{
24 d_ptr->mType = type;
25}
26
27Item::Item(Item::Type type, ItemPrivate *dd)
28 : d_ptr(dd)
29{
30 d_ptr->mType = type;
31}
32
34{
36
37 if (d_ptr->mParent) {
38 d_ptr->mParent->d_ptr->childItemDead(this);
39 }
40
41 delete d_ptr;
42}
43
45{
46 Q_ASSERT(d_ptr->mChildItems);
47
48 stats.mTotalChildCount += d_ptr->mChildItems->count();
49 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
50 if (!child->status().isRead()) {
51 stats.mUnreadChildCount++;
52 }
53 if (child->d_ptr->mChildItems) {
54 child->childItemStats(stats);
55 }
56 }
57}
58
60{
61 return d_ptr->mChildItems;
62}
63
64Item *Item::childItem(int idx) const
65{
66 if (idx < 0) {
67 return nullptr;
68 }
69 if (!d_ptr->mChildItems) {
70 return nullptr;
71 }
72 if (d_ptr->mChildItems->count() <= idx) {
73 return nullptr;
74 }
75 return d_ptr->mChildItems->at(idx);
76}
77
79{
80 return d_ptr->mChildItems ? (d_ptr->mChildItems->count() > 0 ? d_ptr->mChildItems->at(0) : nullptr) : nullptr;
81}
82
84{
85 Q_ASSERT(d_ptr->mChildItems);
86
87 int idx = indexOfChildItem(child);
88 Q_ASSERT(idx >= 0);
89
90 idx++;
91
92 if (idx < d_ptr->mChildItems->count()) {
93 return d_ptr->mChildItems->at(idx);
94 }
95
96 if (!d_ptr->mParent) {
97 return nullptr;
98 }
99
100 return d_ptr->mParent->itemBelowChild(this);
101}
102
104{
105 if (d_ptr->mChildItems) {
106 if (!d_ptr->mChildItems->isEmpty()) {
107 return d_ptr->mChildItems->at(0);
108 }
109 }
110
111 if (!d_ptr->mParent) {
112 return nullptr;
113 }
114
115 return d_ptr->mParent->itemBelowChild(this);
116}
117
119{
120 if (d_ptr->mChildItems) {
121 if (!d_ptr->mChildItems->isEmpty()) {
122 return d_ptr->mChildItems->at(d_ptr->mChildItems->count() - 1)->deepestItem();
123 }
124 }
125
126 return this;
127}
128
130{
131 if (d_ptr->mChildItems) {
132 int idx = indexOfChildItem(child);
133 Q_ASSERT(idx >= 0);
134 idx--;
135
136 if (idx >= 0) {
137 return d_ptr->mChildItems->at(idx);
138 }
139 }
140
141 return this;
142}
143
145{
146 if (!d_ptr->mParent) {
147 return nullptr;
148 }
149
150 Item *siblingAbove = d_ptr->mParent->itemAboveChild(this);
151 if (siblingAbove && siblingAbove != this && siblingAbove != d_ptr->mParent && siblingAbove->childItemCount() > 0) {
152 return siblingAbove->deepestItem();
153 }
154
155 return d_ptr->mParent->itemAboveChild(this);
156}
157
159{
160 return d_ptr->mChildItems ? d_ptr->mChildItems->count() : 0;
161}
162
164{
165 return childItemCount() > 0;
166}
167
169{
170 if (!d_ptr->mChildItems) {
171 return -1;
172 }
173 int idx = child->d_ptr->mThisItemIndexGuess;
174 if (idx < d_ptr->mChildItems->count() && d_ptr->mChildItems->at(idx) == child) {
175 return idx; // good guess
176 }
177
178 // We had a guess but it's out-of-date. Let's use the old guess as our
179 // starting point and search in both directions from it. It's more likely we
180 // will find the new position by going from the old guess rather than scanning
181 // the list from the beginning. The worst case scenario is equal to not having
182 // any guess at all.
183 if (idx > 0 && idx < d_ptr->mChildItems->count()) {
184 const auto begin = d_ptr->mChildItems->cbegin();
185 const auto end = d_ptr->mChildItems->cend();
186 auto fwdIt = begin + idx;
187 auto bwdIt = fwdIt;
188
189 idx = -1; // invalidate idx so it's -1 in case we fail to find the item
190 while (fwdIt != end || bwdIt != end) {
191 if (fwdIt != end) {
192 if (++fwdIt != end && (*fwdIt) == child) {
193 idx = std::distance(begin, fwdIt);
194 break;
195 }
196 }
197 if (bwdIt != end) { // sic!
198 Q_ASSERT(bwdIt != begin);
199 if ((*--bwdIt) == child) {
200 idx = std::distance(begin, bwdIt);
201 break;
202 }
203 if (bwdIt == begin) {
204 // invalidate the iterator if we just checked the first item
205 bwdIt = end;
206 }
207 }
208 }
209 } else {
210 idx = d_ptr->mChildItems->indexOf(child);
211 }
212
213 if (idx >= 0) {
214 Q_ASSERT(d_ptr->mChildItems->at(idx) == child); // make sure the above algorithm works
215 child->d_ptr->mThisItemIndexGuess = idx;
216 }
217 return idx;
218}
219
220void Item::setIndexGuess(int index)
221{
222 d_ptr->mThisItemIndexGuess = index;
223}
224
226{
227 Q_ASSERT(d_ptr->mType != InvisibleRoot);
228
229 if (!d_ptr->mParent) {
230 return this;
231 }
232
233 if (d_ptr->mParent->type() == InvisibleRoot) {
234 return this;
235 }
236
237 return d_ptr->mParent->topmostNonRoot();
238}
239
240static inline void append_string(QString &buffer, const QString &append)
241{
242 if (!buffer.isEmpty()) {
243 buffer += QLatin1StringView(", ");
244 }
245 buffer += append;
246}
247
249{
250 QString ret;
251 if (status().isRead()) {
252 append_string(ret, i18nc("Status of an item", "Read"));
253 } else {
254 append_string(ret, i18nc("Status of an item", "Unread"));
255 }
256
257 if (status().hasAttachment()) {
258 append_string(ret, i18nc("Status of an item", "Has Attachment"));
259 }
260
261 if (status().isToAct()) {
262 append_string(ret, i18nc("Status of an item", "Action Item"));
263 }
264
265 if (status().isReplied()) {
266 append_string(ret, i18nc("Status of an item", "Replied"));
267 }
268
269 if (status().isForwarded()) {
270 append_string(ret, i18nc("Status of an item", "Forwarded"));
271 }
272
273 if (status().isSent()) {
274 append_string(ret, i18nc("Status of an item", "Sent"));
275 }
276
277 if (status().isImportant()) {
278 append_string(ret, i18nc("Status of an item", "Important"));
279 }
280
281 if (status().isSpam()) {
282 append_string(ret, i18nc("Status of an item", "Spam"));
283 }
284
285 if (status().isHam()) {
286 append_string(ret, i18nc("Status of an item", "Ham"));
287 }
288
289 if (status().isWatched()) {
290 append_string(ret, i18nc("Status of an item", "Watched"));
291 }
292
293 if (status().isIgnored()) {
294 append_string(ret, i18nc("Status of an item", "Ignored"));
295 }
296
297 return ret;
298}
299
301{
302 KFormat format;
303 return format.formatByteSize(size());
304}
305
307{
308 if (static_cast<uint>(date()) == static_cast<uint>(-1)) {
309 return Manager::instance()->cachedLocalizedUnknownText();
310 } else {
311 return Manager::instance()->dateFormatter()->dateString(QDateTime::fromSecsSinceEpoch(date()));
312 }
313}
314
316{
317 if (static_cast<uint>(maxDate()) == static_cast<uint>(-1)) {
318 return Manager::instance()->cachedLocalizedUnknownText();
319 } else {
320 return Manager::instance()->dateFormatter()->dateString(QDateTime::fromSecsSinceEpoch(maxDate()));
321 }
322}
323
325{
326 time_t newMaxDate = d_ptr->mDate;
327
328 if (d_ptr->mChildItems) {
329 for (auto child : std::as_const(*d_ptr->mChildItems)) {
330 if (child->d_ptr->mMaxDate > newMaxDate) {
331 newMaxDate = child->d_ptr->mMaxDate;
332 }
333 }
334 }
335
336 if (newMaxDate != d_ptr->mMaxDate) {
337 setMaxDate(newMaxDate);
338 return true;
339 }
340 return false;
341}
342
344{
345 return d_ptr->mType;
346}
347
349{
350 return d_ptr->mInitialExpandStatus;
351}
352
354{
355 d_ptr->mInitialExpandStatus = initialExpandStatus;
356}
357
359{
360 return d_ptr->mIsViewable;
361}
362
363bool Item::hasAncestor(const Item *it) const
364{
365 return d_ptr->mParent ? (d_ptr->mParent == it ? true : d_ptr->mParent->hasAncestor(it)) : false;
366}
367
368void Item::setViewable(Model *model, bool bViewable)
369{
370 if (d_ptr->mIsViewable == bViewable) {
371 return;
372 }
373
374 if (!d_ptr->mChildItems) {
375 d_ptr->mIsViewable = bViewable;
376 return;
377 }
378
379 if (d_ptr->mChildItems->isEmpty()) {
380 d_ptr->mIsViewable = bViewable;
381 return;
382 }
383
384 if (bViewable) {
385 if (model) {
386 // fake having no children, for a second
387 QList<Item *> *tmp = d_ptr->mChildItems;
388 d_ptr->mChildItems = nullptr;
389 // qDebug("BEGIN INSERT ROWS FOR PARENT %x: from %d to %d, (will) have %d children",this,0,tmp->count()-1,tmp->count());
390 model->beginInsertRows(model->index(this, 0), 0, tmp->count() - 1);
391 d_ptr->mChildItems = tmp;
392 d_ptr->mIsViewable = true;
393 model->endInsertRows();
394 } else {
395 d_ptr->mIsViewable = true;
396 }
397
398 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
399 child->setViewable(model, bViewable);
400 }
401 } else {
402 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
403 child->setViewable(model, bViewable);
404 }
405
406 // It seems that we can avoid removing child items here since the parent has been removed: this is a hack tough
407 // and should check if Qt4 still supports it in the next (hopefully largely fixed) release
408
409 if (model) {
410 // fake having no children, for a second
411 model->beginRemoveRows(model->index(this, 0), 0, d_ptr->mChildItems->count() - 1);
412 QList<Item *> *tmp = d_ptr->mChildItems;
413 d_ptr->mChildItems = nullptr;
414 d_ptr->mIsViewable = false;
415 model->endRemoveRows();
416 d_ptr->mChildItems = tmp;
417 } else {
418 d_ptr->mIsViewable = false;
419 }
420 }
421}
422
424{
425 if (!d_ptr->mChildItems) {
426 return;
427 }
428
429 while (!d_ptr->mChildItems->isEmpty()) {
430 delete d_ptr->mChildItems->first(); // this will call childDead() which will remove the child from the list
431 }
432
433 delete d_ptr->mChildItems;
434 d_ptr->mChildItems = nullptr;
435}
436
438{
439 return d_ptr->mParent;
440}
441
442void Item::setParent(Item *pParent)
443{
444 d_ptr->mParent = pParent;
445}
446
448{
449 return d_ptr->mStatus;
450}
451
453{
454 d_ptr->mStatus = status;
455}
456
457size_t Item::size() const
458{
459 return d_ptr->mSize;
460}
461
462void Item::setSize(size_t size)
463{
464 d_ptr->mSize = size;
465}
466
467time_t Item::date() const
468{
469 return d_ptr->mDate;
470}
471
472void Item::setDate(time_t date)
473{
474 d_ptr->mDate = date;
475}
476
477time_t Item::maxDate() const
478{
479 return d_ptr->mMaxDate;
480}
481
482void Item::setMaxDate(time_t date)
483{
484 d_ptr->mMaxDate = date;
485}
486
487const QString &Item::sender() const
488{
489 return d_ptr->mSender;
490}
491
492void Item::setSender(const QString &sender)
493{
494 d_ptr->mSender = sender;
495}
496
498{
499 return sender();
500}
501
503{
504 return d_ptr->mReceiver;
505}
506
507void Item::setReceiver(const QString &receiver)
508{
509 d_ptr->mReceiver = receiver;
510}
511
513{
514 return receiver();
515}
516
518{
519 return d_ptr->mUseReceiver ? d_ptr->mReceiver : d_ptr->mSender;
520}
521
526
528{
529 return d_ptr->mUseReceiver;
530}
531
532const QString &Item::subject() const
533{
534 return d_ptr->mSubject;
535}
536
537void Item::setSubject(const QString &subject)
538{
539 d_ptr->mSubject = subject;
540}
541
542const QString &Item::folder() const
543{
544 return d_ptr->mFolder;
545}
546
547void Item::setFolder(const QString &folder)
548{
549 d_ptr->mFolder = folder;
550}
551
552void MessageList::Core::Item::initialSetup(time_t date, size_t size, const QString &sender, const QString &receiver, bool useReceiver)
553{
554 d_ptr->mDate = date;
555 d_ptr->mMaxDate = date;
556 d_ptr->mSize = size;
557 d_ptr->mSender = sender;
558 d_ptr->mReceiver = receiver;
559 d_ptr->mUseReceiver = useReceiver;
560}
561
562void MessageList::Core::Item::setItemId(qint64 id)
563{
564 d_ptr->mItemId = id;
565}
566
567qint64 MessageList::Core::Item::itemId() const
568{
569 return d_ptr->mItemId;
570}
571
572void Item::setParentCollectionId(qint64 id)
573{
574 d_ptr->mParentCollectionId = id;
575}
576
577qint64 Item::parentCollectionId() const
578{
579 return d_ptr->mParentCollectionId;
580}
581
583{
584 d_ptr->mSubject = subject;
585 d_ptr->mStatus = status;
586}
587
588// FIXME: Try to "cache item insertions" and call beginInsertRows() and endInsertRows() in a chunked fashion...
589
591{
592 if (!d_ptr->mChildItems) {
593 d_ptr->mChildItems = new QList<Item *>();
594 }
595 d_ptr->mChildItems->append(child);
596}
597
599{
600 if (!d_ptr->mChildItems) {
601 d_ptr->mChildItems = new QList<Item *>();
602 }
603 const int idx = d_ptr->mChildItems->count();
604 if (d_ptr->mIsViewable) {
605 if (model) {
606 model->beginInsertRows(model->index(this, 0), idx, idx); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING
607 }
608 d_ptr->mChildItems->append(child);
609 child->setIndexGuess(idx);
610 if (model) {
611 model->endInsertRows(); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING
612 }
613 child->setViewable(model, true);
614 } else {
615 d_ptr->mChildItems->append(child);
616 child->setIndexGuess(idx);
617 }
618 return idx;
619}
620
621void Item::dump(const QString &prefix)
622{
623 QString out = QStringLiteral("%1 %x VIEWABLE:%2").arg(prefix, d_ptr->mIsViewable ? QStringLiteral("yes") : QStringLiteral("no"));
624 qDebug(out.toUtf8().data(), this);
625
626 QString nPrefix(prefix);
627 nPrefix += QLatin1StringView(" ");
628
629 if (!d_ptr->mChildItems) {
630 return;
631 }
632
633 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
634 child->dump(nPrefix);
635 }
636}
637
638void Item::takeChildItem(Model *model, Item *child)
639{
640 if (!d_ptr->mChildItems) {
641 return; // Ugh... not our child ?
642 }
643
644 if (!d_ptr->mIsViewable) {
645 // qDebug("TAKING NON VIEWABLE CHILD ITEM %x",child);
646 // We can highly optimize this case
647 d_ptr->mChildItems->removeOne(child);
648#if 0
649 // This *could* be done, but we optimize and avoid it.
650 if (d->mChildItems->isEmpty()) {
651 delete d->mChildItems;
652 d->mChildItems = 0;
653 }
654#endif
655 child->setParent(nullptr);
656 return;
657 }
658
659 const int idx = indexOfChildItem(child);
660 if (idx < 0) {
661 return; // Aaargh... not our child ?
662 }
663
664 child->setViewable(model, false);
665 if (model) {
666 model->beginRemoveRows(model->index(this, 0), idx, idx);
667 }
668 child->setParent(nullptr);
669 d_ptr->mChildItems->removeAt(idx);
670 if (model) {
671 model->endRemoveRows();
672 }
673
674#if 0
675 // This *could* be done, but we optimize and avoid it.
676 if (d->mChildItems->isEmpty()) {
677 delete d->mChildItems;
678 d->mChildItems = 0;
679 }
680#endif
681}
682
683void ItemPrivate::childItemDead(Item *child)
684{
685 // mChildItems MUST be non zero here, if it's not then it's a bug in THIS FILE
686 mChildItems->removeOne(child); // since we always have ONE (if we not, it's a bug)
687}
QString formatByteSize(double size, int precision=1, KFormat::BinaryUnitDialect dialect=KFormat::DefaultBinaryDialect, KFormat::BinarySizeUnits units=KFormat::DefaultBinaryUnits) const
A structure used with MessageList::Item::childItemStats().
Definition item.h:173
A single item of the MessageList tree managed by MessageList::Model.
Definition item.h:36
Item * firstChildItem() const
Returns the first child item, if any.
Definition item.cpp:78
Item * topmostNonRoot()
Returns the topmost parent item that is not a Root item (that is, is a Message or GroupHeader).
Definition item.cpp:225
bool recomputeMaxDate()
Recompute the maximum date from the current children list.
Definition item.cpp:324
const QString & senderOrReceiver() const
Returns the sender or the receiver, depending on the underlying StorageModel settings.
Definition item.cpp:517
virtual ~Item()
Destroys the Item.
Definition item.cpp:33
const QString & receiver() const
Returns the receiver associated to this item.
Definition item.cpp:502
Item * childItem(int idx) const
Returns the child item at position idx or 0 if idx is out of the allowable range.
Definition item.cpp:64
QString formattedMaxDate() const
A string with a text rappresentation of maxDate() obtained via Manager.
Definition item.cpp:315
QString formattedDate() const
A string with a text rappresentation of date() obtained via Manager.
Definition item.cpp:306
size_t size() const
Returns the size of this item (size of the Message, mainly)
Definition item.cpp:457
InitialExpandStatus
Specifies the initial expand status for the item that should be applied when it's attached to the vie...
Definition item.h:55
void setSize(size_t size)
Sets the size of this item (size of the Message, mainly)
Definition item.cpp:462
void rawAppendChildItem(Item *child)
Appends a child item without inserting it via the model.
Definition item.cpp:590
QString statusDescription() const
Returns a string describing the status e.g: "Read, Forwarded, Important".
Definition item.cpp:248
int appendChildItem(Model *model, Item *child)
Appends an Item to this item's child list.
Definition item.cpp:598
bool useReceiver() const
Returns whether sender or receiver is supposed to be displayed.
Definition item.cpp:527
const Akonadi::MessageStatus & status() const
Returns the status associated to this Item.
Definition item.cpp:447
void setReceiver(const QString &receiver)
Sets the sender associated to this item.
Definition item.cpp:507
InitialExpandStatus initialExpandStatus() const
The initial expand status we have to honor when attaching to the viewable root.
Definition item.cpp:348
void dump(const QString &prefix)
Debug helper.
Definition item.cpp:621
void initialSetup(time_t date, size_t size, const QString &sender, const QString &receiver, bool useReceiver)
This is meant to be called right after the constructor.
Definition item.cpp:552
bool hasAncestor(const Item *it) const
Return true if Item pointed by it is an ancestor of this item (that is, if it is its parent,...
Definition item.cpp:363
void setViewable(Model *model, bool bViewable)
Makes this item viewable, that is, notifies its existence to any listener attached to the "rowsInsert...
Definition item.cpp:368
time_t date() const
Returns the date of this item.
Definition item.cpp:467
Item * itemAboveChild(Item *child)
Returns the item that is visually above the specified child if this item.
Definition item.cpp:129
Item * itemAbove()
Returns the item that is visually above this item in the tree.
Definition item.cpp:144
void killAllChildItems()
Kills all the child items without emitting any signal, recursively.
Definition item.cpp:423
time_t maxDate() const
Returns the maximum date in the subtree originating from this item.
Definition item.cpp:477
void setMaxDate(time_t date)
Sets the maximum date in the subtree originating from this item.
Definition item.cpp:482
void childItemStats(ChildItemStats &stats) const
Gathers statistics about child items.
Definition item.cpp:44
Type type() const
Returns the type of this item.
Definition item.cpp:343
const QString & folder() const
Returns the folder associated to this Item.
Definition item.cpp:542
const QString & sender() const
Returns the sender associated to this item.
Definition item.cpp:487
QString displayReceiver() const
Display receiver.
Definition item.cpp:512
void setStatus(Akonadi::MessageStatus status)
Sets the status associated to this Item.
Definition item.cpp:452
Item * itemBelowChild(Item *child)
Returns the item that is visually below the specified child if this item.
Definition item.cpp:83
void takeChildItem(Model *model, Item *child)
Removes a child from this item's child list without deleting it.
Definition item.cpp:638
void setSender(const QString &sender)
Sets the sender associated to this item.
Definition item.cpp:492
void setIndexGuess(int index)
Sets the cached guess for the index of this item in the parent's child list.
Definition item.cpp:220
QString displaySenderOrReceiver() const
Display sender or receiver.
Definition item.cpp:522
void setSubject(const QString &subject)
Sets the subject associated to this Item.
Definition item.cpp:537
Item * parent() const
Returns the parent Item in the tree, or 0 if this item isn't attached to the tree.
Definition item.cpp:437
Item * deepestItem()
Returns the deepest item in the subtree originating at this item.
Definition item.cpp:118
void setParent(Item *pParent)
Sets the parent for this item.
Definition item.cpp:442
void setDate(time_t date)
Sets the date of this item.
Definition item.cpp:472
void setFolder(const QString &folder)
Sets the folder associated to this Item.
Definition item.cpp:547
void setInitialExpandStatus(InitialExpandStatus initialExpandStatus)
Set the initial expand status we have to honor when attaching to the viewable root.
Definition item.cpp:353
bool hasChildren() const
Convenience function that returns true if this item has children.
Definition item.cpp:163
Type
The type of the Item.
Definition item.h:44
@ InvisibleRoot
This item is just Item and it's the only InvisibleRoot per Model.
Definition item.h:47
QString formattedSize() const
A string with a text rappresentation of size().
Definition item.cpp:300
Item * itemBelow()
Returns the item that is visually below this item in the tree.
Definition item.cpp:103
int indexOfChildItem(Item *item) const
Returns the actual index of the child Item item or -1 if item is not a child of this Item.
Definition item.cpp:168
void setSubjectAndStatus(const QString &subject, Akonadi::MessageStatus status)
This is meant to be called right after the constructor for MessageItem objects.
Definition item.cpp:582
int childItemCount() const
Returns the number of children of this Item.
Definition item.cpp:158
QList< Item * > * childItems() const
Return the list of child items.
Definition item.cpp:59
const QString & subject() const
Returns the subject associated to this Item.
Definition item.cpp:532
Item(Type type)
Creates an Item.
Definition item.cpp:21
QString displaySender() const
Display sender.
Definition item.cpp:497
bool isViewable() const
Is this item attached to the viewable root ?
Definition item.cpp:358
This class manages the huge tree of displayable objects: GroupHeaderItems and MessageItems.
Definition model.h:54
Q_SCRIPTABLE CaptureState status()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
The implementation independent part of the MessageList library.
Definition aggregation.h:22
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
char * data()
QDateTime fromSecsSinceEpoch(qint64 secs)
qsizetype count() const const
QString arg(Args &&... args) const const
bool isEmpty() const const
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:12:43 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.