File indexing completed on 2024-05-12 16:28:11
0001 // SPDX-FileCopyrightText: 2023 Shubham Arora <shubhamarora@protonmail.com> 0002 // SPDX-License-Identifier: GPL-3.0-only 0003 0004 #include "tagsmodel.h" 0005 #include <KLocalizedString> 0006 #include <QJsonArray> 0007 #include <QUrlQuery> 0008 #include <QtMath> 0009 #include <algorithm> 0010 0011 TagsModel::TagsModel(QObject *parent) 0012 : AbstractListModel(parent) 0013 { 0014 connect(this, &AbstractListModel::nameChanged, this, &TagsModel::onNameChanged); 0015 } 0016 0017 void TagsModel::onNameChanged() 0018 { 0019 fillTimeline(); 0020 } 0021 0022 QString TagsModel::displayName() const 0023 { 0024 return i18n("Trending"); 0025 } 0026 0027 void TagsModel::fetchMore(const QModelIndex &parent) 0028 { 0029 Q_UNUSED(parent); 0030 if (shouldLoadMore()) { 0031 fillTimeline(); 0032 } else { 0033 setShouldLoadMore(true); 0034 } 0035 } 0036 0037 bool TagsModel::canFetchMore(const QModelIndex &parent) const 0038 { 0039 Q_UNUSED(parent); 0040 return !m_next.isEmpty(); 0041 } 0042 0043 void TagsModel::fillTimeline(const QString &fromId) 0044 { 0045 Q_UNUSED(fromId); 0046 0047 if (!account() || loading() || name() != "trending") { 0048 return; 0049 } 0050 0051 QUrlQuery q; 0052 q.addQueryItem("limit", "20"); 0053 QUrl uri; 0054 if (m_next.isEmpty()) { 0055 if (name() == "trending") { 0056 uri = account()->apiUrl("/api/v1/trends/tags"); 0057 uri.setQuery(q); 0058 } 0059 } else { 0060 uri = m_next; 0061 } 0062 0063 setLoading(true); 0064 account()->get( 0065 uri, 0066 false, 0067 this, 0068 [this, uri](QNetworkReply *reply) { 0069 const auto data = reply->readAll(); 0070 const auto doc = QJsonDocument::fromJson(data); 0071 if (!doc.isArray()) { 0072 return; 0073 } 0074 static QRegularExpression re("<(.*)>; rel=\"next\""); 0075 const auto next = reply->rawHeader(QByteArrayLiteral("Link")); 0076 const auto match = re.match(next); 0077 m_next = QUrl::fromUserInput(match.captured(1)); 0078 const auto values = doc.array(); 0079 0080 QList<Tag> tags; 0081 std::transform(values.cbegin(), values.cend(), std::back_inserter(tags), [](const QJsonValue &value) { 0082 return Tag(value.toObject()); 0083 }); 0084 0085 beginInsertRows({}, m_tags.size(), m_tags.size() + tags.size() - 1); 0086 m_tags += tags; 0087 endInsertRows(); 0088 setLoading(false); 0089 }, 0090 [this](QNetworkReply *reply) { 0091 Q_UNUSED(reply); 0092 setLoading(false); 0093 }); 0094 } 0095 0096 QHash<int, QByteArray> TagsModel::roleNames() const 0097 { 0098 return { 0099 {CustomRoles::NameRole, "name"}, 0100 {CustomRoles::UrlRole, "url"}, 0101 {CustomRoles::HistoryRole, "history"}, 0102 }; 0103 } 0104 0105 QVariant TagsModel::data(const QModelIndex &index, int role) const 0106 { 0107 Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)); 0108 0109 switch (role) { 0110 case CustomRoles::NameRole: 0111 return m_tags[index.row()].name(); 0112 case CustomRoles::UrlRole: 0113 return m_tags[index.row()].url(); 0114 case CustomRoles::HistoryRole: 0115 return QVariant::fromValue<QList<History>>(m_tags[index.row()].history()); 0116 default: 0117 return {}; 0118 } 0119 } 0120 0121 int TagsModel::rowCount(const QModelIndex &parent) const 0122 { 0123 Q_UNUSED(parent) 0124 return m_tags.size(); 0125 }