mirror of
https://github.com/KDE/kasts.git
synced 2025-02-03 10:47:30 +01:00
Add model for searching for podcasts
This commit is contained in:
parent
653f41c94e
commit
fa1c308c2d
@ -20,6 +20,7 @@ set(SRCS_base
|
||||
powermanagementinterface.cpp
|
||||
errorlogmodel.cpp
|
||||
error.cpp
|
||||
podcastsearchmodel.cpp
|
||||
mpris2/mpris2.cpp
|
||||
resources.qrc
|
||||
)
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
|
||||
QString imagePath(const QString &url) const;
|
||||
QString enclosurePath(const QString &url) const;
|
||||
QNetworkReply *get(QNetworkRequest &request) const;
|
||||
|
||||
// Network status related methods
|
||||
Q_INVOKABLE bool canCheckNetworkStatus() const;
|
||||
@ -80,7 +81,6 @@ private:
|
||||
void processAuthor(const QString &url, const QString &entryId, const QString &authorName, const QString &authorUri, const QString &authorEmail);
|
||||
void processEnclosure(Syndication::EnclosurePtr enclosure, Syndication::ItemPtr entry, const QString &feedUrl);
|
||||
|
||||
QNetworkReply *get(QNetworkRequest &request) const;
|
||||
QNetworkReply *head(QNetworkRequest &request) const;
|
||||
void setHeader(QNetworkRequest &request) const;
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "fetcher.h"
|
||||
#include "kasts-version.h"
|
||||
#include "mpris2/mpris2.h"
|
||||
#include "podcastsearchmodel.h"
|
||||
#include "queuemodel.h"
|
||||
#include "settingsmanager.h"
|
||||
|
||||
@ -120,6 +121,7 @@ int main(int argc, char *argv[])
|
||||
qmlRegisterType<QueueModel>("org.kde.kasts", 1, 0, "QueueModel");
|
||||
qmlRegisterType<EpisodeModel>("org.kde.kasts", 1, 0, "EpisodeModel");
|
||||
qmlRegisterType<Mpris2>("org.kde.kasts", 1, 0, "Mpris2");
|
||||
qmlRegisterType<PodcastSearchModel>("org.kde.kasts", 1, 0, "PodcastSearchModel");
|
||||
|
||||
qmlRegisterUncreatableType<EntriesModel>("org.kde.kasts", 1, 0, "EntriesModel", QStringLiteral("Get from Feed"));
|
||||
qmlRegisterUncreatableType<Enclosure>("org.kde.kasts", 1, 0, "Enclosure", QStringLiteral("Only for enums"));
|
||||
|
75
src/podcastsearchmodel.cpp
Normal file
75
src/podcastsearchmodel.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include "podcastsearchmodel.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "fetcher.h"
|
||||
|
||||
PodcastSearchModel::PodcastSearchModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant PodcastSearchModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= rowCount(QModelIndex())) {
|
||||
// invalid index
|
||||
return QVariant::fromValue(QStringLiteral("DEADBEEF"));
|
||||
}
|
||||
if (role == Title) {
|
||||
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("title")].toString();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> PodcastSearchModel::roleNames() const
|
||||
{
|
||||
return {{Title, "title"}};
|
||||
}
|
||||
|
||||
int PodcastSearchModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
if (m_data.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return m_data[QStringLiteral("feeds")].toArray().size();
|
||||
}
|
||||
|
||||
void PodcastSearchModel::search(const QString &text)
|
||||
{
|
||||
QString safeText(text);
|
||||
// TODO: Make this more urlsafe
|
||||
safeText.replace(QLatin1Char(' '), QLatin1Char('+'));
|
||||
QNetworkRequest request(QUrl(QStringLiteral("https://api.podcastindex.org/api/1.0/search/byterm?q=%1").arg(text)));
|
||||
request.setRawHeader("X-Auth-Key", "BLVCJJSWUJGD3WJQSZ56");
|
||||
auto time = QDateTime::currentDateTime().toSecsSinceEpoch();
|
||||
request.setRawHeader("X-Auth-Date", QString::number(time).toLatin1());
|
||||
QString hashString = QStringLiteral(
|
||||
"BLVCJJSWUJGD3WJQSZ56"
|
||||
"vSPPqM8Tqh9Lr3xbEb77L4$f6kAdVw3v$9TwzGRH")
|
||||
+ QString::number(time);
|
||||
auto hash = QCryptographicHash::hash(hashString.toLatin1(), QCryptographicHash::Sha1);
|
||||
request.setRawHeader("Authorization", hash.toHex());
|
||||
auto reply = Fetcher::instance().get(request);
|
||||
// TODO: error handling
|
||||
connect(reply, &QNetworkReply::finished, this, [=]() {
|
||||
beginResetModel();
|
||||
m_data = QJsonDocument::fromJson(reply->readAll()).object();
|
||||
endResetModel();
|
||||
});
|
||||
}
|
34
src/podcastsearchmodel.h
Normal file
34
src/podcastsearchmodel.h
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QHash>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
#include "feed.h"
|
||||
|
||||
class PodcastSearchModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
Title,
|
||||
};
|
||||
explicit PodcastSearchModel(QObject *parent = nullptr);
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
|
||||
Q_INVOKABLE void search(const QString &text);
|
||||
|
||||
private:
|
||||
QJsonObject m_data;
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user