mirror of https://github.com/KDE/kasts.git
Refactor Error implementation and add Error::Type
- This refactoring also includes a cleanup of a lot of header includes to avoid circular dependencies. - The error message will now be shown below the info message. - Add database migration (for Errors)
This commit is contained in:
parent
719879072e
commit
49977adc38
|
@ -19,7 +19,7 @@ set(SRCS_base
|
|||
audiomanager.cpp
|
||||
powermanagementinterface.cpp
|
||||
errorlogmodel.cpp
|
||||
error.h
|
||||
error.cpp
|
||||
mpris2/mpris2.cpp
|
||||
resources.qrc
|
||||
)
|
||||
|
|
|
@ -39,8 +39,11 @@ Database::Database()
|
|||
|
||||
bool Database::migrate()
|
||||
{
|
||||
if (version() < 1)
|
||||
int dbversion = version();
|
||||
if (dbversion < 1)
|
||||
TRUE_OR_RETURN(migrateTo1());
|
||||
if (dbversion < 2)
|
||||
TRUE_OR_RETURN(migrateTo2());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -56,13 +59,22 @@ bool Database::migrateTo1()
|
|||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Authors (feed TEXT, id TEXT, name TEXT, uri TEXT, email TEXT);")));
|
||||
TRUE_OR_RETURN(
|
||||
execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Enclosures (feed TEXT, id TEXT, duration INTEGER, size INTEGER, title TEXT, type TEXT, url TEXT, "
|
||||
"playposition INTEGER, downloaded BOOL);"))); //, filename TEXT);")));
|
||||
"playposition INTEGER, downloaded BOOL);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Queue (listnr INTEGER, feed TEXT, id TEXT, playing BOOL);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Errors (url TEXT, id TEXT, code INTEGER, message TEXT, date INTEGER);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("PRAGMA user_version = 1;")));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::migrateTo2()
|
||||
{
|
||||
qDebug() << "Migrating database to version 2";
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("DROP TABLE Errors;")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Errors (type INTEGER, url TEXT, id TEXT, code INTEGER, message TEXT, date INTEGER);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("PRAGMA user_version = 2;")));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::execute(const QString &query)
|
||||
{
|
||||
QSqlQuery q;
|
||||
|
|
|
@ -28,5 +28,6 @@ private:
|
|||
|
||||
bool migrate();
|
||||
bool migrateTo1();
|
||||
bool migrateTo2();
|
||||
void cleanup();
|
||||
};
|
||||
|
|
|
@ -5,9 +5,12 @@
|
|||
*/
|
||||
|
||||
#include "datamanager.h"
|
||||
|
||||
#include "audiomanager.h"
|
||||
#include "database.h"
|
||||
#include "datamanagerlogging.h"
|
||||
#include "entry.h"
|
||||
#include "feed.h"
|
||||
#include "fetcher.h"
|
||||
#include "settingsmanager.h"
|
||||
#include <QDateTime>
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "entry.h"
|
||||
#include "episodemodel.h"
|
||||
#include "feed.h"
|
||||
|
||||
class Entry;
|
||||
class Feed;
|
||||
|
||||
class DataManager : public QObject
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "downloadprogressmodel.h"
|
||||
#include "enclosuredownloadjob.h"
|
||||
#include "entry.h"
|
||||
#include "error.h"
|
||||
#include "errorlogmodel.h"
|
||||
#include "fetcher.h"
|
||||
|
||||
|
@ -110,7 +111,7 @@ void Enclosure::download()
|
|||
if (downloadJob->error() != QNetworkReply::OperationCanceledError) {
|
||||
m_entry->feed()->setErrorId(downloadJob->error());
|
||||
m_entry->feed()->setErrorString(downloadJob->errorString());
|
||||
Q_EMIT downloadError(m_entry->feed()->url(), m_entry->id(), downloadJob->error(), downloadJob->errorString());
|
||||
Q_EMIT downloadError(Error::Type::MediaDownload, m_entry->feed()->url(), m_entry->id(), downloadJob->error(), downloadJob->errorString());
|
||||
}
|
||||
}
|
||||
disconnect(this, &Enclosure::cancelDownload, this, nullptr);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <KFormat>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
class Entry;
|
||||
|
||||
class Enclosure : public QObject
|
||||
|
@ -66,7 +68,7 @@ Q_SIGNALS:
|
|||
void playPositionChanged();
|
||||
void durationChanged();
|
||||
void sizeChanged();
|
||||
void downloadError(const QString &url, const QString &id, const int errorId, const QString &errorString);
|
||||
void downloadError(const Error::Type type, const QString &url, const QString &id, const int errorId, const QString &errorString);
|
||||
|
||||
private:
|
||||
void processDownloadedFile();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "datamanager.h"
|
||||
#include "entriesmodel.h"
|
||||
#include "entry.h"
|
||||
#include "feed.h"
|
||||
|
||||
EntriesModel::EntriesModel(Feed *feed)
|
||||
: QAbstractListModel(feed)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <QObject>
|
||||
#include <QVariant>
|
||||
|
||||
#include "feed.h"
|
||||
class Feed;
|
||||
|
||||
class EntriesModel : public QAbstractListModel
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "database.h"
|
||||
#include "datamanager.h"
|
||||
#include "feed.h"
|
||||
#include "fetcher.h"
|
||||
|
||||
Entry::Entry(Feed *feed, const QString &id)
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
#include "author.h"
|
||||
#include "enclosure.h"
|
||||
#include "feed.h"
|
||||
|
||||
class Feed;
|
||||
|
||||
class Entry : public QObject
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "episodemodel.h"
|
||||
#include "datamanager.h"
|
||||
#include "entry.h"
|
||||
|
||||
EpisodeModel::EpisodeModel()
|
||||
: QAbstractListModel(nullptr)
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#include "datamanager.h"
|
||||
#include "entry.h"
|
||||
#include "error.h"
|
||||
#include "feed.h"
|
||||
|
||||
Error::Error(const Type type, const QString url, const QString id, const int code, const QString message, const QDateTime date)
|
||||
: QObject(nullptr)
|
||||
{
|
||||
this->type = type;
|
||||
this->url = url;
|
||||
this->id = id;
|
||||
this->code = code;
|
||||
this->message = message;
|
||||
this->date = date;
|
||||
};
|
||||
|
||||
QString Error::title() const
|
||||
{
|
||||
QString title;
|
||||
if (!id.isEmpty()) {
|
||||
if (DataManager::instance().getEntry(id))
|
||||
title = DataManager::instance().getEntry(id)->title();
|
||||
} else if (!url.isEmpty()) {
|
||||
if (DataManager::instance().getFeed(url))
|
||||
title = DataManager::instance().getFeed(url)->name();
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
QString Error::description() const
|
||||
{
|
||||
switch (type) {
|
||||
case Error::Type::FeedUpdate:
|
||||
return i18n("Podcast Update Error");
|
||||
case Error::Type::MediaDownload:
|
||||
return i18n("Media Download Error");
|
||||
case Error::Type::MeteredNotAllowed:
|
||||
return i18n("Update Not Allowed on Metered Connection");
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
int Error::typeToDb(Error::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Error::Type::FeedUpdate:
|
||||
return 0;
|
||||
case Error::Type::MediaDownload:
|
||||
return 1;
|
||||
case Error::Type::MeteredNotAllowed:
|
||||
return 2;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Error::Type Error::dbToType(int value)
|
||||
{
|
||||
switch (value) {
|
||||
case 0:
|
||||
return Error::Type::FeedUpdate;
|
||||
case 1:
|
||||
return Error::Type::MediaDownload;
|
||||
case 2:
|
||||
return Error::Type::MeteredNotAllowed;
|
||||
default:
|
||||
return Error::Type::Unknown;
|
||||
}
|
||||
}
|
42
src/error.h
42
src/error.h
|
@ -6,7 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "datamanager.h"
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
@ -15,40 +14,35 @@ class Error : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Type {
|
||||
Unknown,
|
||||
FeedUpdate,
|
||||
MediaDownload,
|
||||
MeteredNotAllowed,
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
|
||||
static int typeToDb(Type type); // needed to translate Error::Type values to int for sqlite
|
||||
static Type dbToType(int value); // needed to translate from int to Error::Type values for sqlite
|
||||
|
||||
Q_PROPERTY(QString url MEMBER url CONSTANT)
|
||||
Q_PROPERTY(QString id MEMBER id CONSTANT)
|
||||
Q_PROPERTY(int code MEMBER code CONSTANT)
|
||||
Q_PROPERTY(QString message MEMBER message CONSTANT)
|
||||
Q_PROPERTY(QDateTime date MEMBER date CONSTANT)
|
||||
Q_PROPERTY(QString title READ title CONSTANT)
|
||||
Q_PROPERTY(QString description READ description CONSTANT)
|
||||
|
||||
public:
|
||||
Error(const QString url, const QString id, const int code, const QString message, const QDateTime date)
|
||||
: QObject(nullptr)
|
||||
{
|
||||
this->url = url;
|
||||
this->id = id;
|
||||
this->code = code;
|
||||
this->message = message;
|
||||
this->date = date;
|
||||
};
|
||||
Error(Type type, const QString url, const QString id, const int code, const QString message, const QDateTime date);
|
||||
|
||||
QString title() const;
|
||||
QString description() const;
|
||||
|
||||
Type type;
|
||||
QString url;
|
||||
QString id;
|
||||
int code;
|
||||
QString message;
|
||||
QDateTime date;
|
||||
|
||||
QString title() const
|
||||
{
|
||||
QString title;
|
||||
if (!id.isEmpty()) {
|
||||
if (DataManager::instance().getEntry(id))
|
||||
title = DataManager::instance().getEntry(id)->title();
|
||||
} else if (!url.isEmpty()) {
|
||||
if (DataManager::instance().getFeed(url))
|
||||
title = DataManager::instance().getFeed(url)->name();
|
||||
}
|
||||
return title;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -21,11 +21,10 @@ ErrorLogModel::ErrorLogModel()
|
|||
query.prepare(QStringLiteral("SELECT * FROM Errors ORDER BY date DESC;"));
|
||||
Database::instance().execute(query);
|
||||
while (query.next()) {
|
||||
QString id = query.value(QStringLiteral("id")).toString();
|
||||
QString url = query.value(QStringLiteral("url")).toString();
|
||||
Error *error = new Error(Error::dbToType(query.value(QStringLiteral("type")).toInt()),
|
||||
query.value(QStringLiteral("url")).toString(),
|
||||
query.value(QStringLiteral("id")).toString(),
|
||||
|
||||
Error *error = new Error(url,
|
||||
id,
|
||||
query.value(QStringLiteral("code")).toInt(),
|
||||
query.value(QStringLiteral("message")).toString(),
|
||||
QDateTime::fromSecsSinceEpoch(query.value(QStringLiteral("date")).toInt()));
|
||||
|
@ -54,19 +53,20 @@ int ErrorLogModel::rowCount(const QModelIndex &parent) const
|
|||
return m_errors.count();
|
||||
}
|
||||
|
||||
void ErrorLogModel::monitorErrorMessages(const QString &url, const QString &id, const int errorCode, const QString &errorString)
|
||||
void ErrorLogModel::monitorErrorMessages(const Error::Type type, const QString &url, const QString &id, const int errorCode, const QString &errorString)
|
||||
{
|
||||
qDebug() << "Error happened:" << url << id << errorCode << errorString;
|
||||
qDebug() << "Error happened:" << type << url << id << errorCode << errorString;
|
||||
QString title;
|
||||
|
||||
Error *error = new Error(url, id, errorCode, errorString, QDateTime::currentDateTime());
|
||||
Error *error = new Error(type, url, id, errorCode, errorString, QDateTime::currentDateTime());
|
||||
beginInsertRows(QModelIndex(), 0, 0);
|
||||
m_errors.prepend(error);
|
||||
endInsertRows();
|
||||
|
||||
// Also add error to database
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("INSERT INTO Errors VALUES (:url, :id, :code, :message, :date);"));
|
||||
query.prepare(QStringLiteral("INSERT INTO Errors VALUES (:type, :url, :id, :code, :message, :date);"));
|
||||
query.bindValue(QStringLiteral(":type"), Error::typeToDb(error->type));
|
||||
query.bindValue(QStringLiteral(":url"), error->url);
|
||||
query.bindValue(QStringLiteral(":id"), error->id);
|
||||
query.bindValue(QStringLiteral(":code"), error->code);
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
Q_INVOKABLE void clearAll();
|
||||
|
||||
public:
|
||||
void monitorErrorMessages(const QString &url, const QString &id, const int errorCode, const QString &errorString);
|
||||
void monitorErrorMessages(const Error::Type type, const QString &url, const QString &id, const int errorCode, const QString &errorString);
|
||||
|
||||
Q_SIGNALS:
|
||||
void newErrorLogged(Error *error);
|
||||
|
|
22
src/feed.cpp
22
src/feed.cpp
|
@ -7,9 +7,11 @@
|
|||
|
||||
#include <QVariant>
|
||||
|
||||
#include "author.h"
|
||||
#include "database.h"
|
||||
#include "datamanager.h"
|
||||
#include "entriesmodel.h"
|
||||
#include "error.h"
|
||||
#include "feed.h"
|
||||
#include "feedlogging.h"
|
||||
#include "fetcher.h"
|
||||
|
@ -57,14 +59,18 @@ Feed::Feed(const QString &feedurl)
|
|||
setErrorString(QLatin1String(""));
|
||||
}
|
||||
});
|
||||
connect(&Fetcher::instance(), &Fetcher::error, this, [this](const QString &url, const QString &id, int errorId, const QString &errorString) {
|
||||
Q_UNUSED(id)
|
||||
if (url == m_url) {
|
||||
setErrorId(errorId);
|
||||
setErrorString(errorString);
|
||||
setRefreshing(false);
|
||||
}
|
||||
});
|
||||
connect(&Fetcher::instance(),
|
||||
&Fetcher::error,
|
||||
this,
|
||||
[this](const Error::Type type, const QString &url, const QString &id, int errorId, const QString &errorString) {
|
||||
Q_UNUSED(type)
|
||||
Q_UNUSED(id)
|
||||
if (url == m_url) {
|
||||
setErrorId(errorId);
|
||||
setErrorString(errorString);
|
||||
setRefreshing(false);
|
||||
}
|
||||
});
|
||||
connect(&Fetcher::instance(), &Fetcher::feedUpdateFinished, this, [this](const QString &url) {
|
||||
if (url == m_url) {
|
||||
setRefreshing(false);
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "author.h"
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ void Fetcher::retrieveFeed(const QString &url)
|
|||
if (reply->error()) {
|
||||
qWarning() << "Error fetching feed";
|
||||
qWarning() << reply->errorString();
|
||||
Q_EMIT error(url, QString(), reply->error(), reply->errorString());
|
||||
Q_EMIT error(Error::Type::FeedUpdate, url, QString(), reply->error(), reply->errorString());
|
||||
} else {
|
||||
QByteArray data = reply->readAll();
|
||||
Syndication::DocumentSource *document = new Syndication::DocumentSource(data, url);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <QUrl>
|
||||
#include <Syndication/Syndication>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
class Fetcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -35,6 +37,7 @@ public:
|
|||
Q_INVOKABLE QString image(const QString &url) const;
|
||||
void removeImage(const QString &url);
|
||||
Q_INVOKABLE QNetworkReply *download(const QString &url, const QString &fileName) const;
|
||||
|
||||
QString imagePath(const QString &url) const;
|
||||
QString enclosurePath(const QString &url) const;
|
||||
|
||||
|
@ -48,7 +51,7 @@ Q_SIGNALS:
|
|||
const QString &description,
|
||||
const QDateTime &lastUpdated);
|
||||
void feedUpdateFinished(const QString &url);
|
||||
void error(const QString &url, const QString &id, const int errorId, const QString &errorString);
|
||||
void error(Error::Type type, const QString &url, const QString &id, const int errorId, const QString &errorString);
|
||||
void entryAdded(const QString &feedurl, const QString &id);
|
||||
void downloadFinished(QString url) const;
|
||||
void downloadFileSizeUpdated(QString url, int fileSize) const;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <QLoggingCategory>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlContext>
|
||||
|
||||
#include <QQuickStyle>
|
||||
#include <QQuickView>
|
||||
#include <QString>
|
||||
|
@ -35,8 +36,10 @@
|
|||
#include "datamanager.h"
|
||||
#include "downloadprogressmodel.h"
|
||||
#include "entriesmodel.h"
|
||||
#include "entry.h"
|
||||
#include "episodemodel.h"
|
||||
#include "errorlogmodel.h"
|
||||
#include "feed.h"
|
||||
#include "feedsmodel.h"
|
||||
#include "fetcher.h"
|
||||
#include "kasts-version.h"
|
||||
|
@ -129,6 +132,7 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterSingletonInstance("org.kde.kasts", 1, 0, "AudioManager", &AudioManager::instance());
|
||||
|
||||
qRegisterMetaType<Entry *>("const Entry*"); // "hack" to make qml understand Entry*
|
||||
qRegisterMetaType<Feed *>("const Feed*"); // "hack" to make qml understand Feed*
|
||||
|
||||
// Make sure that settings are saved before the application exits
|
||||
QObject::connect(&app, &QCoreApplication::aboutToQuit, SettingsManager::self(), &SettingsManager::save);
|
||||
|
|
|
@ -8,6 +8,7 @@ import QtQuick 2.14
|
|||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.14
|
||||
import QtGraphicalEffects 1.15
|
||||
|
||||
import org.kde.kirigami 2.15 as Kirigami
|
||||
|
||||
import org.kde.kasts 1.0
|
||||
|
@ -40,7 +41,7 @@ Kirigami.ScrollablePage {
|
|||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Controls.Label {
|
||||
text: ( (error.id) ? i18n("Media Download Error") : i18n("Podcast Update Error") ) + " · " + error.date.toLocaleDateString(Qt.locale(), Locale.NarrowFormat) + " · " + error.date.toLocaleTimeString(Qt.locale(), Locale.NarrowFormat)
|
||||
text: error.description + " · " + error.date.toLocaleDateString(Qt.locale(), Locale.NarrowFormat) + " · " + error.date.toLocaleTimeString(Qt.locale(), Locale.NarrowFormat)
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
font: Kirigami.Theme.smallFont
|
||||
|
@ -54,7 +55,7 @@ Kirigami.ScrollablePage {
|
|||
opacity: 1
|
||||
}
|
||||
Controls.Label {
|
||||
text: i18n("Error Code: ") + error.code + (error.message ? " · " + error.message : "")
|
||||
text: i18n("Error Code: ") + error.code + (error.message ? " · " + error.message : "")
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
font: Kirigami.Theme.smallFont
|
||||
|
|
|
@ -203,7 +203,7 @@ Kirigami.ApplicationWindow {
|
|||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: bottomMessageSpacing
|
||||
bottomMargin: bottomMessageSpacing + ( inlineMessage.visible ? inlineMessage.height + Kirigami.Units.largeSpacing : 0 )
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +214,7 @@ Kirigami.ApplicationWindow {
|
|||
right: parent.right
|
||||
left: parent.left
|
||||
margins: Kirigami.Units.gridUnit
|
||||
bottomMargin: bottomMessageSpacing + ( updateNotification.visible ? updateNotification.height + Kirigami.Units.largeSpacing : 0 )
|
||||
bottomMargin: bottomMessageSpacing
|
||||
}
|
||||
type: Kirigami.MessageType.Error
|
||||
showCloseButton: true
|
||||
|
@ -222,7 +222,7 @@ Kirigami.ApplicationWindow {
|
|||
Connections {
|
||||
target: ErrorLogModel
|
||||
function onNewErrorLogged(error) {
|
||||
inlineMessage.text = error.id ? i18n("Media Download Error") : i18n("Podcast Update Error") + "\n" + i18n("Check Error Log Tab (under Downloads) for more details.");
|
||||
inlineMessage.text = error.description + "\n" + i18n("Check Error Log Tab (under Downloads) for more details");
|
||||
inlineMessage.visible = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue