diff --git a/src/librssguard/gui/notifications/notificationseditor.cpp b/src/librssguard/gui/notifications/notificationseditor.cpp index a93fe1e7c..c4cd432e3 100755 --- a/src/librssguard/gui/notifications/notificationseditor.cpp +++ b/src/librssguard/gui/notifications/notificationseditor.cpp @@ -10,7 +10,11 @@ NotificationsEditor::NotificationsEditor(QWidget* parent) : QScrollArea(parent), m_layout(new QVBoxLayout(this)) { m_ui.setupUi(this); - setLayout(m_layout); + + QWidget* wdg = new QWidget(this); + + wdg->setLayout(m_layout); + setWidget(wdg); } void NotificationsEditor::loadNotifications(const QList& notifications) { diff --git a/src/librssguard/gui/notifications/notificationseditor.ui b/src/librssguard/gui/notifications/notificationseditor.ui index ebf93bf17..71670ee37 100755 --- a/src/librssguard/gui/notifications/notificationseditor.ui +++ b/src/librssguard/gui/notifications/notificationseditor.ui @@ -13,6 +13,9 @@ QFrame::NoFrame + + true + diff --git a/src/librssguard/gui/notifications/singlenotificationeditor.cpp b/src/librssguard/gui/notifications/singlenotificationeditor.cpp index 049417b1e..2362d6d4c 100755 --- a/src/librssguard/gui/notifications/singlenotificationeditor.cpp +++ b/src/librssguard/gui/notifications/singlenotificationeditor.cpp @@ -25,7 +25,7 @@ SingleNotificationEditor::SingleNotificationEditor(const Notification& notificat connect(m_ui.m_txtSound, &QLineEdit::textChanged, this, &SingleNotificationEditor::notificationChanged); connect(m_ui.m_cbBalloon, &QCheckBox::toggled, this, &SingleNotificationEditor::notificationChanged); - //setFixedHeight(sizeHint().height()); + setFixedHeight(sizeHint().height()); } Notification SingleNotificationEditor::notification() const { diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index 7b25d0119..a2372fe60 100755 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.cpp @@ -95,13 +95,11 @@ Application::Application(const QString& id, int& argc, char** argv) if (isFirstRun()) { m_notifications->save({ - Notification(Notification::Event::GeneralEvent, - true), - Notification(Notification::Event::NewUnreadArticlesFetched, - true, + Notification(Notification::Event::GeneralEvent, true), + Notification(Notification::Event::NewUnreadArticlesFetched, true, QSL("%1/rooster.wav").arg(SOUNDS_BUILTIN_DIRECTORY)), - Notification(Notification::Event::NewAppVersionAvailable, - true) + Notification(Notification::Event::NewAppVersionAvailable, true), + Notification(Notification::Event::LoginFailure, true) }, settings()); } else { @@ -254,8 +252,7 @@ void Application::eliminateFirstRuns() { settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + APP_VERSION, false); } -NotificationFactory* Application::notifications() const -{ +NotificationFactory* Application::notifications() const { return m_notifications; } diff --git a/src/librssguard/miscellaneous/notification.cpp b/src/librssguard/miscellaneous/notification.cpp index b36be9ab9..261601a4b 100755 --- a/src/librssguard/miscellaneous/notification.cpp +++ b/src/librssguard/miscellaneous/notification.cpp @@ -43,6 +43,7 @@ QList Notification::allEvents() { Event::NewUnreadArticlesFetched, Event::ArticlesFetchingStarted, Event::LoginDataRefreshed, + Event::LoginFailure, Event::NewAppVersionAvailable, }; } @@ -58,6 +59,9 @@ QString Notification::nameForEvent(Notification::Event event) { case Notification::Event::LoginDataRefreshed: return QObject::tr("Login data refreshed"); + case Notification::Event::LoginFailure: + return QObject::tr("Login failed"); + case Notification::Event::NewAppVersionAvailable: return QObject::tr("New %1 version is available").arg(APP_NAME); diff --git a/src/librssguard/miscellaneous/notification.h b/src/librssguard/miscellaneous/notification.h index 139dd32d2..da0b3a403 100755 --- a/src/librssguard/miscellaneous/notification.h +++ b/src/librssguard/miscellaneous/notification.h @@ -28,7 +28,9 @@ class Notification { // OAuth or similar mechanism. LoginDataRefreshed = 4, - NewAppVersionAvailable = 5 + NewAppVersionAvailable = 5, + + LoginFailure = 6 }; explicit Notification(Event event = Event::NoEvent, bool balloon = {}, const QString& sound_path = {}); diff --git a/src/librssguard/network-web/oauth2service.cpp b/src/librssguard/network-web/oauth2service.cpp index 0506966d0..63efd7d2b 100644 --- a/src/librssguard/network-web/oauth2service.cpp +++ b/src/librssguard/network-web/oauth2service.cpp @@ -80,7 +80,7 @@ OAuth2Service::~OAuth2Service() { QString OAuth2Service::bearer() { if (!isFullyLoggedIn()) { - qApp->showGuiMessage(Notification::Event::GeneralEvent, + qApp->showGuiMessage(Notification::Event::LoginFailure, tr("You have to login first"), tr("Click here to login."), QSystemTrayIcon::MessageIcon::Critical, diff --git a/src/librssguard/services/gmail/gmailnetworkfactory.cpp b/src/librssguard/services/gmail/gmailnetworkfactory.cpp index 089b54775..a7d404b7f 100755 --- a/src/librssguard/services/gmail/gmailnetworkfactory.cpp +++ b/src/librssguard/services/gmail/gmailnetworkfactory.cpp @@ -433,7 +433,7 @@ void GmailNetworkFactory::onTokensError(const QString& error, const QString& err } void GmailNetworkFactory::onAuthFailed() { - qApp->showGuiMessage(Notification::Event::GeneralEvent, + qApp->showGuiMessage(Notification::Event::LoginFailure, tr("Gmail: authorization denied"), tr("Click this to login again."), QSystemTrayIcon::MessageIcon::Critical, diff --git a/src/librssguard/services/greader/greadernetwork.cpp b/src/librssguard/services/greader/greadernetwork.cpp index 779a83bdb..b6f5f8dfe 100755 --- a/src/librssguard/services/greader/greadernetwork.cpp +++ b/src/librssguard/services/greader/greadernetwork.cpp @@ -5,6 +5,7 @@ #include "3rd-party/boolinq/boolinq.h" #include "database/databasequeries.h" #include "exceptions/applicationexception.h" +#include "exceptions/feedfetchexception.h" #include "exceptions/networkexception.h" #include "miscellaneous/application.h" #include "network-web/networkfactory.h" @@ -22,10 +23,10 @@ GreaderNetwork::GreaderNetwork(QObject* parent) : QObject(parent), m_root(nullptr), m_service(GreaderServiceRoot::Service::FreshRss), m_username(QString()), m_password(QString()), m_baseUrl(QString()), m_batchSize(GREADER_DEFAULT_BATCH_SIZE), m_downloadOnlyUnreadMessages(false), - m_prefetchedMessages({}), m_performGlobalFetching(false), m_intelligentSynchronization(true), - m_newerThanFilter(QDate::currentDate().addYears(-1)), - m_oauth2(new OAuth2Service(INO_OAUTH_AUTH_URL, INO_OAUTH_TOKEN_URL, - {}, {}, INO_OAUTH_SCOPE, this)) { + m_prefetchedMessages({}), m_prefetchedStatus(Feed::Status::Normal), m_performGlobalFetching(false), + m_intelligentSynchronization(true), m_newerThanFilter(QDate::currentDate().addYears(-1)), + m_oauth(new OAuth2Service(INO_OAUTH_AUTH_URL, INO_OAUTH_TOKEN_URL, + {}, {}, INO_OAUTH_SCOPE, this)) { initializeOauth(); clearCredentials(); } @@ -129,6 +130,7 @@ QVariantHash GreaderNetwork::userInfo(const QNetworkProxy& proxy) { void GreaderNetwork::clearPrefetchedMessages() { m_prefetchedMessages.clear(); + m_prefetchedStatus = Feed::Status::Normal; } void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root, @@ -139,96 +141,103 @@ void GreaderNetwork::prepareFeedFetching(GreaderServiceRoot* root, Q_UNUSED(tagged_messages) m_prefetchedMessages.clear(); + m_prefetchedStatus = Feed::Status::Normal; - double perc_of_fetching = (feeds.size() * 1.0) / root->getSubTreeFeeds().size(); + try { - m_performGlobalFetching = perc_of_fetching > GREADER_GLOBAL_UPDATE_THRES; + double perc_of_fetching = (feeds.size() * 1.0) / root->getSubTreeFeeds().size(); - qDebugNN << LOGSEC_GREADER - << "Percentage of feeds for fetching:" - << QUOTE_W_SPACE_DOT(perc_of_fetching); + m_performGlobalFetching = perc_of_fetching > GREADER_GLOBAL_UPDATE_THRES; - auto remote_starred_ids_list = itemIds(GREADER_API_FULL_STATE_IMPORTANT, false, proxy, -1, m_newerThanFilter); + qDebugNN << LOGSEC_GREADER + << "Percentage of feeds for fetching:" + << QUOTE_W_SPACE_DOT(perc_of_fetching); - for (int i = 0; i < remote_starred_ids_list.size(); i++) { - remote_starred_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_starred_ids_list.at(i))); - } + auto remote_starred_ids_list = itemIds(GREADER_API_FULL_STATE_IMPORTANT, false, proxy, -1, m_newerThanFilter); - QSet remote_starred_ids = FROM_LIST_TO_SET(QSet, remote_starred_ids_list); - QSet local_starred_ids; - QList> all_states = stated_messages.values(); - - for (auto& lst : all_states) { - auto s = lst.value(ServiceRoot::BagOfMessages::Starred); - - local_starred_ids.unite(FROM_LIST_TO_SET(QSet, s)); - } - - auto starred_to_download((remote_starred_ids - local_starred_ids).unite(local_starred_ids - remote_starred_ids)); - auto to_download = starred_to_download; - - if (m_performGlobalFetching) { - qWarningNN << LOGSEC_GREADER << "Performing global contents fetching."; - - QStringList remote_all_ids_list = m_downloadOnlyUnreadMessages - ? QStringList() - : itemIds(GREADER_API_FULL_STATE_READING_LIST, false, proxy, -1, m_newerThanFilter); - QStringList remote_unread_ids_list = itemIds(GREADER_API_FULL_STATE_READING_LIST, true, proxy, -1, m_newerThanFilter); - - for (int i = 0; i < remote_all_ids_list.size(); i++) { - remote_all_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_all_ids_list.at(i))); + for (int i = 0; i < remote_starred_ids_list.size(); i++) { + remote_starred_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_starred_ids_list.at(i))); } - for (int i = 0; i < remote_unread_ids_list.size(); i++) { - remote_unread_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_unread_ids_list.at(i))); - } - - QSet remote_all_ids = FROM_LIST_TO_SET(QSet, remote_all_ids_list); - QSet remote_unread_ids = FROM_LIST_TO_SET(QSet, remote_unread_ids_list); - QSet remote_read_ids = remote_all_ids - remote_unread_ids; - QSet local_unread_ids; - QSet local_read_ids; + QSet remote_starred_ids = FROM_LIST_TO_SET(QSet, remote_starred_ids_list); + QSet local_starred_ids; + QList> all_states = stated_messages.values(); for (auto& lst : all_states) { - auto u = lst.value(ServiceRoot::BagOfMessages::Unread); - auto r = lst.value(ServiceRoot::BagOfMessages::Read); + auto s = lst.value(ServiceRoot::BagOfMessages::Starred); - local_unread_ids.unite(FROM_LIST_TO_SET(QSet, u)); - local_read_ids.unite(FROM_LIST_TO_SET(QSet, r)); + local_starred_ids.unite(FROM_LIST_TO_SET(QSet, s)); } - if (!m_downloadOnlyUnreadMessages) { - to_download += remote_all_ids - local_read_ids - local_unread_ids; - } - else { - to_download += remote_unread_ids - local_read_ids - local_unread_ids; - } + auto starred_to_download((remote_starred_ids - local_starred_ids).unite(local_starred_ids - remote_starred_ids)); + auto to_download = starred_to_download; - auto moved_read = local_read_ids.intersect(remote_unread_ids); + if (m_performGlobalFetching) { + qWarningNN << LOGSEC_GREADER << "Performing global contents fetching."; - to_download += moved_read; + QStringList remote_all_ids_list = m_downloadOnlyUnreadMessages + ? QStringList() + : itemIds(GREADER_API_FULL_STATE_READING_LIST, false, proxy, -1, m_newerThanFilter); + QStringList remote_unread_ids_list = itemIds(GREADER_API_FULL_STATE_READING_LIST, true, proxy, -1, m_newerThanFilter); - if (!m_downloadOnlyUnreadMessages) { - auto moved_unread = local_unread_ids.intersect(remote_read_ids); + for (int i = 0; i < remote_all_ids_list.size(); i++) { + remote_all_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_all_ids_list.at(i))); + } - to_download += moved_unread; - } - } - else { - qWarningNN << LOGSEC_GREADER << "Performing feed-based contents fetching."; - } + for (int i = 0; i < remote_unread_ids_list.size(); i++) { + remote_unread_ids_list.replace(i, convertShortStreamIdToLongStreamId(remote_unread_ids_list.at(i))); + } - Feed::Status error; - QList to_download_list(to_download.values()); + QSet remote_all_ids = FROM_LIST_TO_SET(QSet, remote_all_ids_list); + QSet remote_unread_ids = FROM_LIST_TO_SET(QSet, remote_unread_ids_list); + QSet remote_read_ids = remote_all_ids - remote_unread_ids; + QSet local_unread_ids; + QSet local_read_ids; - if (!to_download_list.isEmpty()) { - if (m_service == GreaderServiceRoot::Service::Reedah) { - for (int i = 0; i < to_download_list.size(); i++) { - to_download_list.replace(i, convertLongStreamIdToShortStreamId(to_download_list.at(i))); + for (auto& lst : all_states) { + auto u = lst.value(ServiceRoot::BagOfMessages::Unread); + auto r = lst.value(ServiceRoot::BagOfMessages::Read); + + local_unread_ids.unite(FROM_LIST_TO_SET(QSet, u)); + local_read_ids.unite(FROM_LIST_TO_SET(QSet, r)); + } + + if (!m_downloadOnlyUnreadMessages) { + to_download += remote_all_ids - local_read_ids - local_unread_ids; + } + else { + to_download += remote_unread_ids - local_read_ids - local_unread_ids; + } + + auto moved_read = local_read_ids.intersect(remote_unread_ids); + + to_download += moved_read; + + if (!m_downloadOnlyUnreadMessages) { + auto moved_unread = local_unread_ids.intersect(remote_read_ids); + + to_download += moved_unread; } } + else { + qWarningNN << LOGSEC_GREADER << "Performing feed-based contents fetching."; + } - m_prefetchedMessages = itemContents(root, to_download_list, error, proxy); + Feed::Status error; + QList to_download_list(to_download.values()); + + if (!to_download_list.isEmpty()) { + if (m_service == GreaderServiceRoot::Service::Reedah) { + for (int i = 0; i < to_download_list.size(); i++) { + to_download_list.replace(i, convertLongStreamIdToShortStreamId(to_download_list.at(i))); + } + } + + m_prefetchedMessages = itemContents(root, to_download_list, error, proxy); + } + } + catch (const FeedFetchException& fex) { + m_prefetchedStatus = fex.feedStatus(); } } @@ -242,6 +251,11 @@ QList GreaderNetwork::getMessagesIntelligently(ServiceRoot* root, QList msgs; + if (m_prefetchedStatus != Feed::Status::Normal) { + error = m_prefetchedStatus; + return msgs; + } + if (!m_performGlobalFetching) { // 1. Get unread IDs for a feed. // 2. Get read IDs for a feed. @@ -339,7 +353,7 @@ QStringList GreaderNetwork::itemIds(const QString& stream_id, bool unread_only, QString continuation; if (!ensureLogin(proxy)) { - throw ApplicationException(tr("login failed")); + throw FeedFetchException(Feed::Status::AuthError, tr("login failed")); } QStringList ids; @@ -839,7 +853,7 @@ void GreaderNetwork::setBaseUrl(const QString& base_url) { QPair GreaderNetwork::authHeader() const { if (m_service == GreaderServiceRoot::Service::Inoreader) { return { QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), - m_oauth2->bearer().toLocal8Bit() }; + m_oauth->bearer().toLocal8Bit() }; } else { return { QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), @@ -849,7 +863,7 @@ QPair GreaderNetwork::authHeader() const { bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output) { if (m_service == GreaderServiceRoot::Service::Inoreader) { - return !m_oauth2->bearer().isEmpty(); + return !m_oauth->bearer().isEmpty(); } if (m_authSid.isEmpty() && m_authAuth.isEmpty()) { @@ -1073,20 +1087,20 @@ void GreaderNetwork::onTokensError(const QString& error, const QString& error_de QSystemTrayIcon::MessageIcon::Critical, {}, {}, [this]() { - m_oauth2->setAccessToken(QString()); - m_oauth2->setRefreshToken(QString()); - m_oauth2->login(); + m_oauth->setAccessToken(QString()); + m_oauth->setRefreshToken(QString()); + m_oauth->login(); }); } void GreaderNetwork::onAuthFailed() { - qApp->showGuiMessage(Notification::Event::GeneralEvent, + qApp->showGuiMessage(Notification::Event::LoginFailure, tr("Inoreader: authorization denied"), tr("Click this to login again."), QSystemTrayIcon::MessageIcon::Critical, {}, {}, [this]() { - m_oauth2->login(); + m_oauth->login(); }); } @@ -1096,14 +1110,14 @@ void GreaderNetwork::initializeOauth() { m_oauth2->setClientSecretSecret(TextFactory::decrypt(INOREADER_CLIENT_SECRET, OAUTH_DECRYPTION_KEY)); #endif - m_oauth2->setRedirectUrl(QString(OAUTH_REDIRECT_URI) + - QL1C(':') + - QString::number(INO_OAUTH_REDIRECT_URI_PORT), - false); + m_oauth->setRedirectUrl(QString(OAUTH_REDIRECT_URI) + + QL1C(':') + + QString::number(INO_OAUTH_REDIRECT_URI_PORT), + false); - connect(m_oauth2, &OAuth2Service::tokensRetrieveError, this, &GreaderNetwork::onTokensError); - connect(m_oauth2, &OAuth2Service::authFailed, this, &GreaderNetwork::onAuthFailed); - connect(m_oauth2, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) { + connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &GreaderNetwork::onTokensError); + connect(m_oauth, &OAuth2Service::authFailed, this, &GreaderNetwork::onAuthFailed); + connect(m_oauth, &OAuth2Service::tokensRetrieved, this, [this](QString access_token, QString refresh_token, int expires_in) { Q_UNUSED(expires_in) Q_UNUSED(access_token) @@ -1124,11 +1138,11 @@ void GreaderNetwork::setNewerThanFilter(const QDate& newer_than) { } OAuth2Service* GreaderNetwork::oauth() const { - return m_oauth2; + return m_oauth; } void GreaderNetwork::setOauth(OAuth2Service* oauth) { - m_oauth2 = oauth; + m_oauth = oauth; } void GreaderNetwork::setRoot(GreaderServiceRoot* root) { diff --git a/src/librssguard/services/greader/greadernetwork.h b/src/librssguard/services/greader/greadernetwork.h index f3e45c7c8..16e06848c 100755 --- a/src/librssguard/services/greader/greadernetwork.h +++ b/src/librssguard/services/greader/greadernetwork.h @@ -132,10 +132,11 @@ class GreaderNetwork : public QObject { QString m_authAuth; QString m_authToken; QList m_prefetchedMessages; + Feed::Status m_prefetchedStatus; bool m_performGlobalFetching; bool m_intelligentSynchronization; QDate m_newerThanFilter; - OAuth2Service* m_oauth2; + OAuth2Service* m_oauth; }; #endif // GREADERNETWORK_H