mirror of
https://github.com/KDE/kasts.git
synced 2025-02-02 10:26:52 +01:00
Rework the database system
This commit is contained in:
parent
5168e06147
commit
a6f6969912
@ -5,6 +5,7 @@ set(alligator_SRCS
|
||||
fetcher.cpp
|
||||
feed.cpp
|
||||
entry.cpp
|
||||
database.cpp
|
||||
resources.qrc
|
||||
)
|
||||
|
||||
|
89
src/database.cpp
Normal file
89
src/database.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright 2020 Tobias Fella <fella@posteo.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QSqlError>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "database.h"
|
||||
#include "alligator-debug.h"
|
||||
|
||||
#define TRUE_OR_RETURN(x) if(!x) return false;
|
||||
|
||||
Database::Database()
|
||||
{
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
|
||||
QString databasePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir(databasePath).mkpath(databasePath);
|
||||
db.setDatabaseName(databasePath + QStringLiteral("/database.db3"));
|
||||
qCDebug(ALLIGATOR) << "Opening database " << databasePath << "/database.db3";
|
||||
db.open();
|
||||
|
||||
if(!migrate()) {
|
||||
qCCritical(ALLIGATOR) << "Failed to migrate the database";
|
||||
}
|
||||
}
|
||||
|
||||
bool Database::migrate() {
|
||||
qCDebug(ALLIGATOR) << "Migrating database";
|
||||
if(version() < 1) TRUE_OR_RETURN(migrateTo1());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::migrateTo1() {
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Feeds (name TEXT, url TEXT);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Entries (feed TEXT, id TEXT, title TEXT, content TEXT);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Authors (id TEXT, name TEXT, uri TEXT, email TEXT);")));
|
||||
TRUE_OR_RETURN(execute(QStringLiteral("PRAGMA user_version = 1;")));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Database::execute(QString query) {
|
||||
QSqlQuery q;
|
||||
q.prepare(query);
|
||||
return execute(q);
|
||||
}
|
||||
|
||||
bool Database::execute(QSqlQuery &query) {
|
||||
if(!query.exec()) {
|
||||
qCWarning(ALLIGATOR) << "Failed to execute SQL Query";
|
||||
qCWarning(ALLIGATOR) << query.lastQuery();
|
||||
qCWarning(ALLIGATOR) << query.lastError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int Database::version() {
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("PRAGMA user_version;"));
|
||||
execute(query);
|
||||
if(query.next()) {
|
||||
bool ok;
|
||||
int value = query.value(0).toInt(&ok);
|
||||
qCDebug(ALLIGATOR) << "Database version " << value;
|
||||
if(ok) return value;
|
||||
} else {
|
||||
qCCritical(ALLIGATOR) << "Failed to check database version";
|
||||
}
|
||||
return -1;
|
||||
}
|
42
src/database.h
Normal file
42
src/database.h
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2020 Tobias Fella <fella@posteo.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License or (at your option) version 3 or any later version
|
||||
* accepted by the membership of KDE e.V. (or its successor approved
|
||||
* by the membership of KDE e.V.), which shall act as a proxy
|
||||
* defined in Section 14 of version 3 of the license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
class Database
|
||||
{
|
||||
public:
|
||||
static Database &instance()
|
||||
{
|
||||
static Database _instance;
|
||||
return _instance;
|
||||
}
|
||||
bool execute(QSqlQuery &query);
|
||||
bool execute(QString query);
|
||||
|
||||
private:
|
||||
Database();
|
||||
int version();
|
||||
|
||||
bool migrate();
|
||||
bool migrateTo1();
|
||||
};
|
@ -18,12 +18,11 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QVector>
|
||||
|
||||
#include "entryListModel.h"
|
||||
#include "fetcher.h"
|
||||
#include "database.h"
|
||||
|
||||
EntryListModel::EntryListModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
@ -70,10 +69,10 @@ void EntryListModel::fetch()
|
||||
{
|
||||
connect(&Fetcher::instance(), &Fetcher::finished, this, [this]() {
|
||||
beginResetModel();
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("SELECT id, title, content FROM Entries WHERE feed=:feed;"));
|
||||
query.bindValue(QStringLiteral(":feed"), m_feed);
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
while (query.next()) {
|
||||
m_entries.append(Entry(query.value(1).toString(), query.value(2).toString(), false, false));
|
||||
}
|
||||
|
@ -18,21 +18,22 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QUrl>
|
||||
#include <QSqlError>
|
||||
|
||||
#include <Syndication/Syndication>
|
||||
|
||||
#include "feedListModel.h"
|
||||
#include "fetcher.h"
|
||||
#include "database.h"
|
||||
|
||||
#include "alligator-debug.h"
|
||||
|
||||
FeedListModel::FeedListModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
query.exec(QStringLiteral("SELECT name, url FROM Feeds"));
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("SELECT name, url FROM Feeds"));
|
||||
Database::instance().execute(query);
|
||||
beginInsertRows(QModelIndex(), 0, query.size());
|
||||
while (query.next()) {
|
||||
feeds += Feed(query.value(1).toString(), query.value(0).toString());
|
||||
@ -63,11 +64,17 @@ int FeedListModel::rowCount(const QModelIndex &index) const
|
||||
|
||||
void FeedListModel::addFeed(QString url)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("SELECT COUNT (url) FROM Feeds WHERE url=:url;"));
|
||||
query.bindValue(QStringLiteral(":url"), url);
|
||||
Database::instance().execute(query);
|
||||
query.next();
|
||||
if(query.value(0).toInt() != 0) return;
|
||||
connect(&Fetcher::instance(), &Fetcher::finished, this, [this, url]() {
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("SELECT name FROM Feeds WHERE url=:url;"));
|
||||
query.bindValue(QStringLiteral(":url"), url);
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
query.next();
|
||||
for(int i = 0; i < feeds.length(); i++) {
|
||||
if(feeds[i].url() == url) {
|
||||
@ -82,21 +89,21 @@ void FeedListModel::addFeed(QString url)
|
||||
beginInsertRows(QModelIndex(), feeds.size(), feeds.size());
|
||||
feeds.append(Feed(url));
|
||||
endInsertRows();
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
|
||||
query.prepare(QStringLiteral("INSERT INTO Feeds VALUES (:url, :name);"));
|
||||
query.bindValue(QStringLiteral(":url"), url);
|
||||
query.bindValue(QStringLiteral(":name"), url);
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
}
|
||||
|
||||
void FeedListModel::remove_feed(int index)
|
||||
{
|
||||
Feed toRemove = feeds[index];
|
||||
QSqlQuery query(QSqlDatabase::database());
|
||||
QSqlQuery query;
|
||||
query.prepare(QStringLiteral("DELETE FROM Feeds WHERE name=:name AND url=url;"));
|
||||
query.bindValue(QStringLiteral(":url"), toRemove.url());
|
||||
query.bindValue(QStringLiteral(":name"), toRemove.name());
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
feeds.remove(index);
|
||||
endRemoveRows();
|
||||
|
@ -20,13 +20,13 @@
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include <Syndication/Syndication>
|
||||
|
||||
#include "fetcher.h"
|
||||
|
||||
#include "database.h"
|
||||
|
||||
Fetcher::Fetcher() {
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ void Fetcher::fetch(QUrl url)
|
||||
QSqlQuery query(db);
|
||||
|
||||
for (const auto &entry : feed->items()) {
|
||||
query = QSqlQuery(db);
|
||||
query.prepare(QStringLiteral("INSERT INTO Entries VALUES (:feed, :id, :title, :content);"));
|
||||
query.bindValue(QStringLiteral(":feed"), url.toString());
|
||||
query.bindValue(QStringLiteral(":id"), entry->id());
|
||||
@ -56,7 +55,7 @@ void Fetcher::fetch(QUrl url)
|
||||
query.bindValue(QStringLiteral(":content"), entry->content());
|
||||
else
|
||||
query.bindValue(QStringLiteral(":content"), entry->description());
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
for (const auto &author : entry->authors()) {
|
||||
query = QSqlQuery(db);
|
||||
query.prepare(QStringLiteral("INSERT INTO Authors VALUES(:id, :name, :uri, :email);"));
|
||||
@ -64,12 +63,12 @@ void Fetcher::fetch(QUrl url)
|
||||
query.bindValue(QStringLiteral(":name"), author->name());
|
||||
query.bindValue(QStringLiteral(":uri"), author->uri());
|
||||
query.bindValue(QStringLiteral(":email"), author->email());
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
}
|
||||
query.prepare(QStringLiteral("UPDATE Feeds SET name=:name WHERE url=:url;"));
|
||||
query.bindValue(QStringLiteral(":name"), feed->title());
|
||||
query.bindValue(QStringLiteral(":url"), url.toString());
|
||||
query.exec();
|
||||
Database::instance().execute(query);
|
||||
}
|
||||
delete reply;
|
||||
emit finished();
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -21,14 +21,10 @@
|
||||
#include <QApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQuickView>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QUrl>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
|
||||
#include "entryListModel.h"
|
||||
#include "feedListModel.h"
|
||||
#include "database.h"
|
||||
|
||||
#include "alligator-debug.h"
|
||||
|
||||
@ -48,16 +44,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
|
||||
QString databasePath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir(databasePath).mkpath(databasePath);
|
||||
db.setDatabaseName(databasePath + "/database.db3");
|
||||
db.open();
|
||||
|
||||
QSqlQuery query(db);
|
||||
query.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS Feeds (name TEXT, url TEXT);"));
|
||||
query.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS Entries (feed TEXT, id TEXT UNIQUE, title TEXT, content TEXT);"));
|
||||
query.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS Authors (id TEXT, name TEXT, uri TEXT, email TEXT);"));
|
||||
Database::instance();
|
||||
|
||||
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user