KNewStuff

core/commentsmodel.cpp
1 /*
2  SPDX-FileCopyrightText: 2019 Dan Leinir Turthra Jensen <[email protected]>
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 "entryinternal.h"
10 #include "knewstuffcore_debug.h"
11 
12 #include <KLocalizedString>
13 
14 #include <QTimer>
15 
16 namespace KNSCore {
17 class CommentsModel::Private {
18 public:
19  Private(CommentsModel *qq)
20  : q(qq)
21  {}
22  CommentsModel *const q;
23  Engine *engine = nullptr;
24 
25  EntryInternal entry;
26 
28 
29  enum FetchOptions {
30  NoOption,
31  ClearModel,
32  };
33  bool fetchThrottle = false;
34  void fetch(FetchOptions option = NoOption) {
35  if (fetchThrottle) {
36  return;
37  }
38  fetchThrottle = true;
39  QTimer::singleShot(1, q, [this](){
40  fetchThrottle = false;
41  });
42  // Sanity checks, because we need a few things to be correct before we can actually fetch comments...
43  if (!engine) {
44  qCWarning(KNEWSTUFFCORE) << "CommentsModel must be parented on a KNSCore::Engine instance to be able to fetch comments";
45  }
46  if (!entry.isValid()) {
47  qCWarning(KNEWSTUFFCORE) << "Without an entry to fetch comments for, CommentsModel cannot fetch comments for it";
48  }
49 
50  if (engine && entry.isValid()) {
51  QSharedPointer<Provider> provider = engine->provider(entry.providerId());
52  if (option == ClearModel) {
53  q->beginResetModel();
54  comments.clear();
55  provider->disconnect(q);
56  q->connect(provider.data(), &Provider::commentsLoaded, q, [=](const QList<std::shared_ptr<KNSCore::Comment>> &newComments){
57  QList<std::shared_ptr<KNSCore::Comment>> actualNewComments;
58  for (const std::shared_ptr<KNSCore::Comment> &comment : newComments) {
59  bool commentIsKnown = false;
60  for (const std::shared_ptr<KNSCore::Comment> &existingComment : qAsConst(comments)) {
61  if (existingComment->id == comment->id) {
62  commentIsKnown = true;
63  break;
64  }
65  }
66  if (commentIsKnown) {
67  continue;
68  }
69  actualNewComments << comment;
70  }
71  if (actualNewComments.count() > 0) {
72  q->beginInsertRows(QModelIndex(), comments.count(), comments.count() + actualNewComments.count() - 1);
73  qCDebug(KNEWSTUFFCORE) << "Appending" << actualNewComments.count() << "new comments";
74  comments.append(actualNewComments);
75  q->endInsertRows();
76  }
77  });
78  q->endResetModel();
79  }
80  int commentsPerPage = 100;
81  int pageToLoad = comments.count() / commentsPerPage;
82  qCDebug(KNEWSTUFFCORE) << "Loading comments, page" << pageToLoad << "with current comment count" << comments.count() << "out of a total of" << entry.numberOfComments();
83  Q_EMIT provider->loadComments(entry, commentsPerPage, pageToLoad);
84  }
85  }
86 };
87 }
88 
90  : QAbstractListModel(parent)
91  , d(new Private(this))
92 {
93  d->engine = parent;
94 }
95 
96 KNSCore::CommentsModel::~CommentsModel()
97 {
98  delete d;
99 }
100 
101 QHash<int, QByteArray> KNSCore::CommentsModel::roleNames() const
102 {
103  static const QHash<int, QByteArray> roles{
104  {IdRole, "id"},
105  {SubjectRole, "subject"},
106  {TextRole, "text"},
107  {ChildCountRole, "childCound"},
108  {UsernameRole, "username"},
109  {DateRole, "date"},
110  {ScoreRole, "score"},
111  {ParentIndexRole, "parentIndex"},
112  {DepthRole, "depth"}
113  };
114  return roles;
115 }
116 
117 QVariant KNSCore::CommentsModel::data(const QModelIndex &index, int role) const
118 {
119  QVariant value;
120  if (checkIndex(index)) {
121  std::shared_ptr<KNSCore::Comment> comment = d->comments[index.row()];
122  switch (role)
123  {
124  case IdRole:
125  value.setValue(comment->id);
126  break;
127  case SubjectRole:
128  value.setValue(comment->subject);
129  break;
130  case TextRole:
131  value.setValue(comment->text);
132  break;
133  case ChildCountRole:
134  value.setValue(comment->childCount);
135  break;
136  case UsernameRole:
137  value.setValue(comment->username);
138  break;
139  case DateRole:
140  value.setValue(comment->date);
141  break;
142  case ScoreRole:
143  value.setValue(comment->score);
144  break;
145  case ParentIndexRole:
146  {
147  int idx{-1};
148  if (comment->parent) {
149  idx = d->comments.indexOf(comment->parent);
150  }
151  value.setValue(idx);
152  }
153  break;
154  case DepthRole:
155  {
156  int depth{0};
157  if (comment->parent) {
158  std::shared_ptr<KNSCore::Comment> child = comment->parent;
159  while (child) {
160  ++depth;
161  child = child->parent;
162  }
163  }
164  value.setValue(depth);
165  }
166  break;
167  default:
168  value.setValue(i18nc("The value returned for an unknown role when requesting data from the model.", "Unknown CommentsModel role"));
169  break;
170  }
171  }
172  return value;
173 }
174 
175 int KNSCore::CommentsModel::rowCount(const QModelIndex &parent) const
176 {
177  if (parent.isValid())
178  return 0;
179  return d->comments.count();
180 }
181 
182 bool KNSCore::CommentsModel::canFetchMore(const QModelIndex &parent) const
183 {
184  if (parent.isValid())
185  return false;
186  if (d->entry.numberOfComments() > d->comments.count())
187  return true;
188  return false;
189 }
190 
191 void KNSCore::CommentsModel::fetchMore(const QModelIndex &parent)
192 {
193  if(parent.isValid())
194  return;
195  d->fetch();
196 }
197 
199 {
200  return d->entry;
201 }
202 
203 void KNSCore::CommentsModel::setEntry(const KNSCore::EntryInternal &newEntry)
204 {
205  d->entry = newEntry;
206  d->fetch(Private::ClearModel);
207  Q_EMIT entryChanged();
208 }
void clear()
bool checkIndex(const QModelIndex &index, QAbstractItemModel::CheckIndexOptions options) const const
CommentsModel(Engine *parent=nullptr)
Construct a new CommentsModel instance.
Contains the core functionality for handling interaction with NewStuff providers. ...
Encapsulates a KNSCore::Engine for use in Qt Quick.
Definition: quickengine.h:23
T * data() const const
KNSCore::EntryInternal entry
The Entry for which this model should handle comments.
bool isValid() const const
int count(const T &value) const const
void append(const T &value)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
int row() const const
void commentsLoaded(const QList< std::shared_ptr< KNSCore::Comment >> comments)
Fired when new comments have been loaded.
void setValue(const T &value)
KNewStuff data entry container.
Definition: entryinternal.h:49
KNewStuff engine.
Definition: engine.h:59
QObject * parent() const const
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Jan 18 2021 22:43:49 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.