1 | /* |
2 | SPDX-FileCopyrightText: 2019 Dan Leinir Turthra Jensen <admin@leinir.dk> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | |
7 | #include "commentsmodel.h" |
8 | |
9 | #include "entry.h" |
10 | #include "knewstuffcore_debug.h" |
11 | |
12 | #include <KLocalizedString> |
13 | |
14 | #include <QTimer> |
15 | |
16 | namespace KNSCore |
17 | { |
18 | class |
19 | { |
20 | public: |
21 | (CommentsModel *qq) |
22 | : q(qq) |
23 | { |
24 | } |
25 | CommentsModel *const ; |
26 | EngineBase * = nullptr; |
27 | |
28 | Entry ; |
29 | |
30 | QList<std::shared_ptr<KNSCore::Comment>> ; |
31 | |
32 | enum { |
33 | , |
34 | , |
35 | }; |
36 | bool = false; |
37 | void (FetchOptions option = NoOption) |
38 | { |
39 | if (fetchThrottle) { |
40 | return; |
41 | } |
42 | fetchThrottle = true; |
43 | QTimer::singleShot(interval: 1, receiver: q, slot: [this]() { |
44 | fetchThrottle = false; |
45 | }); |
46 | // Sanity checks, because we need a few things to be correct before we can actually fetch comments... |
47 | if (!engine) { |
48 | qCWarning(KNEWSTUFFCORE) << "CommentsModel must be parented on a KNSCore::EngineBase instance to be able to fetch comments" ; |
49 | } |
50 | if (!entry.isValid()) { |
51 | qCWarning(KNEWSTUFFCORE) << "Without an entry to fetch comments for, CommentsModel cannot fetch comments for it" ; |
52 | } |
53 | |
54 | if (engine && entry.isValid()) { |
55 | QSharedPointer<Provider> provider = engine->provider(providerId: entry.providerId()); |
56 | if (option == ClearModel) { |
57 | q->beginResetModel(); |
58 | comments.clear(); |
59 | provider->disconnect(receiver: q); |
60 | q->connect(sender: provider.data(), signal: &Provider::commentsLoaded, context: q, slot: [=](const QList<std::shared_ptr<KNSCore::Comment>> &) { |
61 | QList<std::shared_ptr<KNSCore::Comment>> ; |
62 | for (const std::shared_ptr<KNSCore::Comment> & : newComments) { |
63 | bool = false; |
64 | for (const std::shared_ptr<KNSCore::Comment> & : std::as_const(t&: comments)) { |
65 | if (existingComment->id == comment->id) { |
66 | commentIsKnown = true; |
67 | break; |
68 | } |
69 | } |
70 | if (commentIsKnown) { |
71 | continue; |
72 | } |
73 | actualNewComments << comment; |
74 | } |
75 | if (actualNewComments.count() > 0) { |
76 | q->beginInsertRows(parent: QModelIndex(), first: comments.count(), last: comments.count() + actualNewComments.count() - 1); |
77 | qCDebug(KNEWSTUFFCORE) << "Appending" << actualNewComments.count() << "new comments" ; |
78 | comments.append(l: actualNewComments); |
79 | q->endInsertRows(); |
80 | } |
81 | }); |
82 | q->endResetModel(); |
83 | } |
84 | int = 100; |
85 | int pageToLoad = comments.count() / commentsPerPage; |
86 | qCDebug(KNEWSTUFFCORE) << "Loading comments, page" << pageToLoad << "with current comment count" << comments.count() << "out of a total of" |
87 | << entry.numberOfComments(); |
88 | provider->loadComments(entry, commentsPerPage, pageToLoad); |
89 | } |
90 | } |
91 | }; |
92 | } |
93 | |
94 | KNSCore::CommentsModel::(EngineBase *parent) |
95 | : QAbstractListModel(parent) |
96 | , d(new CommentsModelPrivate(this)) |
97 | { |
98 | d->engine = parent; |
99 | } |
100 | |
101 | KNSCore::CommentsModel::() = default; |
102 | |
103 | QHash<int, QByteArray> KNSCore::CommentsModel::() const |
104 | { |
105 | static const QHash<int, QByteArray> roles{ |
106 | {IdRole, "id" }, |
107 | {SubjectRole, "subject" }, |
108 | {TextRole, "text" }, |
109 | {ChildCountRole, "childCound" }, |
110 | {UsernameRole, "username" }, |
111 | {DateRole, "date" }, |
112 | {ScoreRole, "score" }, |
113 | {ParentIndexRole, "parentIndex" }, |
114 | {DepthRole, "depth" }, |
115 | }; |
116 | return roles; |
117 | } |
118 | |
119 | QVariant KNSCore::CommentsModel::(const QModelIndex &index, int role) const |
120 | { |
121 | if (!checkIndex(index)) { |
122 | return QVariant(); |
123 | } |
124 | const std::shared_ptr<KNSCore::Comment> = d->comments[index.row()]; |
125 | switch (role) { |
126 | case IdRole: |
127 | return comment->id; |
128 | case SubjectRole: |
129 | return comment->subject; |
130 | case TextRole: |
131 | return comment->text; |
132 | case ChildCountRole: |
133 | return comment->childCount; |
134 | case UsernameRole: |
135 | return comment->username; |
136 | case DateRole: |
137 | return comment->date; |
138 | case ScoreRole: |
139 | return comment->score; |
140 | case ParentIndexRole: |
141 | return comment->parent ? d->comments.indexOf(t: comment->parent) : -1; |
142 | case DepthRole: { |
143 | int depth{0}; |
144 | if (comment->parent) { |
145 | std::shared_ptr<KNSCore::Comment> child = comment->parent; |
146 | while (child) { |
147 | ++depth; |
148 | child = child->parent; |
149 | } |
150 | } |
151 | return depth; |
152 | } |
153 | default: |
154 | return i18nc("The value returned for an unknown role when requesting data from the model." , "Unknown CommentsModel role" ); |
155 | } |
156 | } |
157 | |
158 | int KNSCore::CommentsModel::(const QModelIndex &parent) const |
159 | { |
160 | if (parent.isValid()) { |
161 | return 0; |
162 | } |
163 | return d->comments.count(); |
164 | } |
165 | |
166 | bool KNSCore::CommentsModel::(const QModelIndex &parent) const |
167 | { |
168 | if (parent.isValid()) { |
169 | return false; |
170 | } |
171 | if (d->entry.numberOfComments() > d->comments.count()) { |
172 | return true; |
173 | } |
174 | return false; |
175 | } |
176 | |
177 | void KNSCore::CommentsModel::(const QModelIndex &parent) |
178 | { |
179 | if (parent.isValid()) { |
180 | return; |
181 | } |
182 | d->fetch(); |
183 | } |
184 | |
185 | const KNSCore::Entry &KNSCore::CommentsModel::() const |
186 | { |
187 | return d->entry; |
188 | } |
189 | |
190 | void KNSCore::CommentsModel::(const KNSCore::Entry &newEntry) |
191 | { |
192 | d->entry = newEntry; |
193 | d->fetch(option: CommentsModelPrivate::ClearModel); |
194 | Q_EMIT entryChanged(); |
195 | } |
196 | |
197 | #include "moc_commentsmodel.cpp" |
198 | |