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 if (status().isQueued()) {
296 append_string(ret, i18nc("Status of an item", "Queued"));
297 }
298
299 return ret;
300}
301
303{
304 KFormat format;
305 return format.formatByteSize(size());
306}
307
309{
310 if (static_cast<uint>(date()) == static_cast<uint>(-1)) {
311 return Manager::instance()->cachedLocalizedUnknownText();
312 } else {
313 return Manager::instance()->dateFormatter()->dateString(QDateTime::fromSecsSinceEpoch(date()));
314 }
315}
316
318{
319 if (static_cast<uint>(maxDate()) == static_cast<uint>(-1)) {
320 return Manager::instance()->cachedLocalizedUnknownText();
321 } else {
322 return Manager::instance()->dateFormatter()->dateString(QDateTime::fromSecsSinceEpoch(maxDate()));
323 }
324}
325
327{
328 time_t newMaxDate = d_ptr->mDate;
329
330 if (d_ptr->mChildItems) {
331 for (auto child : std::as_const(*d_ptr->mChildItems)) {
332 if (child->d_ptr->mMaxDate > newMaxDate) {
333 newMaxDate = child->d_ptr->mMaxDate;
334 }
335 }
336 }
337
338 if (newMaxDate != d_ptr->mMaxDate) {
339 setMaxDate(newMaxDate);
340 return true;
341 }
342 return false;
343}
344
346{
347 return d_ptr->mType;
348}
349
351{
352 return d_ptr->mInitialExpandStatus;
353}
354
356{
357 d_ptr->mInitialExpandStatus = initialExpandStatus;
358}
359
361{
362 return d_ptr->mIsViewable;
363}
364
365bool Item::hasAncestor(const Item *it) const
366{
367 return d_ptr->mParent ? (d_ptr->mParent == it ? true : d_ptr->mParent->hasAncestor(it)) : false;
368}
369
370void Item::setViewable(Model *model, bool bViewable)
371{
372 if (d_ptr->mIsViewable == bViewable) {
373 return;
374 }
375
376 if (!d_ptr->mChildItems) {
377 d_ptr->mIsViewable = bViewable;
378 return;
379 }
380
381 if (d_ptr->mChildItems->isEmpty()) {
382 d_ptr->mIsViewable = bViewable;
383 return;
384 }
385
386 if (bViewable) {
387 if (model) {
388 // fake having no children, for a second
389 QList<Item *> *tmp = d_ptr->mChildItems;
390 d_ptr->mChildItems = nullptr;
391 // qDebug("BEGIN INSERT ROWS FOR PARENT %x: from %d to %d, (will) have %d children",this,0,tmp->count()-1,tmp->count());
392 model->beginInsertRows(model->index(this, 0), 0, tmp->count() - 1);
393 d_ptr->mChildItems = tmp;
394 d_ptr->mIsViewable = true;
395 model->endInsertRows();
396 } else {
397 d_ptr->mIsViewable = true;
398 }
399
400 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
401 child->setViewable(model, bViewable);
402 }
403 } else {
404 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
405 child->setViewable(model, bViewable);
406 }
407
408 // It seems that we can avoid removing child items here since the parent has been removed: this is a hack tough
409 // and should check if Qt4 still supports it in the next (hopefully largely fixed) release
410
411 if (model) {
412 // fake having no children, for a second
413 model->beginRemoveRows(model->index(this, 0), 0, d_ptr->mChildItems->count() - 1);
414 QList<Item *> *tmp = d_ptr->mChildItems;
415 d_ptr->mChildItems = nullptr;
416 d_ptr->mIsViewable = false;
417 model->endRemoveRows();
418 d_ptr->mChildItems = tmp;
419 } else {
420 d_ptr->mIsViewable = false;
421 }
422 }
423}
424
426{
427 if (!d_ptr->mChildItems) {
428 return;
429 }
430
431 while (!d_ptr->mChildItems->isEmpty()) {
432 delete d_ptr->mChildItems->first(); // this will call childDead() which will remove the child from the list
433 }
434
435 delete d_ptr->mChildItems;
436 d_ptr->mChildItems = nullptr;
437}
438
440{
441 return d_ptr->mParent;
442}
443
444void Item::setParent(Item *pParent)
445{
446 d_ptr->mParent = pParent;
447}
448
450{
451 return d_ptr->mStatus;
452}
453
455{
456 d_ptr->mStatus = status;
457}
458
459size_t Item::size() const
460{
461 return d_ptr->mSize;
462}
463
464void Item::setSize(size_t size)
465{
466 d_ptr->mSize = size;
467}
468
469time_t Item::date() const
470{
471 return d_ptr->mDate;
472}
473
474void Item::setDate(time_t date)
475{
476 d_ptr->mDate = date;
477}
478
479time_t Item::maxDate() const
480{
481 return d_ptr->mMaxDate;
482}
483
484void Item::setMaxDate(time_t date)
485{
486 d_ptr->mMaxDate = date;
487}
488
489const QString &Item::sender() const
490{
491 return d_ptr->mSender;
492}
493
494void Item::setSender(const QString &sender)
495{
496 d_ptr->mSender = sender;
497}
498
500{
501 return sender();
502}
503
505{
506 return d_ptr->mReceiver;
507}
508
509void Item::setReceiver(const QString &receiver)
510{
511 d_ptr->mReceiver = receiver;
512}
513
515{
516 return receiver();
517}
518
520{
521 return d_ptr->mUseReceiver ? d_ptr->mReceiver : d_ptr->mSender;
522}
523
528
530{
531 return d_ptr->mUseReceiver;
532}
533
534const QString &Item::subject() const
535{
536 return d_ptr->mSubject;
537}
538
539void Item::setSubject(const QString &subject)
540{
541 d_ptr->mSubject = subject;
542}
543
544const QString &Item::folder() const
545{
546 return d_ptr->mFolder;
547}
548
549void Item::setFolder(const QString &folder)
550{
551 d_ptr->mFolder = folder;
552}
553
554void MessageList::Core::Item::initialSetup(time_t date, size_t size, const QString &sender, const QString &receiver, bool useReceiver)
555{
556 d_ptr->mDate = date;
557 d_ptr->mMaxDate = date;
558 d_ptr->mSize = size;
559 d_ptr->mSender = sender;
560 d_ptr->mReceiver = receiver;
561 d_ptr->mUseReceiver = useReceiver;
562}
563
564void MessageList::Core::Item::setItemId(qint64 id)
565{
566 d_ptr->mItemId = id;
567}
568
569qint64 MessageList::Core::Item::itemId() const
570{
571 return d_ptr->mItemId;
572}
573
574void Item::setParentCollectionId(qint64 id)
575{
576 d_ptr->mParentCollectionId = id;
577}
578
579qint64 Item::parentCollectionId() const
580{
581 return d_ptr->mParentCollectionId;
582}
583
585{
586 d_ptr->mSubject = subject;
587 d_ptr->mStatus = status;
588}
589
590// FIXME: Try to "cache item insertions" and call beginInsertRows() and endInsertRows() in a chunked fashion...
591
593{
594 if (!d_ptr->mChildItems) {
595 d_ptr->mChildItems = new QList<Item *>();
596 }
597 d_ptr->mChildItems->append(child);
598}
599
601{
602 if (!d_ptr->mChildItems) {
603 d_ptr->mChildItems = new QList<Item *>();
604 }
605 const int idx = d_ptr->mChildItems->count();
606 if (d_ptr->mIsViewable) {
607 if (model) {
608 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
609 }
610 d_ptr->mChildItems->append(child);
611 child->setIndexGuess(idx);
612 if (model) {
613 model->endInsertRows(); // THIS IS EXTREMELY UGLY, BUT IT'S THE ONLY POSSIBLE WAY WITH QT4 AT THE TIME OF WRITING
614 }
615 child->setViewable(model, true);
616 } else {
617 d_ptr->mChildItems->append(child);
618 child->setIndexGuess(idx);
619 }
620 return idx;
621}
622
623void Item::dump(const QString &prefix)
624{
625 QString out = QStringLiteral("%1 %x VIEWABLE:%2").arg(prefix, d_ptr->mIsViewable ? QStringLiteral("yes") : QStringLiteral("no"));
626 qDebug(out.toUtf8().data(), this);
627
628 QString nPrefix(prefix);
629 nPrefix += QLatin1StringView(" ");
630
631 if (!d_ptr->mChildItems) {
632 return;
633 }
634
635 for (const auto child : std::as_const(*d_ptr->mChildItems)) {
636 child->dump(nPrefix);
637 }
638}
639
640void Item::takeChildItem(Model *model, Item *child)
641{
642 if (!d_ptr->mChildItems) {
643 return; // Ugh... not our child ?
644 }
645
646 if (!d_ptr->mIsViewable) {
647 // qDebug("TAKING NON VIEWABLE CHILD ITEM %x",child);
648 // We can highly optimize this case
649 d_ptr->mChildItems->removeOne(child);
650#if 0
651 // This *could* be done, but we optimize and avoid it.
652 if (d->mChildItems->isEmpty()) {
653 delete d->mChildItems;
654 d->mChildItems = 0;
655 }
656#endif
657 child->setParent(nullptr);
658 return;
659 }
660
661 const int idx = indexOfChildItem(child);
662 if (idx < 0) {
663 return; // Aaargh... not our child ?
664 }
665
666 child->setViewable(model, false);
667 if (model) {
668 model->beginRemoveRows(model->index(this, 0), idx, idx);
669 }
670 child->setParent(nullptr);
671 d_ptr->mChildItems->removeAt(idx);
672 if (model) {
673 model->endRemoveRows();
674 }
675
676#if 0
677 // This *could* be done, but we optimize and avoid it.
678 if (d->mChildItems->isEmpty()) {
679 delete d->mChildItems;
680 d->mChildItems = 0;
681 }
682#endif
683}
684
685void ItemPrivate::childItemDead(Item *child)
686{
687 // mChildItems MUST be non zero here, if it's not then it's a bug in THIS FILE
688 mChildItems->removeOne(child); // since we always have ONE (if we not, it's a bug)
689}
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:326
const QString & senderOrReceiver() const
Returns the sender or the receiver, depending on the underlying StorageModel settings.
Definition item.cpp:519
virtual ~Item()
Destroys the Item.
Definition item.cpp:32
const QString & receiver() const
Returns the receiver associated to this item.
Definition item.cpp:504
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:317
QString formattedDate() const
A string with a text rappresentation of date() obtained via Manager.
Definition item.cpp:308
size_t size() const
Returns the size of this item (size of the Message, mainly)
Definition item.cpp:459
void setSize(size_t size)
Sets the size of this item (size of the Message, mainly)
Definition item.cpp:464
void rawAppendChildItem(Item *child)
Appends a child item without inserting it via the model.
Definition item.cpp:592
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:600
bool useReceiver() const
Returns whether sender or receiver is supposed to be displayed.
Definition item.cpp:529
const Akonadi::MessageStatus & status() const
Returns the status associated to this Item.
Definition item.cpp:449
void setReceiver(const QString &receiver)
Sets the sender associated to this item.
Definition item.cpp:509
InitialExpandStatus initialExpandStatus() const
The initial expand status we have to honor when attaching to the viewable root.
Definition item.cpp:350
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
void dump(const QString &prefix)
Debug helper.
Definition item.cpp:623
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:554
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:365
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:370
time_t date() const
Returns the date of this item.
Definition item.cpp:469
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:425
time_t maxDate() const
Returns the maximum date in the subtree originating from this item.
Definition item.cpp:479
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 setMaxDate(time_t date)
Sets the maximum date in the subtree originating from this item.
Definition item.cpp:484
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:345
const QString & folder() const
Returns the folder associated to this Item.
Definition item.cpp:544
const QString & sender() const
Returns the sender associated to this item.
Definition item.cpp:489
QString displayReceiver() const
Display receiver.
Definition item.cpp:514
void setStatus(Akonadi::MessageStatus status)
Sets the status associated to this Item.
Definition item.cpp:454
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:640
void setSender(const QString &sender)
Sets the sender associated to this item.
Definition item.cpp:494
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:524
void setSubject(const QString &subject)
Sets the subject associated to this Item.
Definition item.cpp:539
Item * parent() const
Returns the parent Item in the tree, or 0 if this item isn't attached to the tree.
Definition item.cpp:439
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:444
void setDate(time_t date)
Sets the date of this item.
Definition item.cpp:474
void setFolder(const QString &folder)
Sets the folder associated to this Item.
Definition item.cpp:549
void setInitialExpandStatus(InitialExpandStatus initialExpandStatus)
Set the initial expand status we have to honor when attaching to the viewable root.
Definition item.cpp:355
bool hasChildren() const
Convenience function that returns true if this item has children.
Definition item.cpp:162
QString formattedSize() const
A string with a text rappresentation of size().
Definition item.cpp:302
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:584
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:534
Item(Type type)
Creates an Item.
Definition item.cpp:20
QString displaySender() const
Display sender.
Definition item.cpp:499
bool isViewable() const
Is this item attached to the viewable root ?
Definition item.cpp:360
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 Sat Dec 21 2024 16:59:12 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.