This commit is contained in:
Martin Rotter 2021-03-01 20:09:56 +01:00 committed by Martin Rotter
parent 0610e17128
commit 9c6ed2bbc6
9 changed files with 46 additions and 42 deletions

View File

@ -8,6 +8,7 @@
* [Localizations](#localizations)
* [Videos](#videos)
* [Web-based and lite app variants](#web-based-and-lite-app-variants)
* [RSS Guard 3 vs. RSS Guard 4](#RSS-Guard-3-vs.-RSS-Guard-4)
* [Features](#features)
* [List of main features](#list-of-main-features)
* [Supported feed formats and online feed services](Feed-formats.md)
@ -22,7 +23,7 @@
* [GUI tweaking](#gui-tweaking)
* [Miscellaneous](#miscellaneous)
* [Command line interface](#cli)
* [OS/2](#os2)
* [How to build](#how-to-build)
* [Cleaning database](#cleaning-database)
* [Portable user data](#portable-user-data)
* [Downloading new messages](#downloading-new-messages)
@ -79,7 +80,7 @@ Here you can see some videos to see RSS Guard in action:
## Web-based and lite app variants
RSS Guard is distributed in two variants:
* **Standard package with WebEngine-based bundled message viewer**: This variant displays messages with their full formatting and layout in embedded Chromium-based web viewer. This variant of RSS Guard should be nice for everyone who doesn't care about memory consumption. Also, installation packages are relatively big.
* **Standard package with WebEngine-based bundled message viewer**: This variant displays messages with their full formatting and layout in embedded Chromium-based web viewer. This variant of RSS Guard should be nice for everyone who doesn't care about memory consumption too much. Also, installation packages are relatively big.
<img src="images/webengine-view.png" width="80%">
@ -89,6 +90,11 @@ RSS Guard is distributed in two variants:
If you're not sure which version to use, **use the WebEngine-based RSS Guard**.
## RSS Guard 3 vs. RSS Guard 4
RSS Guard 4 is **NOT** backwards compatible with previous editions of the application!!! It stores settings in slightly different [folder](#portable-user-data) to not overwrite user data from previous versions.
RSS Guard 4.x contains numerous enhancements and many of them are hidden under the hood and they make application easier to maintain, easier to improve and easier to use.
# Features
RSS Guard is simple (yet powerful) feed reader. It is able to fetch the most known feed formats, including RSS/RDF/ATOM/JSON. RSS Guard is developed on top of the [Qt library](http://qt-project.org) and it supports these operating systems:
@ -166,7 +172,7 @@ MariaDB (MySQL) backend is there for users, who want to store their data in a ce
For database-related configuration see `Settings -> Data storage` dialog.
## Google Reader API
Starting with RSS Guard 3.9.0, there is a new plugin which offers synchronization with services using Google Reader API. Plugin was so far tested with FreshRSS, The Old Reader and Bazqux. All Google Reader API enabled services should work.
Starting with RSS Guard 3.9.0, there is a new plugin which offers synchronization with services using Google Reader API. Plugin was so far tested with FreshRSS, Reedah, The Old Reader and Bazqux. All Google Reader API enabled services should work.
Note that Inoreader has its own separate plugin, because it uses OAuth as authentication method, therefore it is cleaner to have separate plugin.
@ -197,8 +203,8 @@ Sadly, some builds of RSS Guard do not have embedded production Feedly API keys
<img src="images/feedly-details.png">
There are two big downsides of using `developer access token`:
* It expires after one month and must be renewed.
* It only allows maximum of 250 API calls per day.
* It expires after one month and must be manually renewed.
* It allows maximum of 250 API calls per day.
## Downloading files
RSS Guard offers simple embedded file downloader.
@ -252,8 +258,11 @@ Options:
-v, --version Displays version information.
```
## OS/2
RSS Guard can run on OS/2 and if you want to compile it by yourself, you need to make sure that your OS/2 distro is up-to-date and you have all dependencies installed:
## How to build
RSS Guard is C++ application and all common build instructions can be found in top of [project file](https://github.com/martinrotter/rssguard/blob/master/build.pro).
### OS/2-specifics
RSS Guard can run on OS/2 and if you want to compile it by yourself, you need to make sure that your OS/2 distribution is up-to-date and you have all dependencies installed:
* `os2-base`,
* all `gcc-*` packages,
* `libc` and `libcx` up-to-date,
@ -262,11 +271,14 @@ RSS Guard can run on OS/2 and if you want to compile it by yourself, you need to
* `binutils`,
* all relevant `qt5-*` packages.
Make sure you really have all development dependencies installed as OS/2 is known to thro erratic errors if you miss some important compile-time dependency.
After your dependecies are installed, then you can compile via standard `qmake -> make -> make install` steps and package with
```
7z.exe a -t7z -mmt -mx9 "rssguard.7z" "<build-folder\src\rssguard\app\*"
```
command.
## Cleaning database
@ -277,11 +289,11 @@ Your RSS Guard's database can grow really big over time, therefore you might nee
## Portable user data
RSS Guard checks "config directory" (this is `C:\Users\<user>\AppData\Local` directory on Windows) for existence of file:
```
RSS Guard\data\config\config.ini
RSS Guard 4\data\config\config.ini
```
If that file exists, then RSS Guard will use the file (this is called _non-portable **FALLBACK** settings_). If this file is not found, then application will check if its root path (folder, in which RSS Guard executable is installed) is writable, and if it is, it will store settings in it, in subfolder:
```
data\config\config.ini
data4\config\config.ini
```
This is _fully-portable mode_. Check `About RSS Guard -> Resources` dialog to find more info on significant paths used.

@ -1 +1 @@
Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9
Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749

View File

@ -27,7 +27,7 @@ CREATE TABLE Categories (
account_id INTEGER NOT NULL,
custom_id TEXT,
FOREIGN KEY (account_id) REFERENCES Accounts (id)
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
);
-- !
CREATE TABLE Feeds (
@ -43,7 +43,7 @@ CREATE TABLE Feeds (
account_id INTEGER NOT NULL,
custom_id TEXT,
FOREIGN KEY (account_id) REFERENCES Accounts (id)
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
);
-- !
CREATE TABLE Messages (
@ -63,7 +63,7 @@ CREATE TABLE Messages (
custom_id TEXT,
custom_hash TEXT,
FOREIGN KEY (account_id) REFERENCES Accounts (id)
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
);
-- !
CREATE TABLE MessageFilters (
@ -88,7 +88,7 @@ CREATE TABLE Labels (
custom_id TEXT,
account_id INTEGER NOT NULL,
FOREIGN KEY (account_id) REFERENCES Accounts (id)
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
);
-- !
CREATE TABLE LabelsInMessages (

View File

@ -1703,17 +1703,6 @@ void DatabaseQueries::createOverwriteAccount(const QSqlDatabase& db, ServiceRoot
bool DatabaseQueries::deleteFeed(const QSqlDatabase& db, int feed_custom_id, int account_id) {
QSqlQuery q(db);
q.setForwardOnly(true);
// Remove all messages and other data from this feed.
q.prepare(QSL("DELETE FROM MessageFiltersInFeeds WHERE feed_custom_id = :feed AND account_id = :account_id;"));
q.bindValue(QSL(":feed"), feed_custom_id);
q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) {
return false;
}
q.prepare(QSL("DELETE FROM Messages WHERE feed = :feed AND account_id = :account_id;"));
q.bindValue(QSL(":feed"), feed_custom_id);
q.bindValue(QSL(":account_id"), account_id);
@ -1726,10 +1715,13 @@ bool DatabaseQueries::deleteFeed(const QSqlDatabase& db, int feed_custom_id, int
q.prepare(QSL("DELETE FROM Feeds WHERE custom_id = :feed AND account_id = :account_id;"));
q.bindValue(QSL(":feed"), feed_custom_id);
q.bindValue(QSL(":account_id"), account_id);
return q.exec();
return q.exec() &&
purgeLeftoverMessageFilterAssignments(db, account_id) &&
purgeLeftoverLabelAssignments(db, account_id);
}
bool DatabaseQueries::deleteStandardCategory(const QSqlDatabase& db, int id) {
bool DatabaseQueries::deleteCategory(const QSqlDatabase& db, int id) {
QSqlQuery q(db);
// Remove this category from database.
@ -1914,16 +1906,16 @@ bool DatabaseQueries::editStandardFeed(const QSqlDatabase& db, int parent_id, in
return suc;
}
bool DatabaseQueries::editBaseFeed(const QSqlDatabase& db, int feed_id, Feed::AutoUpdateType auto_update_type,
int auto_update_interval, bool is_protected, const QString& username,
const QString& password) {
bool DatabaseQueries::editFeed(const QSqlDatabase& db, int feed_id, Feed::AutoUpdateType auto_update_type,
int auto_update_interval, bool is_protected, const QString& username,
const QString& password) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("UPDATE Feeds "
"SET update_type = :update_type, update_interval = :update_interval, protected = :protected, username = :username, password = :password "
"WHERE id = :id;");
q.bindValue(QSL(":update_type"), (int) auto_update_type);
q.bindValue(QSL(":update_type"), int(auto_update_type));
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":id"), feed_id);
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);

View File

@ -112,10 +112,10 @@ class DatabaseQueries {
static bool cleanImportantMessages(const QSqlDatabase& db, bool clean_read_only, int account_id);
static bool cleanFeeds(const QSqlDatabase& db, const QStringList& ids, bool clean_read_only, int account_id);
static bool storeAccountTree(const QSqlDatabase& db, RootItem* tree_root, int account_id);
static bool editBaseFeed(const QSqlDatabase& db, int feed_id,
Feed::AutoUpdateType auto_update_type, int auto_update_interval,
bool is_protected, const QString& username,
const QString& password);
static bool editFeed(const QSqlDatabase& db, int feed_id,
Feed::AutoUpdateType auto_update_type, int auto_update_interval,
bool is_protected, const QString& username,
const QString& password);
template<typename T>
static Assignment getCategories(const QSqlDatabase& db, int account_id, bool* ok = nullptr);
@ -136,10 +136,10 @@ class DatabaseQueries {
static void updateMessageFilter(const QSqlDatabase& db, MessageFilter* filter, bool* ok = nullptr);
static void removeMessageFilterFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, int filter_id,
int account_id, bool* ok = nullptr);
static bool deleteFeed(const QSqlDatabase& db, int feed_custom_id, int account_id);
static bool deleteCategory(const QSqlDatabase& db, int id);
// Standard account.
static bool deleteFeed(const QSqlDatabase& db, int feed_custom_id, int account_id);
static bool deleteStandardCategory(const QSqlDatabase& db, int id);
static int addStandardCategory(const QSqlDatabase& db, int parent_id, int account_id, const QString& title,
const QString& description, const QDateTime& creation_date, const QIcon& icon, bool* ok = nullptr);
static bool editStandardCategory(const QSqlDatabase& db, int parent_id, int category_id,

View File

@ -171,14 +171,14 @@ bool Feed::canBeEdited() const {
bool Feed::editViaGui() {
QScopedPointer<FormFeedDetails> form_pointer(new FormFeedDetails(getParentServiceRoot(), qApp->mainFormWidget()));
form_pointer->editBaseFeed(this);
form_pointer->editFeed(this);
return false;
}
bool Feed::editItself(Feed* new_feed_data) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
if (DatabaseQueries::editBaseFeed(database, id(), new_feed_data->autoUpdateType(),
if (DatabaseQueries::editFeed(database, id(), new_feed_data->autoUpdateType(),
new_feed_data->autoUpdateInitialInterval(),
new_feed_data->passwordProtected(),
new_feed_data->username(),

View File

@ -28,7 +28,7 @@ FormFeedDetails::FormFeedDetails(ServiceRoot* service_root, QWidget* parent)
createConnections();
}
int FormFeedDetails::editBaseFeed(Feed* input_feed) {
int FormFeedDetails::editFeed(Feed* input_feed) {
setEditableFeed(input_feed);
return QDialog::exec();
}

View File

@ -24,7 +24,7 @@ class FormFeedDetails : public QDialog {
virtual ~FormFeedDetails() = default;
public slots:
int editBaseFeed(Feed* input_feed);
int editFeed(Feed* input_feed);
protected slots:
void activateTab(int index);

View File

@ -87,7 +87,7 @@ bool StandardCategory::removeItself() {
// Children are removed, remove this standard category too.
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
return DatabaseQueries::deleteStandardCategory(database, id());
return DatabaseQueries::deleteCategory(database, id());
}
else {
return false;