Warning, file /frameworks/knewstuff/src/core/commentsmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2019 Dan Leinir Turthra Jensen <admin@leinir.dk>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "commentsmodel.h"
0008 
0009 #include "entry.h"
0010 #include "knewstuffcore_debug.h"
0011 
0012 #include <KLocalizedString>
0013 
0014 #include <QTimer>
0015 
0016 namespace KNSCore
0017 {
0018 class CommentsModelPrivate
0019 {
0020 public:
0021     CommentsModelPrivate(CommentsModel *qq)
0022         : q(qq)
0023     {
0024     }
0025     CommentsModel *const q;
0026     EngineBase *engine = nullptr;
0027 
0028     Entry entry;
0029 
0030     QList<std::shared_ptr<KNSCore::Comment>> comments;
0031 
0032     enum FetchOptions {
0033         NoOption,
0034         ClearModel,
0035     };
0036     bool fetchThrottle = false;
0037     void fetch(FetchOptions option = NoOption)
0038     {
0039         if (fetchThrottle) {
0040             return;
0041         }
0042         fetchThrottle = true;
0043         QTimer::singleShot(1, q, [this]() {
0044             fetchThrottle = false;
0045         });
0046         // Sanity checks, because we need a few things to be correct before we can actually fetch comments...
0047         if (!engine) {
0048             qCWarning(KNEWSTUFFCORE) << "CommentsModel must be parented on a KNSCore::EngineBase instance to be able to fetch comments";
0049         }
0050         if (!entry.isValid()) {
0051             qCWarning(KNEWSTUFFCORE) << "Without an entry to fetch comments for, CommentsModel cannot fetch comments for it";
0052         }
0053 
0054         if (engine && entry.isValid()) {
0055             QSharedPointer<Provider> provider = engine->provider(entry.providerId());
0056             if (option == ClearModel) {
0057                 q->beginResetModel();
0058                 comments.clear();
0059                 provider->disconnect(q);
0060                 q->connect(provider.data(), &Provider::commentsLoaded, q, [=](const QList<std::shared_ptr<KNSCore::Comment>> &newComments) {
0061                     QList<std::shared_ptr<KNSCore::Comment>> actualNewComments;
0062                     for (const std::shared_ptr<KNSCore::Comment> &comment : newComments) {
0063                         bool commentIsKnown = false;
0064                         for (const std::shared_ptr<KNSCore::Comment> &existingComment : std::as_const(comments)) {
0065                             if (existingComment->id == comment->id) {
0066                                 commentIsKnown = true;
0067                                 break;
0068                             }
0069                         }
0070                         if (commentIsKnown) {
0071                             continue;
0072                         }
0073                         actualNewComments << comment;
0074                     }
0075                     if (actualNewComments.count() > 0) {
0076                         q->beginInsertRows(QModelIndex(), comments.count(), comments.count() + actualNewComments.count() - 1);
0077                         qCDebug(KNEWSTUFFCORE) << "Appending" << actualNewComments.count() << "new comments";
0078                         comments.append(actualNewComments);
0079                         q->endInsertRows();
0080                     }
0081                 });
0082                 q->endResetModel();
0083             }
0084             int commentsPerPage = 100;
0085             int pageToLoad = comments.count() / commentsPerPage;
0086             qCDebug(KNEWSTUFFCORE) << "Loading comments, page" << pageToLoad << "with current comment count" << comments.count() << "out of a total of"
0087                                    << entry.numberOfComments();
0088             provider->loadComments(entry, commentsPerPage, pageToLoad);
0089         }
0090     }
0091 };
0092 }
0093 
0094 KNSCore::CommentsModel::CommentsModel(EngineBase *parent)
0095     : QAbstractListModel(parent)
0096     , d(new CommentsModelPrivate(this))
0097 {
0098     d->engine = parent;
0099 }
0100 
0101 KNSCore::CommentsModel::~CommentsModel() = default;
0102 
0103 QHash<int, QByteArray> KNSCore::CommentsModel::roleNames() const
0104 {
0105     static const QHash<int, QByteArray> roles{
0106         {IdRole, "id"},
0107         {SubjectRole, "subject"},
0108         {TextRole, "text"},
0109         {ChildCountRole, "childCound"},
0110         {UsernameRole, "username"},
0111         {DateRole, "date"},
0112         {ScoreRole, "score"},
0113         {ParentIndexRole, "parentIndex"},
0114         {DepthRole, "depth"},
0115     };
0116     return roles;
0117 }
0118 
0119 QVariant KNSCore::CommentsModel::data(const QModelIndex &index, int role) const
0120 {
0121     if (!checkIndex(index)) {
0122         return QVariant();
0123     }
0124     const std::shared_ptr<KNSCore::Comment> comment = d->comments[index.row()];
0125     switch (role) {
0126     case IdRole:
0127         return comment->id;
0128     case SubjectRole:
0129         return comment->subject;
0130     case TextRole:
0131         return comment->text;
0132     case ChildCountRole:
0133         return comment->childCount;
0134     case UsernameRole:
0135         return comment->username;
0136     case DateRole:
0137         return comment->date;
0138     case ScoreRole:
0139         return comment->score;
0140     case ParentIndexRole:
0141         return comment->parent ? d->comments.indexOf(comment->parent) : -1;
0142     case DepthRole: {
0143         int depth{0};
0144         if (comment->parent) {
0145             std::shared_ptr<KNSCore::Comment> child = comment->parent;
0146             while (child) {
0147                 ++depth;
0148                 child = child->parent;
0149             }
0150         }
0151         return depth;
0152     }
0153     default:
0154         return i18nc("The value returned for an unknown role when requesting data from the model.", "Unknown CommentsModel role");
0155     }
0156 }
0157 
0158 int KNSCore::CommentsModel::rowCount(const QModelIndex &parent) const
0159 {
0160     if (parent.isValid()) {
0161         return 0;
0162     }
0163     return d->comments.count();
0164 }
0165 
0166 bool KNSCore::CommentsModel::canFetchMore(const QModelIndex &parent) const
0167 {
0168     if (parent.isValid()) {
0169         return false;
0170     }
0171     if (d->entry.numberOfComments() > d->comments.count()) {
0172         return true;
0173     }
0174     return false;
0175 }
0176 
0177 void KNSCore::CommentsModel::fetchMore(const QModelIndex &parent)
0178 {
0179     if (parent.isValid()) {
0180         return;
0181     }
0182     d->fetch();
0183 }
0184 
0185 const KNSCore::Entry &KNSCore::CommentsModel::entry() const
0186 {
0187     return d->entry;
0188 }
0189 
0190 void KNSCore::CommentsModel::setEntry(const KNSCore::Entry &newEntry)
0191 {
0192     d->entry = newEntry;
0193     d->fetch(CommentsModelPrivate::ClearModel);
0194     Q_EMIT entryChanged();
0195 }
0196 
0197 #include "moc_commentsmodel.cpp"