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

KDE's Doxygen guidelines are available online.