diff --git a/localization/rssguard_cs.ts b/localization/rssguard_cs.ts
index f2b7146bd..fffa9c179 100644
--- a/localization/rssguard_cs.ts
+++ b/localization/rssguard_cs.ts
@@ -283,22 +283,24 @@ Klikněte sem pro otevření nadřazeného adresáře.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Status auto-aktualizace: %3does not use auto-updateDescribes feed auto-update status.
-
+ nepoužívá auto-aktualizaceuses global settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ používá globální nastavení (%n minuta do další aktualizace)používá globální nastavení (%n minuty do další aktualizace)používá globální nastavení (%n minut do další aktualizace)uses specific settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ používá specifické nastavení (%n minuta do další aktualizace)používá specifické nastavení (%n minuty do další aktualizace)používá specifické nastavení (%n minut do další aktualizace)
@@ -531,7 +533,7 @@ or this functionality is not implemented yet.
NOT portable
-
+ NEportable
@@ -1666,7 +1668,7 @@ or this functionality is not implemented yet.
&Mark all items as read
-
+ &Označit všechny zprávy jako přečtené
@@ -2194,32 +2196,33 @@ Musíte ho nainstalovat manuálně.
Changelog
-
+ Historie verzíAvailable files
-
+ Dostupné souboryDownload selected update
-
+ Stáhnout vybranou aktualizaciGo to application website to get update packages manually.
-
+ Přejděte na web aplikace pro získání balíčku aktualizace manuálně. (size
-
+ (velikostAvailable update files
-
+ Dostupné soubory aktualizacePackage was downloaded successfully.
You can install it now.
-
+ Balíček byl úspěšně stažen.
+Nyní ho můžete nainstalovat.
@@ -2244,7 +2247,7 @@ You can install it now.
MessageBoxDo not show this dialog again.
-
+ Znovu toto upozornění nezobrazovat.
@@ -2294,8 +2297,8 @@ You can install it now.
obrázek
- Alway open links in external browser.
-
+ Always open links in external browser.
+ Vždy otevírat odkazy v ext. prohlížeči.
@@ -2884,7 +2887,7 @@ File filter for external e-mail selection dialog.
Always open links from simple internal text browser in external web browser
-
+ Odkazy z jednoduchého interního prohlížeče vždy otevírat v externím webovém prohlížeči.
@@ -3498,7 +3501,7 @@ ID účtu: %1
bytes
-
+ bajtů
diff --git a/localization/rssguard_da.ts b/localization/rssguard_da.ts
index b426f6fa0..847b6e48e 100644
--- a/localization/rssguard_da.ts
+++ b/localization/rssguard_da.ts
@@ -284,7 +284,7 @@ Auto-update status: %3
does not use auto-updateDescribes feed auto-update status.
-
+ bruger ikke automatisk ajourføringuses global settings (%n minute(s) to next auto-update)
@@ -2184,7 +2184,7 @@ You must install it manually.
Changelog
-
+ ÆndringslogAvailable files
@@ -2284,7 +2284,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_de.ts b/localization/rssguard_de.ts
index 28f68b44b..c8eb6cbab 100644
--- a/localization/rssguard_de.ts
+++ b/localization/rssguard_de.ts
@@ -281,12 +281,14 @@ Click here to open parent directory.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Status der automatische Aktualisierung: %3does not use auto-updateDescribes feed auto-update status.
-
+ keine automatische Aktualisierunguses global settings (%n minute(s) to next auto-update)
@@ -2191,7 +2193,7 @@ You must install it manually.
Changelog
-
+ ChangelogAvailable files
@@ -2291,7 +2293,7 @@ You can install it now.
Graphik
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_en.ts b/localization/rssguard_en.ts
index 948da3849..5bf7fa171 100644
--- a/localization/rssguard_en.ts
+++ b/localization/rssguard_en.ts
@@ -2320,7 +2320,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_en_GB.ts b/localization/rssguard_en_GB.ts
index b047c1566..4cb65ac06 100644
--- a/localization/rssguard_en_GB.ts
+++ b/localization/rssguard_en_GB.ts
@@ -2284,7 +2284,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_fr.ts b/localization/rssguard_fr.ts
index b76f3d909..b03c306ed 100644
--- a/localization/rssguard_fr.ts
+++ b/localization/rssguard_fr.ts
@@ -285,7 +285,7 @@ Auto-update status: %3
does not use auto-updateDescribes feed auto-update status.
-
+ Ne pas utiliser la mise à jour automatiqueuses global settings (%n minute(s) to next auto-update)
@@ -2189,7 +2189,7 @@ You must install it manually.
Changelog
-
+ ChangelogAvailable files
@@ -2289,7 +2289,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_he.ts b/localization/rssguard_he.ts
index 08f56aa35..5d19e1d73 100644
--- a/localization/rssguard_he.ts
+++ b/localization/rssguard_he.ts
@@ -2284,7 +2284,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_id.ts b/localization/rssguard_id.ts
index ec177f4e2..04e965755 100644
--- a/localization/rssguard_id.ts
+++ b/localization/rssguard_id.ts
@@ -281,12 +281,14 @@ Klik disini untuk membuka direktori induk.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Status pembaruan otomatis: %3does not use auto-updateDescribes feed auto-update status.
-
+ tidak menggunakan pembaruan otomatisuses global settings (%n minute(s) to next auto-update)
@@ -2195,7 +2197,7 @@ Anda harus instal secara manual.
Changelog
-
+ Daftar perubahanAvailable files
@@ -2295,7 +2297,7 @@ You can install it now.
gambar
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_it.ts b/localization/rssguard_it.ts
index e7d662b66..74d9cf26b 100644
--- a/localization/rssguard_it.ts
+++ b/localization/rssguard_it.ts
@@ -282,12 +282,14 @@ Fai clic qui per aprire la cartella genitrice.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Stato aggiornamento automatico: %3does not use auto-updateDescribes feed auto-update status.
-
+ non utilizza l'auto-aggiornamentouses global settings (%n minute(s) to next auto-update)
@@ -2195,7 +2197,7 @@ Devi installarlo manualmente.
Changelog
-
+ ChangelogAvailable files
@@ -2295,7 +2297,7 @@ You can install it now.
immagine
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_ja.ts b/localization/rssguard_ja.ts
index dc050eb98..708d00a07 100644
--- a/localization/rssguard_ja.ts
+++ b/localization/rssguard_ja.ts
@@ -2184,7 +2184,7 @@ You must install it manually.
Changelog
-
+ 変更履歴Available files
@@ -2284,7 +2284,7 @@ You can install it now.
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_lt.ts b/localization/rssguard_lt.ts
index 69ec94cb8..003ea0e3f 100644
--- a/localization/rssguard_lt.ts
+++ b/localization/rssguard_lt.ts
@@ -283,22 +283,24 @@ Spustelėkite čia, kad atvertumėte virškatalogį.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Automatinio atnaujinimo būsena: %3does not use auto-updateDescribes feed auto-update status.
-
+ nenaudoja automatinio atnaujinimouses global settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ naudoja visuotinius nustatymus (%n minutė iki kito automatinio atnaujinimo)naudoja visuotinius nustatymus (%n minutės iki kito automatinio atnaujinimo)naudoja visuotinius nustatymus (%n minučių iki kito automatinio atnaujinimo)uses specific settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ naudoja specifinius nustatymus (%n minutė iki kito automatinio atnaujinimo)naudoja specifinius nustatymus (%n minutės iki kito automatinio atnaujinimo)naudoja specifinius nustatymus (%n minučių iki kito automatinio atnaujinimo)
@@ -532,7 +534,7 @@ arba šis funkcionalumas dar nėra įgyvendintas.
NOT portable
-
+ NEPERKELIAMI
@@ -1667,7 +1669,7 @@ arba šis funkcionalumas dar nėra įgyvendintas.
&Mark all items as read
-
+ Žymėti visus elementus kaip &skaitytus
@@ -2197,32 +2199,33 @@ Jūs privalote jį įdiegti rankiniu būdu.
Changelog
-
+ Keitimų žurnalasAvailable files
-
+ Prieinami failaiDownload selected update
-
+ Atsisiųsti pasirinktą atnaujinimąGo to application website to get update packages manually.
-
+ Pereikite į programos svetainę, kad rankiniu būdu gautumėte atnaujinimo paketus. (size
-
+ (dydis Available update files
-
+ Prieinami atnaujinimo failaiPackage was downloaded successfully.
You can install it now.
-
+ Paketas buvo sėkmingai atsisiųstas.
+Jūs dabar galite jį įdiegti.
@@ -2247,7 +2250,7 @@ You can install it now.
MessageBoxDo not show this dialog again.
-
+ Daugiau neberodyti šio dialogo.
@@ -2297,7 +2300,7 @@ You can install it now.
paveikslas
- Alway open links in external browser.
+ Always open links in external browser.
@@ -2887,7 +2890,7 @@ File filter for external e-mail selection dialog.
Always open links from simple internal text browser in external web browser
-
+ Visada atverti nuorodas iš paprastos vidinės tekstų naršyklės į išorinę saityno naršyklę
@@ -3501,7 +3504,7 @@ Paskyros ID: %1
bytes
-
+ baitų
diff --git a/localization/rssguard_nl.ts b/localization/rssguard_nl.ts
index 7962d8e2e..900283a95 100644
--- a/localization/rssguard_nl.ts
+++ b/localization/rssguard_nl.ts
@@ -283,22 +283,24 @@ Klik hier om map te openen.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Auto update status: %3does not use auto-updateDescribes feed auto-update status.
-
+ automatisch bijwerken niet gebruikenuses global settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ gebruik algemene instellingen (%n minuut(en) tot volgende auto-update)gebruik globale instellingen (%n minut(en) voor volgende automatische update)uses specific settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ gebruik specifieke instellingen (%n minuut(en) tot volgende auto-update)gebruik specifieke instellingen (%n minut(en) tot volgende auto-update)
@@ -532,7 +534,7 @@ of deze functie bestaat nog niet.
NOT portable
-
+ NIET portable
@@ -1667,7 +1669,7 @@ of deze functie bestaat nog niet.
&Mark all items as read
-
+ &Markeer alle items als gelezen
@@ -2197,32 +2199,33 @@ Je moet het handmatig installeren.
Changelog
-
+ ChangelogAvailable files
-
+ Beschikbare bestandenDownload selected update
-
+ Download geselecteerde updateGo to application website to get update packages manually.
-
+ Ga naar Rssguard website om update handmatig te verkrijgen (size
-
+ (grootteAvailable update files
-
+ Beschikbare update bestandenPackage was downloaded successfully.
You can install it now.
-
+ Pakket was succesvol gedownload.
+Installeer het nu.
@@ -2247,7 +2250,7 @@ You can install it now.
MessageBoxDo not show this dialog again.
-
+ Laat deze dialoog niet meer zien
@@ -2297,7 +2300,7 @@ You can install it now.
Beeld
- Alway open links in external browser.
+ Always open links in external browser.
@@ -2885,7 +2888,7 @@ File filter for external e-mail selection dialog.
Always open links from simple internal text browser in external web browser
-
+ Open links altijd van een simpele interne tekstbrowser in de externe browser.
@@ -3500,7 +3503,7 @@ Account ID: %1
bytes
-
+ bytes
diff --git a/localization/rssguard_pl.ts b/localization/rssguard_pl.ts
index e3307bab0..8ab88c159 100644
--- a/localization/rssguard_pl.ts
+++ b/localization/rssguard_pl.ts
@@ -284,12 +284,14 @@ Kliknij tutaj, aby otworzyć katalog nadrzędny.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Stan auto-aktualizacji: %3does not use auto-updateDescribes feed auto-update status.
-
+ nie używa auto-aktualizacjiuses global settings (%n minute(s) to next auto-update)
@@ -2198,7 +2200,7 @@ Musisz go zainstalować ręcznie.
Changelog
-
+ Lista zmianAvailable files
@@ -2298,7 +2300,7 @@ You can install it now.
Obraz
- Alway open links in external browser.
+ Always open links in external browser.
diff --git a/localization/rssguard_pt.ts b/localization/rssguard_pt.ts
index deb89bec3..17905ece5 100644
--- a/localization/rssguard_pt.ts
+++ b/localization/rssguard_pt.ts
@@ -282,22 +282,24 @@ Clique para abrir a pasta de destino.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Status da atualização automática: %3does not use auto-updateDescribes feed auto-update status.
-
+ não usa a atualização automáticauses global settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ usa configurações globais (%n minuto(s) para a próxima atualização automática)usa configurações globais (%n minuto(s) para a próxima atualização automática)uses specific settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ usa configurações específicas (%n minuto(s) para a próxima atualização automática)usa configurações específicas (%n minuto(s) para a próxima atualização automática)
@@ -531,7 +533,7 @@ ou esta função ainda não foi implementada.
NOT portable
-
+ NÃO portátil
@@ -1666,7 +1668,7 @@ ou esta função ainda não foi implementada.
&Mark all items as read
-
+ &Marcar todos os itens como lidos
@@ -2196,32 +2198,33 @@ Você precisa instalá-lo manualmente.
Changelog
-
+ Log de alteraçõesAvailable files
-
+ Arquivos disponíveisDownload selected update
-
+ Baixar atualização selecionadaGo to application website to get update packages manually.
-
+ Acesse o site do aplicativo para obter os pacotes de atualização manualmente. (size
-
+ (tamanhoAvailable update files
-
+ Arquivos de atualização disponíveisPackage was downloaded successfully.
You can install it now.
-
+ O pacote foi baixado com sucesso.
+Você pode instalá-lo agora.
@@ -2246,7 +2249,7 @@ You can install it now.
MessageBoxDo not show this dialog again.
-
+ Não exibir novamente.
@@ -2296,7 +2299,7 @@ You can install it now.
imagem
- Alway open links in external browser.
+ Always open links in external browser.
@@ -2884,7 +2887,7 @@ File filter for external e-mail selection dialog.
Always open links from simple internal text browser in external web browser
-
+ Sempre abrir links do navegador de texto interno simples no navegador externo.
@@ -3498,7 +3501,7 @@ ID da Conta: %1
bytes
-
+ bytes
diff --git a/localization/rssguard_sv.ts b/localization/rssguard_sv.ts
index 67aaa40a2..7f3be804a 100644
--- a/localization/rssguard_sv.ts
+++ b/localization/rssguard_sv.ts
@@ -282,22 +282,24 @@ Klicka här för att öppna målmappen.
Auto-update status: %3
Tooltip for feed.
-
+ %1%2
+
+Autouppdateringsstatus: %3does not use auto-updateDescribes feed auto-update status.
-
+ uppdateras inte automatisktuses global settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ använder global inställning (%n minut till nästa automatiska uppdatering)använder globala inställningar (%n minuter till nästa automatiska uppdatering)uses specific settings (%n minute(s) to next auto-update)Describes feed auto-update status.
-
+ använder specifik inställning (%n minut till nästa automatiska uppdatering)använder specifika inställningar (%n minuter till nästa automatiska uppdatering)
@@ -531,7 +533,7 @@ att funktionen inte är implementerad än.
NOT portable
-
+ INTE portabel
@@ -1666,7 +1668,7 @@ att funktionen inte är implementerad än.
&Mark all items as read
-
+ &Märk alla objekt som lästa
@@ -2195,32 +2197,33 @@ Du måste installera det manuellt.
Changelog
-
+ ÄndringsloggAvailable files
-
+ Tillgängliga filerDownload selected update
-
+ Ladda ner vald uppdateringGo to application website to get update packages manually.
-
+ Gå till programmets webbsida för att hämta uppdateringspaketet manuellt. (size
-
+ (storlekAvailable update files
-
+ Tillgängliga uppdateringsfilerPackage was downloaded successfully.
You can install it now.
-
+ Paketet har laddats ner.
+Du kan installera det nu.
@@ -2245,7 +2248,7 @@ You can install it now.
MessageBoxDo not show this dialog again.
-
+ Visa inte denna dialog igen.
@@ -2295,7 +2298,7 @@ You can install it now.
bild
- Alway open links in external browser.
+ Always open links in external browser.
@@ -2881,7 +2884,7 @@ File filter for external e-mail selection dialog.
Always open links from simple internal text browser in external web browser
-
+ Öppna alltid länkar från intern textläsare, i extern webbläsare.
@@ -3496,7 +3499,7 @@ Konto-ID: %1
bytes
-
+ byte
diff --git a/resources/graphics/misc/nextcloud.png b/resources/graphics/misc/nextcloud.png
new file mode 100755
index 000000000..65fafbc63
Binary files /dev/null and b/resources/graphics/misc/nextcloud.png differ
diff --git a/resources/graphics/misc/owncloud.png b/resources/graphics/misc/owncloud.png
deleted file mode 100755
index 75bd1bbf9..000000000
Binary files a/resources/graphics/misc/owncloud.png and /dev/null differ
diff --git a/rssguard.pro b/rssguard.pro
index 512df2e2c..672a69c89 100755
--- a/rssguard.pro
+++ b/rssguard.pro
@@ -326,7 +326,8 @@ HEADERS += src/core/feeddownloader.h \
src/services/standard/atomparser.h \
src/services/standard/feedparser.h \
src/services/standard/rdfparser.h \
- src/services/standard/rssparser.h
+ src/services/standard/rssparser.h \
+ src/miscellaneous/serviceoperator.h
SOURCES += src/core/feeddownloader.cpp \
src/core/feedsmodel.cpp \
@@ -444,7 +445,8 @@ SOURCES += src/core/feeddownloader.cpp \
src/services/standard/atomparser.cpp \
src/services/standard/feedparser.cpp \
src/services/standard/rdfparser.cpp \
- src/services/standard/rssparser.cpp
+ src/services/standard/rssparser.cpp \
+ src/miscellaneous/serviceoperator.cpp
FORMS += src/gui/toolbareditor.ui \
src/network-web/downloaditem.ui \
diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp
index 98164999c..f3672bb5d 100755
--- a/src/gui/statusbar.cpp
+++ b/src/gui/statusbar.cpp
@@ -26,7 +26,6 @@
#include
#include
#include
-#include
StatusBar::StatusBar(QWidget *parent) : QStatusBar(parent), m_mutex(new Mutex(QMutex::NonRecursive, this)) {
diff --git a/src/miscellaneous/application.cpp b/src/miscellaneous/application.cpp
index d17b33215..4b7a21dd1 100755
--- a/src/miscellaneous/application.cpp
+++ b/src/miscellaneous/application.cpp
@@ -35,7 +35,6 @@
#include "services/owncloud/owncloudserviceentrypoint.h"
#include
-#include
#include
#if defined(USE_WEBENGINE)
@@ -373,7 +372,7 @@ void Application::onAboutToQuit() {
system()->removeTrolltechJunkRegistryKeys();
#endif
- qApp->feedReader()->stop();
+ qApp->feedReader()->quit();
database()->saveDatabase();
if (mainForm() != nullptr) {
diff --git a/src/miscellaneous/debugging.cpp b/src/miscellaneous/debugging.cpp
index 34099ddaf..e433edb1b 100755
--- a/src/miscellaneous/debugging.cpp
+++ b/src/miscellaneous/debugging.cpp
@@ -23,6 +23,8 @@
#include
#include
+#include
+#include
Debugging::Debugging() {
@@ -31,13 +33,18 @@ Debugging::Debugging() {
void Debugging::performLog(const char *message, QtMsgType type, const char *file, const char *function, int line) {
const char *type_string = typeToString(type);
+ std::time_t t = std::time(nullptr);
+ char mbstr[32];
+
+ std::strftime(mbstr, sizeof(mbstr), "%y/%d/%m %H:%M:%S", std::localtime(&t));
+
// Write to console.
if (file == 0 || function == 0 || line < 0) {
- fprintf(stderr, "[%s] %s: %s\n", APP_LOW_NAME, type_string, message);
+ fprintf(stderr, "[%s] %s: %s (%s)\n", APP_LOW_NAME, type_string, message, mbstr);
}
else {
- fprintf(stderr, "[%s] %s\n Type: %s\n File: %s (line %d)\n Function: %s\n\n",
- APP_LOW_NAME, message, type_string, file, line, function);
+ fprintf(stderr, "[%s] %s (%s)\n Type: %s\n File: %s (line %d)\n Function: %s\n\n",
+ APP_LOW_NAME, message, mbstr, type_string, file, line, function);
}
if (type == QtFatalMsg) {
diff --git a/src/miscellaneous/feedreader.cpp b/src/miscellaneous/feedreader.cpp
index 73a779a6c..9dca3071b 100755
--- a/src/miscellaneous/feedreader.cpp
+++ b/src/miscellaneous/feedreader.cpp
@@ -20,6 +20,7 @@
#include "services/standard/standardserviceentrypoint.h"
#include "services/owncloud/owncloudserviceentrypoint.h"
#include "services/tt-rss/ttrssserviceentrypoint.h"
+#include "services/abstract/serviceroot.h"
#include "core/feedsmodel.h"
#include "core/feedsproxymodel.h"
@@ -32,10 +33,12 @@
#include
#include
+#include
FeedReader::FeedReader(QObject *parent)
- : QObject(parent), m_feedServices(QList()), m_autoUpdateTimer(new QTimer(this)),
+ : QObject(parent), m_feedServices(QList()),
+ m_cacheSaveFutureWatcher(new QFutureWatcher(this)), m_autoUpdateTimer(new QTimer(this)),
m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr),
m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) {
m_feedsModel = new FeedsModel(this);
@@ -43,8 +46,10 @@ FeedReader::FeedReader(QObject *parent)
m_messagesModel = new MessagesModel(this);
m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this);
+ connect(m_cacheSaveFutureWatcher, &QFutureWatcher::finished, this, &FeedReader::asyncCacheSaveFinished);
connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate);
updateAutoUpdateStatus();
+ asyncCacheSaveFinished();
if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) {
qDebug("Requesting update for all feeds on application startup.");
@@ -209,11 +214,60 @@ void FeedReader::executeNextAutoUpdate() {
}
}
-void FeedReader::stop() {
+void FeedReader::checkServicesForAsyncOperations() {
+ checkServicesForAsyncOperations(false);
+}
+
+void FeedReader::checkServicesForAsyncOperations(bool wait_for_future) {
+ if (m_cacheSaveFutureWatcher->future().isRunning()) {
+ qDebug("Previous future is still running.");
+
+
+ // If we want to wait for future synchronously, we want to make sure that
+ // we save all cached data (app exit).
+ if (wait_for_future) {
+ qWarning("Waiting for previously started saving of cached service data.");
+ m_cacheSaveFutureWatcher->future().waitForFinished();
+ }
+ else {
+ qWarning("Some cached service data are being saved now, so aborting this saving cycle.");
+ // Some cache saving is now running.
+ return;
+ }
+ }
+
+ QFuture future = QtConcurrent::run([&] {
+ foreach (ServiceRoot *service, m_feedsModel->serviceRoots()) {
+ // Store any cached data.
+ service->saveAllCachedData();
+ }
+ });
+
+ if (wait_for_future) {
+ qDebug("Waiting for saving of cached service data to finish.");
+ future.waitForFinished();
+ }
+ else {
+ m_cacheSaveFutureWatcher->setFuture(future);
+ }
+}
+
+void FeedReader::asyncCacheSaveFinished() {
+ qDebug("I will start next check for cached service data in 30 seconds.");
+
+ QTimer::singleShot(30000, [&] {
+ qDebug("Starting next check for cached service data in NOW.");
+ checkServicesForAsyncOperations(false);
+ });
+}
+
+void FeedReader::quit() {
if (m_autoUpdateTimer->isActive()) {
m_autoUpdateTimer->stop();
}
+ checkServicesForAsyncOperations(true);
+
// Close worker threads.
if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) {
m_feedDownloader->stopRunningUpdate();
diff --git a/src/miscellaneous/feedreader.h b/src/miscellaneous/feedreader.h
index d3715d8c1..46c0b8413 100755
--- a/src/miscellaneous/feedreader.h
+++ b/src/miscellaneous/feedreader.h
@@ -23,12 +23,15 @@
#include "services/abstract/feed.h"
#include "core/feeddownloader.h"
+#include
+
class FeedsModel;
class MessagesModel;
class MessagesProxyModel;
class FeedsProxyModel;
class ServiceEntryPoint;
+class ServiceOperator;
class DatabaseCleaner;
class QTimer;
@@ -69,11 +72,14 @@ class FeedReader : public QObject {
// Schedules all feeds from all accounts for update.
void updateAllFeeds();
void stopRunningFeedUpdate();
- void stop();
+ void quit();
private slots:
// Is executed when next auto-update round could be done.
void executeNextAutoUpdate();
+ void checkServicesForAsyncOperations();
+ void checkServicesForAsyncOperations(bool wait_for_future);
+ void asyncCacheSaveFinished();
signals:
void feedUpdatesStarted();
@@ -88,12 +94,16 @@ class FeedReader : public QObject {
MessagesModel *m_messagesModel;
MessagesProxyModel *m_messagesProxyModel;
+ QFutureWatcher *m_cacheSaveFutureWatcher;
+
// Auto-update stuff.
QTimer *m_autoUpdateTimer;
bool m_globalAutoUpdateEnabled;
int m_globalAutoUpdateInitialInterval;
int m_globalAutoUpdateRemainingInterval;
+ ServiceOperator *m_serviceOperator;
+
QThread *m_feedDownloaderThread;
FeedDownloader *m_feedDownloader;
diff --git a/src/miscellaneous/serviceoperator.cpp b/src/miscellaneous/serviceoperator.cpp
new file mode 100755
index 000000000..cbb07c04f
--- /dev/null
+++ b/src/miscellaneous/serviceoperator.cpp
@@ -0,0 +1,25 @@
+// This file is part of RSS Guard.
+//
+// Copyright (C) 2011-2017 by Martin Rotter
+//
+// RSS Guard 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 3 of the License, or
+// (at your option) any later version.
+//
+// RSS Guard 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 RSS Guard. If not, see .
+
+#include "miscellaneous/serviceoperator.h"
+
+
+ServiceOperator::ServiceOperator(QObject *parent) : QObject(parent) {
+}
+
+ServiceOperator::~ServiceOperator() {
+}
diff --git a/src/miscellaneous/serviceoperator.h b/src/miscellaneous/serviceoperator.h
new file mode 100755
index 000000000..352ae29df
--- /dev/null
+++ b/src/miscellaneous/serviceoperator.h
@@ -0,0 +1,36 @@
+// This file is part of RSS Guard.
+//
+// Copyright (C) 2011-2017 by Martin Rotter
+//
+// RSS Guard 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 3 of the License, or
+// (at your option) any later version.
+//
+// RSS Guard 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 RSS Guard. If not, see .
+
+#ifndef SERVICEOPERATOR_H
+#define SERVICEOPERATOR_H
+
+#include
+
+
+class ServiceOperator : public QObject {
+ Q_OBJECT
+
+ public:
+ explicit ServiceOperator(QObject *parent = 0);
+ virtual ~ServiceOperator();
+
+ signals:
+
+ public slots:
+};
+
+#endif // SERVICEOPERATOR_H
diff --git a/src/services/abstract/serviceroot.cpp b/src/services/abstract/serviceroot.cpp
index 6c5c46feb..59494d234 100755
--- a/src/services/abstract/serviceroot.cpp
+++ b/src/services/abstract/serviceroot.cpp
@@ -192,6 +192,9 @@ QList ServiceRoot::undeletedMessages() const {
return DatabaseQueries::getUndeletedMessagesForAccount(database, accountId());
}
+void ServiceRoot::saveAllCachedData() {
+}
+
void ServiceRoot::itemChanged(const QList &items) {
emit dataChanged(items);
}
diff --git a/src/services/abstract/serviceroot.h b/src/services/abstract/serviceroot.h
index 39f5268e7..7850d83f4 100755
--- a/src/services/abstract/serviceroot.h
+++ b/src/services/abstract/serviceroot.h
@@ -59,6 +59,7 @@ class ServiceRoot : public RootItem {
// NOTE: Caller does NOT take ownership of created menu!
virtual QList addItemMenu();
+ // Returns actions to display as context menu.
QList contextMenu();
// Returns list of specific actions to be shown in main window menu
@@ -83,6 +84,8 @@ class ServiceRoot : public RootItem {
virtual void start(bool freshly_activated) = 0;
virtual void stop() = 0;
+ virtual void saveAllCachedData();
+
// Account ID corresponds with DB attribute Accounts (id).
int accountId() const;
void setAccountId(int account_id);
diff --git a/src/services/owncloud/owncloudfeed.cpp b/src/services/owncloud/owncloudfeed.cpp
index 9c742d8f6..fe4471a66 100755
--- a/src/services/owncloud/owncloudfeed.cpp
+++ b/src/services/owncloud/owncloudfeed.cpp
@@ -89,15 +89,8 @@ bool OwnCloudFeed::removeItself() {
}
bool OwnCloudFeed::markAsReadUnread(RootItem::ReadStatus status) {
- QStringList ids = getParentServiceRoot()->customIDSOfMessagesForItem(this);
- QNetworkReply::NetworkError response = serviceRoot()->network()->markMessagesRead(status, ids);
-
- if (response != QNetworkReply::NoError) {
- return false;
- }
- else {
- return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status);
- }
+ serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status);
+ return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status);
}
bool OwnCloudFeed::cleanMessages(bool clear_only_read) {
diff --git a/src/services/owncloud/owncloudrecyclebin.cpp b/src/services/owncloud/owncloudrecyclebin.cpp
index 128ceb559..5e9cb715d 100755
--- a/src/services/owncloud/owncloudrecyclebin.cpp
+++ b/src/services/owncloud/owncloudrecyclebin.cpp
@@ -34,13 +34,6 @@ OwnCloudServiceRoot *OwnCloudRecycleBin::serviceRoot() {
}
bool OwnCloudRecycleBin::markAsReadUnread(RootItem::ReadStatus status) {
- QStringList ids = getParentServiceRoot()->customIDSOfMessagesForItem(this);
- QNetworkReply::NetworkError response = serviceRoot()->network()->markMessagesRead(status, ids);
-
- if (response != QNetworkReply::NoError) {
- return false;
- }
- else {
- return RecycleBin::markAsReadUnread(status);
- }
+ serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status);
+ return RecycleBin::markAsReadUnread(status);
}
diff --git a/src/services/owncloud/owncloudserviceentrypoint.cpp b/src/services/owncloud/owncloudserviceentrypoint.cpp
index 33089089f..45244f19d 100755
--- a/src/services/owncloud/owncloudserviceentrypoint.cpp
+++ b/src/services/owncloud/owncloudserviceentrypoint.cpp
@@ -38,7 +38,6 @@ ServiceRoot *OwnCloudServiceEntryPoint::createNewRoot() const {
}
QList OwnCloudServiceEntryPoint::initializeSubtree() const {
- // Check DB if standard account is enabled.
QSqlDatabase database = qApp->database()->connection(QSL("OwnCloudServiceEntryPoint"), DatabaseFactory::FromSettings);
return DatabaseQueries::getOwnCloudAccounts(database);
@@ -49,7 +48,7 @@ bool OwnCloudServiceEntryPoint::isSingleInstanceService() const {
}
QString OwnCloudServiceEntryPoint::name() const {
- return QSL("ownCloud News");
+ return QSL("NextCloud News");
}
QString OwnCloudServiceEntryPoint::code() const {
@@ -57,7 +56,7 @@ QString OwnCloudServiceEntryPoint::code() const {
}
QString OwnCloudServiceEntryPoint::description() const {
- return QObject::tr("The News app is an RSS/Atom feed aggregator. It is part of ownCloud suite. This plugin implements %1 API.").arg(API_VERSION);
+ return QObject::tr("The News app is an RSS/Atom feed aggregator. It is part of Nextcloud suite. This plugin implements %1 API.").arg(API_VERSION);
}
QString OwnCloudServiceEntryPoint::version() const {
@@ -69,6 +68,6 @@ QString OwnCloudServiceEntryPoint::author() const {
}
QIcon OwnCloudServiceEntryPoint::icon() const {
- return qApp->icons()->miscIcon(QSL("owncloud"));
+ return qApp->icons()->miscIcon(QSL("nextcloud"));
}
diff --git a/src/services/owncloud/owncloudserviceroot.cpp b/src/services/owncloud/owncloudserviceroot.cpp
index 928252c7e..182e1496b 100755
--- a/src/services/owncloud/owncloudserviceroot.cpp
+++ b/src/services/owncloud/owncloudserviceroot.cpp
@@ -33,7 +33,8 @@
OwnCloudServiceRoot::OwnCloudServiceRoot(RootItem *parent)
- : ServiceRoot(parent), m_recycleBin(new OwnCloudRecycleBin(this)),
+ : ServiceRoot(parent), m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, this)), m_cachedStatesRead(QMap()),
+ m_cachedStatesImportant(QMap()), m_recycleBin(new OwnCloudRecycleBin(this)),
m_actionSyncIn(nullptr), m_serviceMenu(QList()), m_network(new OwnCloudNetworkFactory()) {
setIcon(OwnCloudServiceEntryPoint().icon());
}
@@ -112,12 +113,64 @@ OwnCloudNetworkFactory *OwnCloudServiceRoot::network() const {
return m_network;
}
+void OwnCloudServiceRoot::addMessageStatesToCache(const QStringList &ids_of_messages, RootItem::ReadStatus read) {
+ m_cacheSaveMutex->lock();
+
+ QStringList &list_act = m_cachedStatesRead[read];
+ QStringList &list_other = m_cachedStatesRead[read == RootItem::Read ? RootItem::Unread : RootItem::Read];
+
+ // Store changes, they will be sent to server later.
+ list_act.append(ids_of_messages);
+
+ QSet set_act = list_act.toSet();
+ QSet set_other = list_other.toSet();
+
+ // Now, we want to remove all IDS from list_other, which are contained in list.
+ set_other -= set_act;
+
+ list_act.clear(); list_act.append(set_act.toList());
+ list_other.clear(); list_other.append(set_other.toList());
+
+ m_cacheSaveMutex->unlock();
+}
+
+void OwnCloudServiceRoot::saveAllCachedData() {
+ if (m_cachedStatesRead.isEmpty() && m_cachedStatesImportant.isEmpty()) {
+ // No cached changes.
+ return;
+ }
+
+ m_cacheSaveMutex->lock();
+
+ // Make copy of changes.
+ QMap cached_data_read = m_cachedStatesRead;
+ cached_data_read.detach();
+
+ QMap cached_data_imp = m_cachedStatesImportant;
+ cached_data_imp.detach();
+
+ m_cachedStatesRead.clear();
+ m_cachedStatesImportant.clear();
+
+ m_cacheSaveMutex->unlock();
+
+ // Save the actual data.
+ for (int i = 0; i < cached_data_read.size(); i++) {
+ auto key = cached_data_read.keys().at(i);
+ QStringList ids = cached_data_read[key];
+
+ if (!ids.isEmpty()) {
+ network()->markMessagesRead(key, ids);
+ }
+ }
+}
+
bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem *selected_item, const QList &messages,
RootItem::ReadStatus read) {
Q_UNUSED(selected_item)
- QNetworkReply::NetworkError reply = network()->markMessagesRead(read, customIDsOfMessages(messages));
- return reply == QNetworkReply::NoError;
+ addMessageStatesToCache(customIDsOfMessages(messages), read);
+ return true;
}
bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem *selected_item,
@@ -185,8 +238,8 @@ void OwnCloudServiceRoot::saveAccountDataToDatabase() {
if (saved) {
if (DatabaseQueries::createOwnCloudAccount(database, id_to_assign, m_network->authUsername(),
- m_network->authPassword(), m_network->url(),
- m_network->forceServerSideUpdate())) {
+ m_network->authPassword(), m_network->url(),
+ m_network->forceServerSideUpdate())) {
setId(id_to_assign);
setAccountId(id_to_assign);
updateTitle();
diff --git a/src/services/owncloud/owncloudserviceroot.h b/src/services/owncloud/owncloudserviceroot.h
index 3c2ddef6b..a99fb4049 100755
--- a/src/services/owncloud/owncloudserviceroot.h
+++ b/src/services/owncloud/owncloudserviceroot.h
@@ -20,9 +20,12 @@
#include "services/abstract/serviceroot.h"
+#include
+
class OwnCloudNetworkFactory;
class OwnCloudRecycleBin;
+class Mutex;
class OwnCloudServiceRoot : public ServiceRoot {
Q_OBJECT
@@ -45,17 +48,25 @@ class OwnCloudServiceRoot : public ServiceRoot {
OwnCloudNetworkFactory *network() const;
+ void addMessageStatesToCache(const QStringList &ids_of_messages, ReadStatus read);
+
bool onBeforeSetMessagesRead(RootItem *selected_item, const QList &messages, ReadStatus read);
bool onBeforeSwitchMessageImportance(RootItem *selected_item, const QList &changes);
void updateTitle();
void saveAccountDataToDatabase();
+ void saveAllCachedData();
+
public slots:
void addNewFeed(const QString &url);
void addNewCategory();
private:
+ Mutex *m_cacheSaveMutex;
+ QMap m_cachedStatesRead;
+ QMap m_cachedStatesImportant;
+
QMap storeCustomFeedsData();
void restoreCustomFeedsData(const QMap &data, const QHash &feeds);
RootItem *obtainNewTreeForSyncIn() const;