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

KDE's Doxygen guidelines are available online.