Simplify author handling

- Don't make them QObjects; those are heavy and there's no reason for that
- In fact, don't make them objects at all; we're only using them in string form anyway
This commit is contained in:
Tobias Fella 2023-12-19 09:14:48 +00:00 committed by Bart De Vries
parent fe6626ebeb
commit eb74c913a9
11 changed files with 45 additions and 165 deletions

View File

@ -10,7 +10,6 @@ add_executable(kasts
database.cpp database.cpp
entry.cpp entry.cpp
feed.cpp feed.cpp
author.cpp
enclosure.cpp enclosure.cpp
chapter.cpp chapter.cpp
datamanager.cpp datamanager.cpp

View File

@ -731,11 +731,8 @@ void AudioManager::updateMetaData()
if (!d->m_entry->feed()->name().isEmpty()) { if (!d->m_entry->feed()->name().isEmpty()) {
d->m_player.metaData()->setAlbum(d->m_entry->feed()->name()); d->m_player.metaData()->setAlbum(d->m_entry->feed()->name());
} }
if (d->m_entry->authors().count() > 0) { if (d->m_entry->authors().length() > 0) {
QString authors; d->m_player.metaData()->setArtist(d->m_entry->authors());
for (auto &author : d->m_entry->authors())
authors.append(author->name());
d->m_player.metaData()->setArtist(authors);
} }
if (!d->m_entry->image().isEmpty()) { if (!d->m_entry->image().isEmpty()) {
d->m_player.metaData()->setArtworkUrl(QUrl(d->m_entry->cachedImage())); d->m_player.metaData()->setArtworkUrl(QUrl(d->m_entry->cachedImage()));

View File

@ -1,30 +0,0 @@
/**
* SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "author.h"
Author::Author(const QString &name, const QString &email, const QString &url, QObject *parent)
: QObject(parent)
, m_name(name)
, m_email(email)
, m_url(url)
{
}
QString Author::name() const
{
return m_name;
}
QString Author::email() const
{
return m_email;
}
QString Author::url() const
{
return m_url;
}

View File

@ -1,30 +0,0 @@
/**
* SPDX-FileCopyrightText: 2020 Tobias Fella <tobias.fella@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#pragma once
#include <QObject>
class Author : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(QString email READ email CONSTANT)
Q_PROPERTY(QString url READ url CONSTANT)
public:
Author(const QString &name, const QString &email, const QString &url, QObject *parent = nullptr);
QString name() const;
QString email() const;
QString url() const;
private:
QString m_name;
QString m_email;
QString m_url;
};

View File

@ -12,6 +12,8 @@
#include <QSqlQuery> #include <QSqlQuery>
#include <QUrl> #include <QUrl>
#include <KLocalizedString>
#include "database.h" #include "database.h"
#include "datamanager.h" #include "datamanager.h"
#include "feed.h" #include "feed.h"
@ -76,55 +78,31 @@ void Entry::updateFromDb(bool emitSignals)
setHasEnclosure(entryQuery.value(QStringLiteral("hasEnclosure")).toBool(), emitSignals); setHasEnclosure(entryQuery.value(QStringLiteral("hasEnclosure")).toBool(), emitSignals);
setImage(entryQuery.value(QStringLiteral("image")).toString(), emitSignals); setImage(entryQuery.value(QStringLiteral("image")).toString(), emitSignals);
updateAuthors(emitSignals); updateAuthors();
} }
void Entry::updateAuthors(bool emitSignals) void Entry::updateAuthors()
{ {
QVector<Author *> newAuthors; QStringList authors;
bool haveAuthorsChanged = false;
QSqlQuery authorQuery; QSqlQuery authorQuery;
authorQuery.prepare(QStringLiteral("SELECT * FROM Authors WHERE id=:id AND feed=:feed;")); authorQuery.prepare(QStringLiteral("SELECT name FROM Authors WHERE id=:id AND feed=:feed"));
authorQuery.bindValue(QStringLiteral(":id"), m_id); authorQuery.bindValue(QStringLiteral(":id"), m_id);
authorQuery.bindValue(QStringLiteral(":feed"), m_feed->url()); authorQuery.bindValue(QStringLiteral(":feed"), m_feed->url());
Database::instance().execute(authorQuery); Database::instance().execute(authorQuery);
while (authorQuery.next()) { while (authorQuery.next()) {
// check if author already exists, if so, then reuse authors += authorQuery.value(QStringLiteral("name")).toString();
bool existingAuthor = false;
QString name = authorQuery.value(QStringLiteral("name")).toString();
QString email = authorQuery.value(QStringLiteral("email")).toString();
QString url = authorQuery.value(QStringLiteral("uri")).toString();
qCDebug(kastsEntry) << name << email << url;
for (Author *author : m_authors) {
if (author)
qCDebug(kastsEntry) << "old authors" << author->name() << author->email() << author->url();
if (author && author->name() == name && author->email() == email && author->url() == url) {
existingAuthor = true;
newAuthors += author;
}
}
if (!existingAuthor) {
newAuthors += new Author(name, email, url, this);
haveAuthorsChanged = true;
}
} }
// Finally check whether m_authors and newAuthors are identical if (authors.size() == 1) {
// if not, then delete the authors that were removed m_authors = authors[0];
for (Author *author : m_authors) { } else if (authors.size() == 2) {
if (!newAuthors.contains(author)) { m_authors = i18nc("<name> and <name>", "%1 and %2", authors.first(), authors.last());
delete author; } else if (authors.size() > 2) {
haveAuthorsChanged = true; auto last = authors.takeLast();
} m_authors = i18nc("<name(s)>, and <name>", "%1, and %2", authors.join(u','), last);
}
m_authors = newAuthors;
if (haveAuthorsChanged && emitSignals) {
Q_EMIT authorsChanged(m_authors);
qCDebug(kastsEntry) << "entry" << m_id << "authors have changed?" << haveAuthorsChanged;
} }
Q_EMIT authorsChanged(m_authors);
} }
QString Entry::id() const QString Entry::id() const
@ -142,7 +120,7 @@ QString Entry::content() const
return m_content; return m_content;
} }
QVector<Author *> Entry::authors() const QString Entry::authors() const
{ {
return m_authors; return m_authors;
} }

View File

@ -13,7 +13,6 @@
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include "author.h"
#include "enclosure.h" #include "enclosure.h"
#include "feed.h" #include "feed.h"
@ -25,7 +24,7 @@ class Entry : public QObject
Q_PROPERTY(QString id READ id CONSTANT) Q_PROPERTY(QString id READ id CONSTANT)
Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(QString content READ content NOTIFY contentChanged) Q_PROPERTY(QString content READ content NOTIFY contentChanged)
Q_PROPERTY(QVector<Author *> authors READ authors NOTIFY authorsChanged) Q_PROPERTY(QString authors READ authors NOTIFY authorsChanged)
Q_PROPERTY(QDateTime created READ created NOTIFY createdChanged) Q_PROPERTY(QDateTime created READ created NOTIFY createdChanged)
Q_PROPERTY(QDateTime updated READ updated NOTIFY updatedChanged) Q_PROPERTY(QDateTime updated READ updated NOTIFY updatedChanged)
Q_PROPERTY(QString link READ link NOTIFY linkChanged) Q_PROPERTY(QString link READ link NOTIFY linkChanged)
@ -45,7 +44,7 @@ public:
QString id() const; QString id() const;
QString title() const; QString title() const;
QString content() const; QString content() const;
QVector<Author *> authors() const; QString authors() const;
QDateTime created() const; QDateTime created() const;
QDateTime updated() const; QDateTime updated() const;
QString link() const; QString link() const;
@ -76,7 +75,7 @@ public:
Q_SIGNALS: Q_SIGNALS:
void titleChanged(const QString &title); void titleChanged(const QString &title);
void contentChanged(const QString &content); void contentChanged(const QString &content);
void authorsChanged(const QVector<Author *> &authors); void authorsChanged(const QString &authors);
void createdChanged(const QDateTime &created); void createdChanged(const QDateTime &created);
void updatedChanged(const QDateTime &updated); void updatedChanged(const QDateTime &updated);
void linkChanged(const QString &link); void linkChanged(const QString &link);
@ -91,7 +90,7 @@ Q_SIGNALS:
private: private:
void updateFromDb(bool emitSignals = true); void updateFromDb(bool emitSignals = true);
void updateAuthors(bool emitSignals = true); void updateAuthors();
void setTitle(const QString &title, bool emitSignal = true); void setTitle(const QString &title, bool emitSignal = true);
void setContent(const QString &content, bool emitSignal = true); void setContent(const QString &content, bool emitSignal = true);
void setCreated(const QDateTime &created, bool emitSignal = true); void setCreated(const QDateTime &created, bool emitSignal = true);
@ -104,7 +103,7 @@ private:
QString m_id; QString m_id;
QString m_title; QString m_title;
QString m_content; QString m_content;
QVector<Author *> m_authors; QString m_authors;
QDateTime m_created; QDateTime m_created;
QDateTime m_updated; QDateTime m_updated;
QString m_link; QString m_link;

View File

@ -7,7 +7,8 @@
#include <QVariant> #include <QVariant>
#include "author.h" #include <KLocalizedString>
#include "database.h" #include "database.h"
#include "datamanager.h" #include "datamanager.h"
#include "error.h" #include "error.h"
@ -100,47 +101,25 @@ Feed::Feed(const QString &feedurl)
void Feed::updateAuthors() void Feed::updateAuthors()
{ {
QVector<Author *> newAuthors; QStringList authors;
bool haveAuthorsChanged = false;
QSqlQuery authorQuery; QSqlQuery authorQuery;
authorQuery.prepare(QStringLiteral("SELECT * FROM Authors WHERE id='' AND feed=:feed")); authorQuery.prepare(QStringLiteral("SELECT name FROM Authors WHERE id='' AND feed=:feed"));
authorQuery.bindValue(QStringLiteral(":feed"), m_url); authorQuery.bindValue(QStringLiteral(":feed"), m_url);
Database::instance().execute(authorQuery); Database::instance().execute(authorQuery);
while (authorQuery.next()) { while (authorQuery.next()) {
// check if author already exists, if so, then reuse authors += authorQuery.value(QStringLiteral("name")).toString();
bool existingAuthor = false;
QString name = authorQuery.value(QStringLiteral("name")).toString();
QString email = authorQuery.value(QStringLiteral("email")).toString();
QString url = authorQuery.value(QStringLiteral("uri")).toString();
qCDebug(kastsFeed) << name << email << url;
for (int i = 0; i < m_authors.count(); i++) {
qCDebug(kastsFeed) << "old authors" << m_authors[i]->name() << m_authors[i]->email() << m_authors[i]->url();
if (m_authors[i] && m_authors[i]->name() == name && m_authors[i]->email() == email && m_authors[i]->url() == url) {
existingAuthor = true;
newAuthors += m_authors[i];
}
}
if (!existingAuthor) {
newAuthors += new Author(name, email, url, nullptr);
haveAuthorsChanged = true;
}
} }
// Finally check whether m_authors and newAuthors are identical if (authors.size() == 1) {
// if not, then delete the authors that were removed m_authors = authors[0];
for (int i = 0; i < m_authors.count(); i++) { } else if (authors.size() == 2) {
if (!newAuthors.contains(m_authors[i])) { m_authors = i18nc("<name> and <name>", "%1 and %2", authors.first(), authors.last());
delete m_authors[i]; } else if (authors.size() > 2) {
haveAuthorsChanged = true; auto last = authors.takeLast();
} m_authors = i18nc("<name(s)>, and <name>", "%1, and %2", authors.join(u','), last);
} }
Q_EMIT authorsChanged(m_authors);
m_authors = newAuthors;
if (haveAuthorsChanged)
Q_EMIT authorsChanged(m_authors);
qCDebug(kastsFeed) << "feed" << m_name << "authors have changed?" << haveAuthorsChanged;
} }
void Feed::updateUnreadEntryCountFromDB() void Feed::updateUnreadEntryCountFromDB()
@ -206,7 +185,7 @@ QString Feed::description() const
return m_description; return m_description;
} }
QVector<Author *> Feed::authors() const QString Feed::authors() const
{ {
return m_authors; return m_authors;
} }
@ -309,16 +288,6 @@ void Feed::setDescription(const QString &description)
} }
} }
void Feed::setAuthors(const QVector<Author *> &authors)
{
for (auto &author : m_authors) {
delete author;
}
m_authors.clear();
m_authors = authors;
Q_EMIT authorsChanged(m_authors);
}
void Feed::setDeleteAfterCount(int count) void Feed::setDeleteAfterCount(int count)
{ {
m_deleteAfterCount = count; m_deleteAfterCount = count;

View File

@ -12,7 +12,6 @@
#include <QString> #include <QString>
#include <QVector> #include <QVector>
#include "author.h"
#include "models/entriesproxymodel.h" #include "models/entriesproxymodel.h"
class Feed : public QObject class Feed : public QObject
@ -25,7 +24,7 @@ class Feed : public QObject
Q_PROPERTY(QString cachedImage READ cachedImage NOTIFY cachedImageChanged) Q_PROPERTY(QString cachedImage READ cachedImage NOTIFY cachedImageChanged)
Q_PROPERTY(QString link READ link WRITE setLink NOTIFY linkChanged) Q_PROPERTY(QString link READ link WRITE setLink NOTIFY linkChanged)
Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
Q_PROPERTY(QVector<Author *> authors READ authors WRITE setAuthors NOTIFY authorsChanged) Q_PROPERTY(QString authors READ authors NOTIFY authorsChanged)
Q_PROPERTY(bool refreshing READ refreshing WRITE setRefreshing NOTIFY refreshingChanged) Q_PROPERTY(bool refreshing READ refreshing WRITE setRefreshing NOTIFY refreshingChanged)
Q_PROPERTY(int deleteAfterCount READ deleteAfterCount WRITE setDeleteAfterCount NOTIFY deleteAfterCountChanged) Q_PROPERTY(int deleteAfterCount READ deleteAfterCount WRITE setDeleteAfterCount NOTIFY deleteAfterCountChanged)
Q_PROPERTY(int deleteAfterType READ deleteAfterType WRITE setDeleteAfterType NOTIFY deleteAfterTypeChanged) Q_PROPERTY(int deleteAfterType READ deleteAfterType WRITE setDeleteAfterType NOTIFY deleteAfterTypeChanged)
@ -52,7 +51,7 @@ public:
QString cachedImage() const; QString cachedImage() const;
QString link() const; QString link() const;
QString description() const; QString description() const;
QVector<Author *> authors() const; QString authors() const;
int deleteAfterCount() const; int deleteAfterCount() const;
int deleteAfterType() const; int deleteAfterType() const;
QDateTime subscribed() const; QDateTime subscribed() const;
@ -73,7 +72,6 @@ public:
void setImage(const QString &image); void setImage(const QString &image);
void setLink(const QString &link); void setLink(const QString &link);
void setDescription(const QString &description); void setDescription(const QString &description);
void setAuthors(const QVector<Author *> &authors);
void setDeleteAfterCount(int count); void setDeleteAfterCount(int count);
void setDeleteAfterType(int type); void setDeleteAfterType(int type);
void setLastUpdated(const QDateTime &lastUpdated); void setLastUpdated(const QDateTime &lastUpdated);
@ -92,7 +90,7 @@ Q_SIGNALS:
void cachedImageChanged(const QString &imagePath); void cachedImageChanged(const QString &imagePath);
void linkChanged(const QString &link); void linkChanged(const QString &link);
void descriptionChanged(const QString &description); void descriptionChanged(const QString &description);
void authorsChanged(const QVector<Author *> &authors); void authorsChanged(const QString &authors);
void deleteAfterCountChanged(int count); void deleteAfterCountChanged(int count);
void deleteAfterTypeChanged(int type); void deleteAfterTypeChanged(int type);
void lastUpdatedChanged(const QDateTime &lastUpdated); void lastUpdatedChanged(const QDateTime &lastUpdated);
@ -117,7 +115,7 @@ private:
QString m_image; QString m_image;
QString m_link; QString m_link;
QString m_description; QString m_description;
QVector<Author *> m_authors; QString m_authors;
int m_deleteAfterCount; int m_deleteAfterCount;
int m_deleteAfterType; int m_deleteAfterType;
QDateTime m_subscribed; QDateTime m_subscribed;

View File

@ -32,7 +32,6 @@
#include "androidlogging.h" #include "androidlogging.h"
#endif #endif
#include "audiomanager.h" #include "audiomanager.h"
#include "author.h"
#include "database.h" #include "database.h"
#include "datamanager.h" #include "datamanager.h"
#include "entry.h" #include "entry.h"

View File

@ -116,7 +116,7 @@ FocusScope {
property string blurredImage: AudioManager.entry ? AudioManager.entry.cachedImage : "no-image" property string blurredImage: AudioManager.entry ? AudioManager.entry.cachedImage : "no-image"
property string title: AudioManager.entry ? AudioManager.entry.title : i18n("No Track Title") property string title: AudioManager.entry ? AudioManager.entry.title : i18n("No Track Title")
property string feed: AudioManager.entry ? AudioManager.entry.feed.name : i18n("No track loaded") property string feed: AudioManager.entry ? AudioManager.entry.feed.name : i18n("No track loaded")
property string authors: AudioManager.entry ? (AudioManager.entry.feed.authors.length !== 0 ? AudioManager.entry.feed.authors[0].name : "") : "" property string authors: AudioManager.entry ? AudioManager.entry.feed.authors : ""
implicitHeight: headerBar.handlePosition implicitHeight: headerBar.handlePosition
implicitWidth: parent.width implicitWidth: parent.width

View File

@ -23,7 +23,6 @@ Kirigami.ScrollablePage {
property bool isSubscribed: true property bool isSubscribed: true
property var subscribeAction: undefined // this is only used if instantiated from the discoverpage property var subscribeAction: undefined // this is only used if instantiated from the discoverpage
property string author: isSubscribed ? (page.feed.authors.length === 0 ? "" : page.feed.authors[0].name) : feed.author
property bool showMoreInfo: false property bool showMoreInfo: false
title: i18n("Podcast Details") title: i18n("Podcast Details")
@ -114,9 +113,11 @@ Kirigami.ScrollablePage {
id: headerImage id: headerImage
Layout.fillWidth: true Layout.fillWidth: true
property string authors: isSubscribed ? feed.authors : feed.author
image: isSubscribed ? feed.cachedImage : feed.image image: isSubscribed ? feed.cachedImage : feed.image
title: isSubscribed ? feed.name : feed.title title: isSubscribed ? feed.name : feed.title
subtitle: (!page.feed.authors || page.feed.authors.length === 0) ? "" : i18nc("by <author(s)>", "by %1", page.feed.authors[0].name) subtitle: authors ? i18nc("by <author(s)>", "by %1", authors) : undefined
} }
// header actions // header actions