File indexing completed on 2024-05-12 16:23:39

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Tobias Fella <fella@posteo.de>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include <QVariant>
0008 
0009 #include "database.h"
0010 #include "entriesmodel.h"
0011 #include "feed.h"
0012 #include "fetcher.h"
0013 
0014 Feed::Feed(int index)
0015     : QObject(nullptr)
0016 {
0017     QSqlQuery query;
0018     if (query.prepare(QStringLiteral("SELECT * FROM Feeds LIMIT 1 OFFSET :index;"))) {
0019         query.bindValue(QStringLiteral(":index"), index);
0020         Database::instance().execute(query);
0021         if (!query.next()) {
0022             qWarning() << "Failed to load feed" << index;
0023         }
0024 
0025         QSqlQuery authorQuery;
0026         if (authorQuery.prepare(QStringLiteral("SELECT * FROM Authors WHERE id='' AND feed=:feed"))) {
0027             authorQuery.bindValue(QStringLiteral(":feed"), query.value(QStringLiteral("url")).toString());
0028             Database::instance().execute(authorQuery);
0029             while (authorQuery.next()) {
0030                 m_authors += new Author(authorQuery.value(QStringLiteral("name")).toString(),
0031                                         authorQuery.value(QStringLiteral("email")).toString(),
0032                                         authorQuery.value(QStringLiteral("uri")).toString(),
0033                                         nullptr);
0034             }
0035         }
0036 
0037         m_subscribed.setSecsSinceEpoch(query.value(QStringLiteral("subscribed")).toInt());
0038 
0039         m_lastUpdated.setSecsSinceEpoch(query.value(QStringLiteral("lastUpdated")).toInt());
0040 
0041         m_url = query.value(QStringLiteral("url")).toString();
0042         m_name = query.value(QStringLiteral("name")).toString();
0043         m_display_name = query.value(QStringLiteral("displayName")).toString();
0044         m_image = query.value(QStringLiteral("image")).toString();
0045         m_link = query.value(QStringLiteral("link")).toString();
0046         m_description = query.value(QStringLiteral("description")).toString();
0047         m_group_name = query.value(QStringLiteral("groupName")).toString();
0048         m_deleteAfterCount = query.value(QStringLiteral("deleteAfterCount")).toInt();
0049         m_deleteAfterType = query.value(QStringLiteral("deleteAfterType")).toInt();
0050         m_notify = query.value(QStringLiteral("notify")).toBool();
0051     } else {
0052         qWarning() << "Failed to load feed" << index;
0053     }
0054 
0055     m_errorId = 0;
0056     m_errorString = QLatin1String("");
0057 
0058     connect(&Fetcher::instance(), &Fetcher::startedFetchingFeed, this, [this](const QString &url) {
0059         if (url == m_url) {
0060             setRefreshing(true);
0061         }
0062     });
0063     connect(&Fetcher::instance(), &Fetcher::feedUpdated, this, [this](const QString &url) {
0064         if (url == m_url) {
0065             setRefreshing(false);
0066             Q_EMIT entryCountChanged();
0067             Q_EMIT unreadEntryCountChanged();
0068             setErrorId(0);
0069             setErrorString(QLatin1String(""));
0070         }
0071     });
0072     connect(&Fetcher::instance(), &Fetcher::error, this, [this](const QString &url, int errorId, const QString &errorString) {
0073         if (url == m_url) {
0074             setErrorId(errorId);
0075             setErrorString(errorString);
0076             setRefreshing(false);
0077         }
0078     });
0079     connect(&Fetcher::instance(), &Fetcher::imageDownloadFinished, this, [this](const QString &url) {
0080         if (url == m_image) {
0081             Q_EMIT imageChanged(url);
0082         }
0083     });
0084 
0085     m_entries = new EntriesModel(this);
0086 }
0087 
0088 Feed::~Feed()
0089 {
0090 }
0091 
0092 QString Feed::url() const
0093 {
0094     return m_url;
0095 }
0096 
0097 QString Feed::name() const
0098 {
0099     return m_name;
0100 }
0101 
0102 QString Feed::displayName() const
0103 {
0104     return m_display_name;
0105 }
0106 
0107 QString Feed::image() const
0108 {
0109     return m_image;
0110 }
0111 
0112 QString Feed::link() const
0113 {
0114     return m_link;
0115 }
0116 
0117 QString Feed::description() const
0118 {
0119     return m_description;
0120 }
0121 
0122 QString Feed::groupName() const
0123 {
0124     return m_group_name;
0125 }
0126 
0127 QVector<Author *> Feed::authors() const
0128 {
0129     return m_authors;
0130 }
0131 
0132 int Feed::deleteAfterCount() const
0133 {
0134     return m_deleteAfterCount;
0135 }
0136 
0137 int Feed::deleteAfterType() const
0138 {
0139     return m_deleteAfterType;
0140 }
0141 
0142 QDateTime Feed::subscribed() const
0143 {
0144     return m_subscribed;
0145 }
0146 
0147 QDateTime Feed::lastUpdated() const
0148 {
0149     return m_lastUpdated;
0150 }
0151 
0152 bool Feed::notify() const
0153 {
0154     return m_notify;
0155 }
0156 
0157 int Feed::entryCount() const
0158 {
0159     static const int errorReturn = -1;
0160     QSqlQuery query;
0161     if (query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed;"))) {
0162         query.bindValue(QStringLiteral(":feed"), m_url);
0163         Database::instance().execute(query);
0164         if (!query.next()) {
0165             return errorReturn;
0166         }
0167         return query.value(0).toInt();
0168     } else {
0169         return errorReturn;
0170     }
0171 }
0172 
0173 int Feed::unreadEntryCount() const
0174 {
0175     static const int errorReturn = -1;
0176     QSqlQuery query;
0177     if (query.prepare(QStringLiteral("SELECT COUNT (id) FROM Entries where feed=:feed AND read=0;"))) {
0178         query.bindValue(QStringLiteral(":feed"), m_url);
0179         Database::instance().execute(query);
0180         if (!query.next()) {
0181             return errorReturn;
0182         }
0183         return query.value(0).toInt();
0184     } else {
0185         return errorReturn;
0186     }
0187 }
0188 
0189 bool Feed::refreshing() const
0190 {
0191     return m_refreshing;
0192 }
0193 
0194 int Feed::errorId() const
0195 {
0196     return m_errorId;
0197 }
0198 
0199 QString Feed::errorString() const
0200 {
0201     return m_errorString;
0202 }
0203 
0204 void Feed::setName(const QString &name)
0205 {
0206     m_name = name;
0207     Q_EMIT nameChanged(m_name);
0208 }
0209 
0210 void Feed::setDisplayName(const QString &displayName)
0211 {
0212     if (m_display_name != displayName) {
0213         m_display_name = displayName;
0214 
0215         Q_EMIT displayNameChanged(m_display_name);
0216     }
0217 }
0218 
0219 void Feed::setImage(const QString &image)
0220 {
0221     m_image = image;
0222     Q_EMIT imageChanged(m_image);
0223 }
0224 
0225 void Feed::setLink(const QString &link)
0226 {
0227     m_link = link;
0228     Q_EMIT linkChanged(m_link);
0229 }
0230 
0231 void Feed::setDescription(const QString &description)
0232 {
0233     m_description = description;
0234     Q_EMIT descriptionChanged(m_description);
0235 }
0236 
0237 void Feed::setGroupName(const QString &groupName)
0238 {
0239     if (m_group_name != groupName) {
0240         m_group_name = groupName;
0241 
0242         Q_EMIT groupNameChanged(groupName);
0243     }
0244 }
0245 
0246 void Feed::setAuthors(const QVector<Author *> &authors)
0247 {
0248     m_authors = authors;
0249     Q_EMIT authorsChanged(m_authors);
0250 }
0251 
0252 void Feed::setDeleteAfterCount(int count)
0253 {
0254     m_deleteAfterCount = count;
0255     Q_EMIT deleteAfterCountChanged(m_deleteAfterCount);
0256 }
0257 
0258 void Feed::setDeleteAfterType(int type)
0259 {
0260     m_deleteAfterType = type;
0261     Q_EMIT deleteAfterTypeChanged(m_deleteAfterType);
0262 }
0263 
0264 void Feed::setLastUpdated(const QDateTime &lastUpdated)
0265 {
0266     m_lastUpdated = lastUpdated;
0267     Q_EMIT lastUpdatedChanged(m_lastUpdated);
0268 }
0269 
0270 void Feed::setNotify(bool notify)
0271 {
0272     m_notify = notify;
0273     Q_EMIT notifyChanged(m_notify);
0274 }
0275 
0276 void Feed::setRefreshing(bool refreshing)
0277 {
0278     m_refreshing = refreshing;
0279     Q_EMIT refreshingChanged(m_refreshing);
0280 }
0281 
0282 void Feed::setErrorId(int errorId)
0283 {
0284     m_errorId = errorId;
0285     Q_EMIT errorIdChanged(m_errorId);
0286 }
0287 
0288 void Feed::setErrorString(const QString &errorString)
0289 {
0290     m_errorString = errorString;
0291     Q_EMIT errorStringChanged(m_errorString);
0292 }
0293 
0294 void Feed::refresh()
0295 {
0296     Fetcher::instance().fetch(m_url);
0297 }
0298 
0299 void Feed::remove()
0300 {
0301     // Delete Authors
0302     QSqlQuery query;
0303     if (query.prepare(QStringLiteral("DELETE FROM Authors WHERE feed=:feed;"))) {
0304         query.bindValue(QStringLiteral(":feed"), m_url);
0305         Database::instance().execute(query);
0306     }
0307 
0308     // Delete Entries
0309     if (query.prepare(QStringLiteral("DELETE FROM Entries WHERE feed=:feed;"))) {
0310         query.bindValue(QStringLiteral(":feed"), m_url);
0311         Database::instance().execute(query);
0312     }
0313 
0314     // TODO Delete Enclosures
0315 
0316     // Delete Feed
0317     if (query.prepare(QStringLiteral("DELETE FROM Feeds WHERE url=:url;"))) {
0318         query.bindValue(QStringLiteral(":url"), m_url);
0319         Database::instance().execute(query);
0320     }
0321 }