Merge branch 'master' of invent.kde.org:kde/alligator

This commit is contained in:
Tobias Fella 2020-04-23 13:52:30 +02:00
commit 6e204c6ec9
12 changed files with 133 additions and 48 deletions

View File

@ -7,7 +7,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.alligator"
android:versionName="0.0.1"
android:versionCode="1587507847"
android:versionCode="1587578760"
android:installLocation="auto">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Alligator" android:icon="@drawable/alligator">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
@ -42,6 +42,9 @@
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Splash screen -->
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
<!-- Background running -->
<meta-data android:name="android.app.background_running" android:value="false"/>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="128dp" android:height="128dp" android:gravity="center">
<bitmap
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="@drawable/alligator"/>
</item>
</layer-list>

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -2,12 +2,32 @@
<component type="desktop-application">
<id>org.kde.mobile.alligator</id>
<name>Alligator</name>
<name xml:lang="ca">Alligator</name>
<name xml:lang="et">Alligator</name>
<name xml:lang="nl">Alligator</name>
<name xml:lang="uk">Alligator</name>
<name xml:lang="x-test">xxAlligatorxx</name>
<summary>Feed reader for mobile devices</summary>
<summary xml:lang="ca">Lector de fonts per a dispositius mòbils</summary>
<summary xml:lang="et">Mobiilseadmete uudistelugeja</summary>
<summary xml:lang="nl">Feedlezer voor mobiele apparaten</summary>
<summary xml:lang="uk">Програма для читання подач на мобільних пристроях</summary>
<summary xml:lang="x-test">xxFeed reader for mobile devicesxx</summary>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<developer_name>KDE Community</developer_name>
<description>
<developer_name xml:lang="ca">La comunitat KDE</developer_name>
<developer_name xml:lang="et">KDE kogukond</developer_name>
<developer_name xml:lang="nl">KDE gemeenschap</developer_name>
<developer_name xml:lang="uk">Спільнота KDE</developer_name>
<developer_name xml:lang="x-test">xxKDE Communityxx</developer_name>
<description>
<p>Alligator is a mobile feed reader</p>
<p xml:lang="ca">L'Alligator és un lector de fonts per a mòbil</p>
<p xml:lang="et">Alligator on mobiilide uudistelugeja</p>
<p xml:lang="nl">Alligator is een mobiele feedlezer</p>
<p xml:lang="uk">Alligator — програма для читання подач на мобільних пристроях</p>
<p xml:lang="x-test">xxAlligator is a mobile feed readerxx</p>
</description>
<provides>
<binary>alligator</binary>

View File

@ -1,9 +1,24 @@
[Desktop Entry]
Name=Alligator
Name[ca]=Alligator
Name[et]=Alligator
Name[nl]=Alligator
Name[uk]=Alligator
Name[x-test]=xxAlligatorxx
Comment=Mobile Feed Reader
Comment[ca]=Lector de fonts per a mòbil
Comment[et]=Mobiili uudistelugeja
Comment[nl]=Mobiele feedlezer
Comment[uk]=Програма для читання подач на мобільному
Comment[x-test]=xxMobile Feed Readerxx
GenericName=Feed Reader
GenericName[ca]=Lector de fonts
GenericName[et]=Uudistelugeja
GenericName[nl]=Feedlezer
GenericName[uk]=Читання подач
GenericName[x-test]=xxFeed Readerxx
Encoding=UTF-8
Icon=org.kde.mobile.alligator
Icon=alligator
Exec=alligator
Type=Application
Categories=Qt;KDE;RSS;

View File

@ -18,16 +18,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QDir>
#include <QStandardPaths>
#include <QSqlError>
#include <QSqlDatabase>
#include <QDateTime>
#include <QDir>
#include <QSqlDatabase>
#include <QSqlError>
#include <QStandardPaths>
#include "database.h"
#include "alligatorsettings.h"
#include "database.h"
#define TRUE_OR_RETURN(x) if(!x) return false;
#define TRUE_OR_RETURN(x) \
if (!x) \
return false;
Database::Database()
{
@ -37,19 +39,22 @@ Database::Database()
db.setDatabaseName(databasePath + QStringLiteral("/database.db3"));
db.open();
if(!migrate()) {
if (!migrate()) {
qCritical() << "Failed to migrate the database";
}
cleanup();
}
bool Database::migrate() {
if(version() < 1) TRUE_OR_RETURN(migrateTo1());
bool Database::migrate()
{
if (version() < 1)
TRUE_OR_RETURN(migrateTo1());
return true;
}
bool Database::migrateTo1() {
bool Database::migrateTo1()
{
qDebug() << "Migrating database to version 1";
QSqlQuery query(QSqlDatabase::database());
TRUE_OR_RETURN(execute(QStringLiteral("CREATE TABLE IF NOT EXISTS Feeds (name TEXT, url TEXT, image TEXT);")));
@ -59,14 +64,16 @@ bool Database::migrateTo1() {
return true;
}
bool Database::execute(QString query) {
bool Database::execute(QString query)
{
QSqlQuery q;
q.prepare(query);
return execute(q);
}
bool Database::execute(QSqlQuery &query) {
if(!query.exec()) {
bool Database::execute(QSqlQuery &query)
{
if (!query.exec()) {
qWarning() << "Failed to execute SQL Query";
qWarning() << query.lastQuery();
qWarning() << query.lastError();
@ -75,33 +82,39 @@ bool Database::execute(QSqlQuery &query) {
return true;
}
int Database::version() {
int Database::version()
{
QSqlQuery query;
query.prepare(QStringLiteral("PRAGMA user_version;"));
execute(query);
if(query.next()) {
if (query.next()) {
bool ok;
int value = query.value(0).toInt(&ok);
qDebug() << "Database version " << value;
if(ok) return value;
if (ok)
return value;
} else {
qCritical() << "Failed to check database version";
}
return -1;
}
void Database::cleanup() {
void Database::cleanup()
{
AlligatorSettings settings;
int count = settings.deleteAfterCount();
int type = settings.deleteAfterType();
if(type == 0) { // Delete after <count> posts per feed
//TODO
if (type == 0) { // Delete after <count> posts per feed
// TODO
} else {
QDateTime dateTime = QDateTime::currentDateTime();
if(type == 1) dateTime = dateTime.addDays(-count);
else if(type == 2) dateTime = dateTime.addDays(-7*count);
else if(type == 3) dateTime = dateTime.addMonths(-count);
if (type == 1)
dateTime = dateTime.addDays(-count);
else if (type == 2)
dateTime = dateTime.addDays(-7 * count);
else if (type == 3)
dateTime = dateTime.addMonths(-count);
qint64 sinceEpoch = dateTime.toSecsSinceEpoch();
QSqlQuery query;

View File

@ -18,12 +18,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QVector>
#include <QDateTime>
#include <QVector>
#include "database.h"
#include "entryListModel.h"
#include "fetcher.h"
#include "database.h"
EntryListModel::EntryListModel(QObject *parent)
: QSqlTableModel(parent)
@ -36,12 +36,12 @@ EntryListModel::EntryListModel(QObject *parent)
QVariant EntryListModel::data(const QModelIndex &index, int role) const
{
if(role == Updated || role == Created) {
if (role == Updated || role == Created) {
QDateTime updated;
updated.setSecsSinceEpoch(QSqlQueryModel::data(createIndex(index.row(), role), 0).toInt());
return updated;
}
return QSqlQueryModel::data(createIndex(index.row(), role), 0);
return QSqlQueryModel::data(createIndex(index.row(), role), 0);
}
QHash<int, QByteArray> EntryListModel::roleNames() const

View File

@ -20,8 +20,8 @@
#pragma once
#include <QSqlTableModel>
#include <QObject>
#include <QSqlTableModel>
#include <QString>
class EntryListModel : public QSqlTableModel

View File

@ -18,15 +18,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QUrl>
#include <QSqlRecord>
#include <QDebug>
#include <QModelIndex>
#include <QSqlError>
#include <QSqlRecord>
#include <QUrl>
#include "database.h"
#include "feedListModel.h"
#include "fetcher.h"
#include "database.h"
FeedListModel::FeedListModel(QObject *parent)
: QSqlTableModel(parent)
@ -49,7 +49,7 @@ QHash<int, QByteArray> FeedListModel::roleNames() const
void FeedListModel::addFeed(QString url)
{
qDebug() << "Adding feed";
if(feedExists(url)) {
if (feedExists(url)) {
qDebug() << "Feed already exists";
return;
}
@ -75,7 +75,8 @@ QVariant FeedListModel::data(const QModelIndex &index, int role) const
return QSqlTableModel::data(createIndex(index.row(), role), 0);
}
bool FeedListModel::feedExists(QString url) {
bool FeedListModel::feedExists(QString url)
{
QSqlQuery query;
query.prepare(QStringLiteral("SELECT COUNT (url) FROM Feeds WHERE url=:url;"));
query.bindValue(QStringLiteral(":url"), url);
@ -95,7 +96,7 @@ void FeedListModel::removeFeed(int index)
query.bindValue(QStringLiteral(":feed"), data(createIndex(index, 0), 1).toString());
Database::instance().execute(query);
//Workaround...
// Workaround...
query.prepare(QStringLiteral("DELETE FROM Feeds WHERE url=:url;"));
query.bindValue(QStringLiteral(":url"), data(createIndex(index, 0), 1).toString());
Database::instance().execute(query);

View File

@ -23,10 +23,11 @@
#include <Syndication/Syndication>
#include "fetcher.h"
#include "database.h"
#include "fetcher.h"
Fetcher::Fetcher() {
Fetcher::Fetcher()
{
}
void Fetcher::fetch(QUrl url)
@ -44,7 +45,8 @@ void Fetcher::fetch(QUrl url)
Syndication::DocumentSource *document = new Syndication::DocumentSource(data, url.toString());
Syndication::FeedPtr feed = Syndication::parserCollection()->parse(*document, QStringLiteral("Atom"));
if(feed.isNull()) return;
if (feed.isNull())
return;
QSqlQuery query;
@ -61,14 +63,15 @@ void Fetcher::fetch(QUrl url)
query.bindValue(QStringLiteral(":id"), entry->id());
Database::instance().execute(query);
query.next();
if(query.value(0).toInt() != 0) continue;
if (query.value(0).toInt() != 0)
continue;
query.prepare(QStringLiteral("INSERT INTO Entries VALUES (:feed, :id, :title, :content, :created, :updated);"));
query.bindValue(QStringLiteral(":feed"), url.toString());
query.bindValue(QStringLiteral(":id"), entry->id());
query.bindValue(QStringLiteral(":title"), entry->title());
query.bindValue(QStringLiteral(":created"), static_cast<int>(entry->datePublished()));
query.bindValue(QStringLiteral(":updated"), static_cast<int>(entry->dateUpdated()));
if(!entry->content().isEmpty())
if (!entry->content().isEmpty())
query.bindValue(QStringLiteral(":content"), entry->content());
else
query.bindValue(QStringLiteral(":content"), entry->description());

View File

@ -25,18 +25,18 @@
#endif
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlContext>
#include <QQuickView>
#include <KAboutData>
#include <KLocalizedString>
#include <KLocalizedContext>
#include <KLocalizedString>
#include "entryListModel.h"
#include "feedListModel.h"
#include "database.h"
#include "alligatorsettings.h"
#include "database.h"
#include "entryListModel.h"
#include "feed.h"
#include "feedListModel.h"
#ifdef Q_OS_ANDROID
Q_DECL_EXPORT
@ -60,8 +60,7 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
KAboutData about(QStringLiteral("alligator"), i18n("Alligator"), QStringLiteral("0.1"), i18n("Feed Reader"),
KAboutLicense::GPL, i18n("© 2020 KDE Community"));
KAboutData about(QStringLiteral("alligator"), i18n("Alligator"), QStringLiteral("0.1"), i18n("Feed Reader"), KAboutLicense::GPL, i18n("© 2020 KDE Community"));
about.addAuthor(i18n("Tobias Fella"), QString(), QStringLiteral("fella@posteo.de"));
KAboutData::setApplicationData(about);

View File

@ -1,3 +1,23 @@
/**
* 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/>.
*/
import QtQuick 2.14
import QtQuick.Controls 2.14 as Controls