File indexing completed on 2024-05-12 05:04:14
0001 // SPDX-FileCopyrightText: 2022 Carl Schwan <carlschwan@kde.org> 0002 // SPDX-License-Identifier: LGPL-2.0-or-later 0003 0004 #include "searchmodel.h" 0005 0006 #include "account.h" 0007 0008 #include <KLocalizedString> 0009 0010 using namespace Qt::Literals::StringLiterals; 0011 0012 SearchModel::SearchModel(QObject *parent) 0013 : AbstractTimelineModel(parent) 0014 { 0015 m_account = AccountManager::instance().selectedAccount(); 0016 0017 connect(&AccountManager::instance(), &AccountManager::invalidated, this, [=](AbstractAccount *account) { 0018 if (m_account == account) { 0019 beginResetModel(); 0020 clear(); 0021 endResetModel(); 0022 } 0023 }); 0024 0025 connect(&AccountManager::instance(), &AccountManager::accountSelected, this, [=](AbstractAccount *account) { 0026 if (m_account != account) { 0027 m_account = account; 0028 beginResetModel(); 0029 clear(); 0030 endResetModel(); 0031 } 0032 }); 0033 } 0034 0035 SearchModel::~SearchModel() = default; 0036 0037 void SearchModel::search(const QString &queryString) 0038 { 0039 beginResetModel(); 0040 clear(); 0041 endResetModel(); 0042 0043 auto url = m_account->apiUrl(QStringLiteral("/api/v2/search")); 0044 url.setQuery({{QStringLiteral("q"), queryString}}); 0045 setLoading(true); 0046 setLoaded(false); 0047 m_account->get(url, true, this, [this](QNetworkReply *reply) { 0048 const auto searchResult = QJsonDocument::fromJson(reply->readAll()).object(); 0049 const auto statuses = searchResult[QStringLiteral("statuses")].toArray(); 0050 0051 beginResetModel(); 0052 clear(); 0053 0054 std::transform( 0055 statuses.cbegin(), 0056 statuses.cend(), 0057 std::back_inserter(m_statuses), 0058 [this](const QJsonValue &value) -> auto{ return new Post(m_account, value.toObject(), this); }); 0059 const auto accounts = searchResult[QStringLiteral("accounts")].toArray(); 0060 std::transform( 0061 accounts.cbegin(), 0062 accounts.cend(), 0063 std::back_inserter(m_accounts), 0064 [this](const QJsonValue &value) -> auto{ 0065 const auto account = value.toObject(); 0066 return m_account->identityLookup(account["id"_L1].toString(), account); 0067 }); 0068 const auto hashtags = searchResult[QStringLiteral("hashtags")].toArray(); 0069 std::transform( 0070 hashtags.cbegin(), 0071 hashtags.cend(), 0072 std::back_inserter(m_hashtags), 0073 [](const QJsonValue &value) -> auto{ return SearchHashtag(value.toObject()); }); 0074 endResetModel(); 0075 setLoading(false); 0076 setLoaded(true); 0077 }); 0078 } 0079 0080 int SearchModel::rowCount(const QModelIndex &parent) const 0081 { 0082 Q_UNUSED(parent); 0083 0084 return m_accounts.count() + m_statuses.count() + m_hashtags.count(); 0085 } 0086 0087 QVariant SearchModel::data(const QModelIndex &index, int role) const 0088 { 0089 const auto row = index.row(); 0090 0091 const bool isStatus = row >= m_accounts.count() && row < m_accounts.count() + m_statuses.size(); 0092 const bool isHashtag = row >= m_accounts.size() + m_statuses.count(); 0093 0094 if (role == TypeRole) { 0095 if (isHashtag) { 0096 return Hashtag; 0097 } else if (isStatus) { 0098 return Status; 0099 } else { 0100 return Account; 0101 } 0102 } 0103 0104 if (isStatus) { 0105 const auto post = m_statuses[row - m_accounts.count()]; 0106 return postData(post, role); 0107 } 0108 0109 if (isHashtag) { 0110 const auto hashtag = m_hashtags[row - m_accounts.count() - m_statuses.count()]; 0111 switch (role) { 0112 case IdRole: 0113 return hashtag.getName(); 0114 } 0115 } 0116 0117 const auto identity = m_accounts[row]; 0118 switch (role) { 0119 case AuthorIdentityRole: 0120 return QVariant::fromValue<Identity *>(identity.get()); 0121 } 0122 0123 return {}; 0124 } 0125 0126 void SearchModel::clear() 0127 { 0128 m_accounts.clear(); 0129 qDeleteAll(m_statuses); 0130 m_statuses.clear(); 0131 m_hashtags.clear(); 0132 setLoading(false); 0133 setLoaded(false); 0134 } 0135 0136 QString SearchModel::labelForType(ResultType sectionType) 0137 { 0138 switch (sectionType) { 0139 case Account: 0140 return i18n("Users"); 0141 case Hashtag: 0142 return i18n("Hashtags"); 0143 case Status: 0144 return i18n("Posts"); 0145 default: 0146 return {}; 0147 } 0148 } 0149 0150 bool SearchModel::loaded() const 0151 { 0152 return m_loaded; 0153 } 0154 0155 void SearchModel::setLoaded(bool loaded) 0156 { 0157 if (m_loaded == loaded) { 0158 return; 0159 } 0160 m_loaded = loaded; 0161 Q_EMIT loadedChanged(); 0162 } 0163 0164 SearchHashtag::SearchHashtag(const QJsonObject &object) 0165 { 0166 m_name = object["name"_L1].toString(); 0167 } 0168 0169 QString SearchHashtag::getName() const 0170 { 0171 return m_name; 0172 } 0173 0174 #include "moc_searchmodel.cpp"