Some initial code for #105.
This commit is contained in:
parent
da8de799b7
commit
0c56897bca
14
pri/vars.pri
14
pri/vars.pri
@ -34,3 +34,17 @@ isEmpty(USE_WEBENGINE) {
|
||||
##message($$MSG_PREFIX: WebEngine component is probably NOT installed, disabling it.)
|
||||
}
|
||||
}
|
||||
|
||||
isEmpty(FEEDLY_CLIENT_ID)|isEmpty(FEEDLY_CLIENT_SECRET) {
|
||||
FEEDLY_OFFICIAL_SUPPORT = false
|
||||
|
||||
message($$MSG_PREFIX: Feedly client ID/secret variables are not set. Disabling official support.)
|
||||
}
|
||||
else {
|
||||
FEEDLY_OFFICIAL_SUPPORT = true
|
||||
DEFINES *= FEEDLY_OFFICIAL_SUPPORT
|
||||
DEFINES *= FEEDLY_CLIENT_ID='"\\\"$$FEEDLY_CLIENT_ID\\\""'
|
||||
DEFINES *= FEEDLY_CLIENT_SECRET='"\\\"$$FEEDLY_CLIENT_SECRET\\\""'
|
||||
|
||||
message($$MSG_PREFIX: Enabling official Feedly support.)
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
<url type="donation">https://martinrotter.github.io/donate/</url>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="3.8.4" date="2021-02-05"/>
|
||||
<release version="3.8.4" date="2021-02-08"/>
|
||||
</releases>
|
||||
<content_rating type="oars-1.0">
|
||||
<content_attribute id="violence-cartoon">none</content_attribute>
|
||||
|
BIN
resources/graphics/misc/feedly.png
Executable file
BIN
resources/graphics/misc/feedly.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
@ -17,6 +17,7 @@
|
||||
<file>graphics/misc/adblock.png</file>
|
||||
<file>graphics/misc/adblock-disabled.png</file>
|
||||
<file>graphics/misc/bazqux.png</file>
|
||||
<file>graphics/misc/feedly.png</file>
|
||||
<file>graphics/misc/freshrss.png</file>
|
||||
<file>graphics/misc/gmail.png</file>
|
||||
<file>graphics/misc/google.png</file>
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749
|
||||
Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9
|
@ -13,6 +13,7 @@
|
||||
#define SERVICE_CODE_TT_RSS "tt-rss"
|
||||
#define SERVICE_CODE_OWNCLOUD "owncloud"
|
||||
#define SERVICE_CODE_GREADER "greader"
|
||||
#define SERVICE_CODE_FEEDLY "feedly"
|
||||
#define SERVICE_CODE_INOREADER "inoreader"
|
||||
#define SERVICE_CODE_GMAIL "gmail"
|
||||
|
||||
|
@ -143,6 +143,13 @@ HEADERS += core/feeddownloader.h \
|
||||
services/abstract/rootitem.h \
|
||||
services/abstract/serviceentrypoint.h \
|
||||
services/abstract/serviceroot.h \
|
||||
services/feedly/definitions.h \
|
||||
services/feedly/feedlyentrypoint.h \
|
||||
services/feedly/feedlyfeed.h \
|
||||
services/feedly/feedlynetwork.h \
|
||||
services/feedly/feedlyserviceroot.h \
|
||||
services/feedly/gui/feedlyaccountdetails.h \
|
||||
services/feedly/gui/formeditfeedlyaccount.h \
|
||||
services/gmail/definitions.h \
|
||||
services/gmail/gmailentrypoint.h \
|
||||
services/gmail/gmailfeed.h \
|
||||
@ -312,6 +319,12 @@ SOURCES += core/feeddownloader.cpp \
|
||||
services/abstract/recyclebin.cpp \
|
||||
services/abstract/rootitem.cpp \
|
||||
services/abstract/serviceroot.cpp \
|
||||
services/feedly/feedlyentrypoint.cpp \
|
||||
services/feedly/feedlyfeed.cpp \
|
||||
services/feedly/feedlynetwork.cpp \
|
||||
services/feedly/feedlyserviceroot.cpp \
|
||||
services/feedly/gui/feedlyaccountdetails.cpp \
|
||||
services/feedly/gui/formeditfeedlyaccount.cpp \
|
||||
services/gmail/gmailentrypoint.cpp \
|
||||
services/gmail/gmailfeed.cpp \
|
||||
services/gmail/gmailserviceroot.cpp \
|
||||
@ -398,6 +411,7 @@ FORMS += gui/dialogs/formabout.ui \
|
||||
services/abstract/gui/formaccountdetails.ui \
|
||||
services/abstract/gui/formfeeddetails.ui \
|
||||
services/abstract/gui/authenticationdetails.ui \
|
||||
services/feedly/gui/feedlyaccountdetails.ui \
|
||||
services/gmail/gui/gmailaccountdetails.ui \
|
||||
services/greader/gui/greaderaccountdetails.ui \
|
||||
services/inoreader/gui/inoreaderaccountdetails.ui \
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
#include "services/feedly/feedlyentrypoint.h"
|
||||
#include "services/gmail/gmailentrypoint.h"
|
||||
#include "services/greader/greaderentrypoint.h"
|
||||
#include "services/inoreader/inoreaderentrypoint.h"
|
||||
@ -55,6 +56,7 @@ FeedReader::~FeedReader() {
|
||||
QList<ServiceEntryPoint*> FeedReader::feedServices() {
|
||||
if (m_feedServices.isEmpty()) {
|
||||
// NOTE: All installed services create their entry points here.
|
||||
m_feedServices.append(new FeedlyEntryPoint());
|
||||
m_feedServices.append(new GmailEntryPoint());
|
||||
m_feedServices.append(new GreaderEntryPoint());
|
||||
m_feedServices.append(new InoreaderEntryPoint());
|
||||
|
@ -10,7 +10,8 @@
|
||||
#include <QTcpSocket>
|
||||
#include <QUrlQuery>
|
||||
|
||||
OAuthHttpHandler::OAuthHttpHandler(const QString& success_text, QObject* parent) : QObject(parent), m_successText(success_text) {
|
||||
OAuthHttpHandler::OAuthHttpHandler(const QString& success_text, QObject* parent)
|
||||
: QObject(parent), m_successText(success_text) {
|
||||
connect(&m_httpServer, &QTcpServer::newConnection, this, &OAuthHttpHandler::clientConnected);
|
||||
setListenAddressPort(QString(OAUTH_REDIRECT_URI) + QL1C(':') + QString::number(OAUTH_REDIRECT_URI_PORT));
|
||||
}
|
||||
|
14
src/librssguard/services/feedly/definitions.h
Executable file
14
src/librssguard/services/feedly/definitions.h
Executable file
@ -0,0 +1,14 @@
|
||||
#ifndef FEEDLY_DEFINITIONS_H
|
||||
#define FEEDLY_DEFINITIONS_H
|
||||
|
||||
#define FEEDLY_UNLIMITED_BATCH_SIZE -1
|
||||
#define FEEDLY_GENERATE_DAT "https://feedly.com/v3/auth/dev"
|
||||
|
||||
#define FEEDLY_API_REDIRECT_URI_PORT 8080
|
||||
#define FEEDLY_API_SCOPE "https://cloud.feedly.com/subscriptions"
|
||||
|
||||
#define FEEDLY_API_URL_BASE "https://cloud.feedly.com/v3/"
|
||||
#define FEEDLY_API_URL_AUTH "auth/auth"
|
||||
#define FEEDLY_API_URL_TOKEN "auth/token"
|
||||
|
||||
#endif // FEEDLY_DEFINITIONS_H
|
47
src/librssguard/services/feedly/feedlyentrypoint.cpp
Executable file
47
src/librssguard/services/feedly/feedlyentrypoint.cpp
Executable file
@ -0,0 +1,47 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/feedlyentrypoint.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/feedly/definitions.h"
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
#include "services/feedly/gui/formeditfeedlyaccount.h"
|
||||
|
||||
ServiceRoot* FeedlyEntryPoint::createNewRoot() const {
|
||||
FormEditFeedlyAccount form_acc(qApp->mainFormWidget());
|
||||
|
||||
return form_acc.addEditAccount<FeedlyServiceRoot>();
|
||||
}
|
||||
|
||||
QList<ServiceRoot*> FeedlyEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("FeedlyEntryPoint"));
|
||||
|
||||
return {};
|
||||
|
||||
//return DatabaseQueries::getGreaderAccounts(database);
|
||||
}
|
||||
|
||||
QString FeedlyEntryPoint::name() const {
|
||||
return QSL("Feedly (WIP)");
|
||||
}
|
||||
|
||||
QString FeedlyEntryPoint::code() const {
|
||||
return SERVICE_CODE_FEEDLY;
|
||||
}
|
||||
|
||||
QString FeedlyEntryPoint::description() const {
|
||||
return QObject::tr("Keep up with the topics and trends you care about, without the overwhelm. "
|
||||
"Feedly is a secure space where you can privately organize and research the "
|
||||
"topics and trends that matter to you.");
|
||||
}
|
||||
|
||||
QString FeedlyEntryPoint::author() const {
|
||||
return APP_AUTHOR;
|
||||
}
|
||||
|
||||
QIcon FeedlyEntryPoint::icon() const {
|
||||
return qApp->icons()->miscIcon(QSL("feedly"));
|
||||
}
|
19
src/librssguard/services/feedly/feedlyentrypoint.h
Executable file
19
src/librssguard/services/feedly/feedlyentrypoint.h
Executable file
@ -0,0 +1,19 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDLYENTRYPOINT_H
|
||||
#define FEEDLYENTRYPOINT_H
|
||||
|
||||
#include "services/abstract/serviceentrypoint.h"
|
||||
|
||||
class FeedlyEntryPoint : public ServiceEntryPoint {
|
||||
public:
|
||||
virtual ServiceRoot* createNewRoot() const;
|
||||
virtual QList<ServiceRoot*> initializeSubtree() const;
|
||||
virtual QString name() const;
|
||||
virtual QString code() const;
|
||||
virtual QString description() const;
|
||||
virtual QString author() const;
|
||||
virtual QIcon icon() const;
|
||||
};
|
||||
|
||||
#endif // FEEDLYENTRYPOINT_H
|
35
src/librssguard/services/feedly/feedlyfeed.cpp
Executable file
35
src/librssguard/services/feedly/feedlyfeed.cpp
Executable file
@ -0,0 +1,35 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/feedlyfeed.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
|
||||
FeedlyFeed::FeedlyFeed(RootItem* parent) : Feed(parent) {}
|
||||
|
||||
FeedlyFeed::FeedlyFeed(const QSqlRecord& record) : Feed(record) {}
|
||||
|
||||
FeedlyServiceRoot* FeedlyFeed::serviceRoot() const {
|
||||
return qobject_cast<FeedlyServiceRoot*>(getParentServiceRoot());
|
||||
}
|
||||
|
||||
QList<Message> FeedlyFeed::obtainNewMessages(bool* error_during_obtaining) {
|
||||
return {};
|
||||
|
||||
/*
|
||||
Feed::Status error = Feed::Status::Normal;
|
||||
QList<Message> messages = serviceRoot()->network()->streamContents(getParentServiceRoot(),
|
||||
customId(),
|
||||
error,
|
||||
getParentServiceRoot()->networkProxy());
|
||||
|
||||
setStatus(error);
|
||||
|
||||
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
|
||||
* error_during_obtaining = true;
|
||||
}
|
||||
|
||||
return messages;*/
|
||||
}
|
19
src/librssguard/services/feedly/feedlyfeed.h
Executable file
19
src/librssguard/services/feedly/feedlyfeed.h
Executable file
@ -0,0 +1,19 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDLYFEED_H
|
||||
#define FEEDLYFEED_H
|
||||
|
||||
#include "services/abstract/feed.h"
|
||||
|
||||
class FeedlyServiceRoot;
|
||||
|
||||
class FeedlyFeed : public Feed {
|
||||
public:
|
||||
explicit FeedlyFeed(RootItem* parent = nullptr);
|
||||
explicit FeedlyFeed(const QSqlRecord& record);
|
||||
|
||||
FeedlyServiceRoot* serviceRoot() const;
|
||||
QList<Message> obtainNewMessages(bool* error_during_obtaining);
|
||||
};
|
||||
|
||||
#endif // FEEDLYFEED_H
|
123
src/librssguard/services/feedly/feedlynetwork.cpp
Executable file
123
src/librssguard/services/feedly/feedlynetwork.cpp
Executable file
@ -0,0 +1,123 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
|
||||
#include "network-web/webfactory.h"
|
||||
#include "services/abstract/category.h"
|
||||
#include "services/abstract/label.h"
|
||||
#include "services/abstract/labelsnode.h"
|
||||
#include "services/feedly/definitions.h"
|
||||
#include "services/feedly/feedlyfeed.h"
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
#include "network-web/oauth2service.h"
|
||||
#endif
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
FeedlyNetwork::FeedlyNetwork(QObject* parent)
|
||||
: QObject(parent), m_service(nullptr),
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_oauth(new OAuth2Service(QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_AUTH,
|
||||
QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_TOKEN,
|
||||
"dontknow",
|
||||
"dontknow",
|
||||
FEEDLY_API_SCOPE, this)),
|
||||
#endif
|
||||
m_username(QString()),
|
||||
m_developerAccessToken(QString()), m_batchSize(FEEDLY_UNLIMITED_BATCH_SIZE) {
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_oauth->setRedirectUrl(QString(OAUTH_REDIRECT_URI) + QL1C(':') + QString::number(FEEDLY_API_REDIRECT_URI_PORT));
|
||||
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &FeedlyNetwork::onTokensError);
|
||||
connect(m_oauth, &OAuth2Service::authFailed, this, &FeedlyNetwork::onAuthFailed);
|
||||
connect(m_oauth, &OAuth2Service::tokensReceived, this, &FeedlyNetwork::onTokensReceived);
|
||||
#endif
|
||||
}
|
||||
|
||||
QString FeedlyNetwork::username() const {
|
||||
return m_username;
|
||||
}
|
||||
|
||||
void FeedlyNetwork::setUsername(const QString& username) {
|
||||
m_username = username;
|
||||
}
|
||||
|
||||
QString FeedlyNetwork::developerAccessToken() const {
|
||||
return m_developerAccessToken;
|
||||
}
|
||||
|
||||
void FeedlyNetwork::setDeveloperAccessToken(const QString& dev_acc_token) {
|
||||
m_developerAccessToken = dev_acc_token;
|
||||
}
|
||||
|
||||
int FeedlyNetwork::batchSize() const {
|
||||
return m_batchSize;
|
||||
}
|
||||
|
||||
void FeedlyNetwork::setBatchSize(int batch_size) {
|
||||
m_batchSize = batch_size;
|
||||
}
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
|
||||
void FeedlyNetwork::onTokensError(const QString& error, const QString& error_description) {
|
||||
Q_UNUSED(error)
|
||||
|
||||
qApp->showGuiMessage(tr("Feedly: authentication error"),
|
||||
tr("Click this to login again. Error is: '%1'").arg(error_description),
|
||||
QSystemTrayIcon::MessageIcon::Critical,
|
||||
nullptr, false,
|
||||
[this]() {
|
||||
m_oauth->setAccessToken({});
|
||||
m_oauth->setRefreshToken({});
|
||||
m_oauth->login();
|
||||
});
|
||||
}
|
||||
|
||||
void FeedlyNetwork::onAuthFailed() {
|
||||
qApp->showGuiMessage(tr("Feedly: authorization denied"),
|
||||
tr("Click this to login again."),
|
||||
QSystemTrayIcon::MessageIcon::Critical,
|
||||
nullptr, false,
|
||||
[this]() {
|
||||
m_oauth->login();
|
||||
});
|
||||
}
|
||||
|
||||
void FeedlyNetwork::onTokensReceived(const QString& access_token, const QString& refresh_token, int expires_in) {
|
||||
Q_UNUSED(expires_in)
|
||||
Q_UNUSED(access_token)
|
||||
|
||||
if (m_service != nullptr && !refresh_token.isEmpty()) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
//DatabaseQueries::storeNewInoreaderTokens(database, refresh_token, m_service->accountId());
|
||||
|
||||
qApp->showGuiMessage(tr("Logged in successfully"),
|
||||
tr("Your login to Feedly was authorized."),
|
||||
QSystemTrayIcon::MessageIcon::Information);
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2Service* FeedlyNetwork::oauth() const {
|
||||
return m_oauth;
|
||||
}
|
||||
|
||||
void FeedlyNetwork::setOauth(OAuth2Service* oauth) {
|
||||
m_oauth = oauth;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void FeedlyNetwork::setService(FeedlyServiceRoot* service) {
|
||||
m_service = service;
|
||||
}
|
56
src/librssguard/services/feedly/feedlynetwork.h
Executable file
56
src/librssguard/services/feedly/feedlynetwork.h
Executable file
@ -0,0 +1,56 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDLYNETWORK_H
|
||||
#define FEEDLYNETWORK_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "services/abstract/feed.h"
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
class OAuth2Service;
|
||||
#endif
|
||||
|
||||
class FeedlyServiceRoot;
|
||||
|
||||
class FeedlyNetwork : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FeedlyNetwork(QObject* parent = nullptr);
|
||||
|
||||
QString username() const;
|
||||
void setUsername(const QString& username);
|
||||
|
||||
QString developerAccessToken() const;
|
||||
void setDeveloperAccessToken(const QString& dev_acc_token);
|
||||
|
||||
int batchSize() const;
|
||||
void setBatchSize(int batch_size);
|
||||
|
||||
void setService(FeedlyServiceRoot* service);
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
OAuth2Service* oauth() const;
|
||||
void setOauth(OAuth2Service* oauth);
|
||||
|
||||
private slots:
|
||||
void onTokensError(const QString& error, const QString& error_description);
|
||||
void onAuthFailed();
|
||||
void onTokensReceived(const QString& access_token, const QString& refresh_token, int expires_in);
|
||||
#endif
|
||||
|
||||
private:
|
||||
FeedlyServiceRoot* m_service;
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
OAuth2Service* m_oauth;
|
||||
#endif
|
||||
|
||||
QString m_username;
|
||||
QString m_developerAccessToken;
|
||||
int m_batchSize;
|
||||
};
|
||||
|
||||
#endif // FEEDLYNETWORK_H
|
111
src/librssguard/services/feedly/feedlyserviceroot.cpp
Executable file
111
src/librssguard/services/feedly/feedlyserviceroot.cpp
Executable file
@ -0,0 +1,111 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "services/abstract/importantnode.h"
|
||||
#include "services/abstract/recyclebin.h"
|
||||
#include "services/feedly/feedlyentrypoint.h"
|
||||
#include "services/feedly/feedlyfeed.h"
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
#include "services/feedly/gui/formeditfeedlyaccount.h"
|
||||
|
||||
FeedlyServiceRoot::FeedlyServiceRoot(RootItem* parent)
|
||||
: ServiceRoot(parent), m_network(new FeedlyNetwork(this)) {
|
||||
setIcon(FeedlyEntryPoint().icon());
|
||||
m_network->setService(this);
|
||||
}
|
||||
|
||||
bool FeedlyServiceRoot::isSyncable() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedlyServiceRoot::canBeEdited() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedlyServiceRoot::canBeDeleted() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedlyServiceRoot::editViaGui() {
|
||||
FormEditFeedlyAccount form_pointer(qApp->mainFormWidget());
|
||||
|
||||
form_pointer.addEditAccount(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FeedlyServiceRoot::deleteViaGui() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::deleteGreaderAccount(database, accountId())) {
|
||||
return ServiceRoot::deleteViaGui();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FeedlyServiceRoot::start(bool freshly_activated) {
|
||||
Q_UNUSED(freshly_activated)
|
||||
loadFromDatabase();
|
||||
loadCacheFromFile();
|
||||
|
||||
if (childCount() <= 3) {
|
||||
syncIn();
|
||||
}
|
||||
}
|
||||
|
||||
QString FeedlyServiceRoot::code() const {
|
||||
return FeedlyServiceRoot().code();
|
||||
}
|
||||
|
||||
void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) {
|
||||
auto msg_cache = takeMessageCache();
|
||||
}
|
||||
|
||||
void FeedlyServiceRoot::updateTitle() {
|
||||
setTitle(QString("%1 (Feedly)").arg(TextFactory::extractUsernameFromEmail(m_network->username())));
|
||||
}
|
||||
|
||||
void FeedlyServiceRoot::saveAccountDataToDatabase(bool creating_new) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
|
||||
/*
|
||||
if (!creating_new) {
|
||||
if (DatabaseQueries::overwriteGreaderAccount(database, m_network->username(),
|
||||
m_network->password(), m_network->service(),
|
||||
m_network->baseUrl(), m_network->batchSize(),
|
||||
accountId())) {
|
||||
updateTitle();
|
||||
itemChanged(QList<RootItem*>() << this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (DatabaseQueries::createGreaderAccount(database, accountId(), m_network->username(),
|
||||
m_network->password(), m_network->service(),
|
||||
m_network->baseUrl(), m_network->batchSize())) {
|
||||
updateTitle();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
RootItem* FeedlyServiceRoot::obtainNewTreeForSyncIn() const {
|
||||
return nullptr;
|
||||
|
||||
//return m_network->categoriesFeedsLabelsTree(true, networkProxy());
|
||||
}
|
||||
|
||||
void FeedlyServiceRoot::loadFromDatabase() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
Assignment categories = DatabaseQueries::getCategories<Category>(database, accountId());
|
||||
Assignment feeds = DatabaseQueries::getFeeds<FeedlyFeed>(database, qApp->feedReader()->messageFilters(), accountId());
|
||||
auto labels = DatabaseQueries::getLabels(database, accountId());
|
||||
|
||||
performInitialAssembly(categories, feeds, labels);
|
||||
}
|
45
src/librssguard/services/feedly/feedlyserviceroot.h
Executable file
45
src/librssguard/services/feedly/feedlyserviceroot.h
Executable file
@ -0,0 +1,45 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDLYSERVICEROOT_H
|
||||
#define FEEDLYSERVICEROOT_H
|
||||
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
||||
class FeedlyNetwork;
|
||||
|
||||
class FeedlyServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FeedlyServiceRoot(RootItem* parent = nullptr);
|
||||
|
||||
virtual bool isSyncable() const;
|
||||
virtual bool canBeEdited() const;
|
||||
virtual bool canBeDeleted() const;
|
||||
virtual bool editViaGui();
|
||||
virtual bool deleteViaGui();
|
||||
virtual void start(bool freshly_activated);
|
||||
virtual QString code() const;
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
|
||||
FeedlyNetwork* network() const;
|
||||
|
||||
void updateTitle();
|
||||
void saveAccountDataToDatabase(bool creating_new);
|
||||
|
||||
protected:
|
||||
virtual RootItem* obtainNewTreeForSyncIn() const;
|
||||
|
||||
private:
|
||||
void loadFromDatabase();
|
||||
|
||||
private:
|
||||
FeedlyNetwork* m_network;
|
||||
};
|
||||
|
||||
inline FeedlyNetwork* FeedlyServiceRoot::network() const {
|
||||
return m_network;
|
||||
}
|
||||
|
||||
#endif // FEEDLYSERVICEROOT_H
|
153
src/librssguard/services/feedly/gui/feedlyaccountdetails.cpp
Executable file
153
src/librssguard/services/feedly/gui/feedlyaccountdetails.cpp
Executable file
@ -0,0 +1,153 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/gui/feedlyaccountdetails.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "gui/guiutilities.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/systemfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "services/feedly/definitions.h"
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
#include "network-web/oauth2service.h"
|
||||
#endif
|
||||
|
||||
FeedlyAccountDetails::FeedlyAccountDetails(QWidget* parent) : QWidget(parent) {
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_oauth = new OAuth2Service(QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_AUTH,
|
||||
QSL(FEEDLY_API_URL_BASE) + FEEDLY_API_URL_TOKEN,
|
||||
"dontknow",
|
||||
"dontknow",
|
||||
FEEDLY_API_SCOPE, this),
|
||||
#endif
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_ui.m_lblTestResult->label()->setWordWrap(true);
|
||||
m_ui.m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your account"));
|
||||
m_ui.m_txtDeveloperAccessToken->lineEdit()->setPlaceholderText(tr("Developer access token"));
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Information,
|
||||
tr("No test done yet."),
|
||||
tr("Here, results of connection test are shown."));
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_ui.m_lblInfo->setText(tr("Your %1 build has official Feedly support. You do not have to use \"developer acess "
|
||||
"token\". You can therefore leave corresponding field empty.").arg(APP_NAME));
|
||||
#else
|
||||
m_ui.m_lblInfo->setText(tr("Your %1 does not offer official Feedly support, thus you must "
|
||||
"authorize via special authorization code called \"developer access token\". "
|
||||
"These tokens are usually valid only for 1 month and allow only 250 API calls "
|
||||
"each day.").arg(APP_NAME));
|
||||
#endif
|
||||
|
||||
connect(m_ui.m_spinLimitMessages, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=](int value) {
|
||||
if (value <= 0) {
|
||||
m_ui.m_spinLimitMessages->setSuffix(QSL(" ") + tr("= unlimited"));
|
||||
}
|
||||
else {
|
||||
m_ui.m_spinLimitMessages->setSuffix(QSL(" ") + tr("messages"));
|
||||
}
|
||||
});
|
||||
|
||||
GuiUtilities::setLabelAsNotice(*m_ui.m_lblInfo, true);
|
||||
|
||||
connect(m_ui.m_btnGetToken, &QPushButton::clicked, this, &FeedlyAccountDetails::getDeveloperAccessToken);
|
||||
connect(m_ui.m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FeedlyAccountDetails::onUsernameChanged);
|
||||
connect(m_ui.m_txtDeveloperAccessToken->lineEdit(), &BaseLineEdit::textChanged,
|
||||
this, &FeedlyAccountDetails::onDeveloperAccessTokenChanged);
|
||||
|
||||
setTabOrder(m_ui.m_txtUsername->lineEdit(), m_ui.m_btnGetToken);
|
||||
setTabOrder(m_ui.m_btnGetToken, m_ui.m_txtDeveloperAccessToken->lineEdit());
|
||||
setTabOrder(m_ui.m_txtDeveloperAccessToken->lineEdit(), m_ui.m_spinLimitMessages);
|
||||
setTabOrder(m_ui.m_spinLimitMessages, m_ui.m_btnTestSetup);
|
||||
|
||||
onDeveloperAccessTokenChanged();
|
||||
onUsernameChanged();
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
hookNetwork();
|
||||
#endif
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::getDeveloperAccessToken() {
|
||||
qApp->web()->openUrlInExternalBrowser(FEEDLY_GENERATE_DAT);
|
||||
}
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
|
||||
void FeedlyAccountDetails::hookNetwork() {
|
||||
connect(m_oauth, &OAuth2Service::tokensReceived, this, &FeedlyAccountDetails::onAuthGranted);
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &FeedlyAccountDetails::onAuthError);
|
||||
connect(m_oauth, &OAuth2Service::authFailed, this, &FeedlyAccountDetails::onAuthFailed);
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::onAuthFailed() {
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Error,
|
||||
tr("You did not grant access."),
|
||||
tr("There was error during testing."));
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::onAuthError(const QString& error, const QString& detailed_description) {
|
||||
Q_UNUSED(error)
|
||||
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Error,
|
||||
tr("There is error. %1").arg(detailed_description),
|
||||
tr("There was error during testing."));
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::onAuthGranted() {
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Ok,
|
||||
tr("Tested successfully. You may be prompted to login once more."),
|
||||
tr("Your access was approved."));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void FeedlyAccountDetails::performTest(const QNetworkProxy& custom_proxy) {
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_oauth->logout();
|
||||
|
||||
if (m_oauth->login()) {
|
||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Ok,
|
||||
tr("You are already logged in."),
|
||||
tr("Access granted."));
|
||||
}
|
||||
#else
|
||||
FeedlyNetwork factory;
|
||||
|
||||
factory.setUsername(m_ui.m_txtUsername->lineEdit()->text());
|
||||
factory.setDeveloperAccessToken(m_ui.m_txtDeveloperAccessToken->lineEdit()->text());
|
||||
|
||||
// TODO: todo
|
||||
#endif
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::onUsernameChanged() {
|
||||
const QString username = m_ui.m_txtUsername->lineEdit()->text();
|
||||
|
||||
if (username.isEmpty()) {
|
||||
m_ui.m_txtUsername->setStatus(WidgetWithStatus::StatusType::Error, tr("Username cannot be empty."));
|
||||
}
|
||||
else {
|
||||
m_ui.m_txtUsername->setStatus(WidgetWithStatus::StatusType::Ok, tr("Username is okay."));
|
||||
}
|
||||
}
|
||||
|
||||
void FeedlyAccountDetails::onDeveloperAccessTokenChanged() {
|
||||
const QString token = m_ui.m_txtDeveloperAccessToken->lineEdit()->text();
|
||||
|
||||
if (token.isEmpty()) {
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
WidgetWithStatus::StatusType stat = WidgetWithStatus::StatusType::Ok;
|
||||
#else
|
||||
WidgetWithStatus::StatusType stat = WidgetWithStatus::StatusType::Error;
|
||||
#endif
|
||||
|
||||
m_ui.m_txtDeveloperAccessToken->setStatus(stat, tr("Access token is empty."));
|
||||
}
|
||||
else {
|
||||
m_ui.m_txtDeveloperAccessToken->setStatus(WidgetWithStatus::StatusType::Ok, tr("Access token is okay."));
|
||||
}
|
||||
}
|
50
src/librssguard/services/feedly/gui/feedlyaccountdetails.h
Executable file
50
src/librssguard/services/feedly/gui/feedlyaccountdetails.h
Executable file
@ -0,0 +1,50 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDLYACCOUNTDETAILS_H
|
||||
#define FEEDLYACCOUNTDETAILS_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ui_feedlyaccountdetails.h"
|
||||
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
class OAuth2Service;
|
||||
#endif
|
||||
|
||||
class FeedlyAccountDetails : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
friend class FormEditFeedlyAccount;
|
||||
|
||||
public:
|
||||
explicit FeedlyAccountDetails(QWidget* parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void getDeveloperAccessToken();
|
||||
void performTest(const QNetworkProxy& custom_proxy);
|
||||
void onUsernameChanged();
|
||||
void onDeveloperAccessTokenChanged();
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
private slots:
|
||||
void onAuthFailed();
|
||||
void onAuthError(const QString& error, const QString& detailed_description);
|
||||
void onAuthGranted();
|
||||
|
||||
private:
|
||||
void hookNetwork();
|
||||
#endif
|
||||
|
||||
private:
|
||||
Ui::FeedlyAccountDetails m_ui;
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
OAuth2Service* m_oauth;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FEEDLYACCOUNTDETAILS_H
|
131
src/librssguard/services/feedly/gui/feedlyaccountdetails.ui
Executable file
131
src/librssguard/services/feedly/gui/feedlyaccountdetails.ui
Executable file
@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FeedlyAccountDetails</class>
|
||||
<widget class="QWidget" name="FeedlyAccountDetails">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>235</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="m_lblUsername">
|
||||
<property name="text">
|
||||
<string>Username</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="LineEditWithStatus" name="m_txtUsername" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="m_lblUsername_2">
|
||||
<property name="text">
|
||||
<string>Developer access token</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_btnGetToken">
|
||||
<property name="text">
|
||||
<string>Get token</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LineEditWithStatus" name="m_txtDeveloperAccessToken" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="m_lblInfo">
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="m_spinLimitMessages">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> message(s)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Only download newest X messages per feed</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_spinLimitMessages</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>86</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="m_btnTestSetup">
|
||||
<property name="text">
|
||||
<string>&Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="LabelWithStatus" name="m_lblTestResult" native="true">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::RightToLeft</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LineEditWithStatus</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>lineeditwithstatus.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LabelWithStatus</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>labelwithstatus.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
66
src/librssguard/services/feedly/gui/formeditfeedlyaccount.cpp
Executable file
66
src/librssguard/services/feedly/gui/formeditfeedlyaccount.cpp
Executable file
@ -0,0 +1,66 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "services/feedly/gui/formeditfeedlyaccount.h"
|
||||
|
||||
#include "gui/guiutilities.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "services/feedly/definitions.h"
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
#include "services/feedly/gui/feedlyaccountdetails.h"
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
#include "network-web/oauth2service.h"
|
||||
#endif
|
||||
|
||||
FormEditFeedlyAccount::FormEditFeedlyAccount(QWidget* parent)
|
||||
: FormAccountDetails(qApp->icons()->miscIcon(QSL("google")), parent), m_details(new FeedlyAccountDetails(this)) {
|
||||
insertCustomTab(m_details, tr("Service setup"), 0);
|
||||
activateTab(0);
|
||||
|
||||
connect(m_details->m_ui.m_btnTestSetup, &QPushButton::clicked, this, &FormEditFeedlyAccount::performTest);
|
||||
m_details->m_ui.m_txtUsername->setFocus();
|
||||
}
|
||||
|
||||
void FormEditFeedlyAccount::apply() {
|
||||
bool editing_account = !applyInternal<FeedlyServiceRoot>();
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
// We copy credentials from testing OAuth to live OAuth.
|
||||
account<FeedlyServiceRoot>()->network()->oauth()->setAccessToken(m_details->m_oauth->accessToken());
|
||||
account<FeedlyServiceRoot>()->network()->oauth()->setRefreshToken(m_details->m_oauth->refreshToken());
|
||||
account<FeedlyServiceRoot>()->network()->oauth()->setTokensExpireIn(m_details->m_oauth->tokensExpireIn());
|
||||
#endif
|
||||
|
||||
account<FeedlyServiceRoot>()->network()->setUsername(m_details->m_ui.m_txtUsername->lineEdit()->text());
|
||||
account<FeedlyServiceRoot>()->network()->setBatchSize(m_details->m_ui.m_spinLimitMessages->value());
|
||||
account<FeedlyServiceRoot>()->network()->setDeveloperAccessToken(m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->text());
|
||||
|
||||
account<FeedlyServiceRoot>()->saveAccountDataToDatabase(!editing_account);
|
||||
accept();
|
||||
|
||||
if (editing_account) {
|
||||
account<FeedlyServiceRoot>()->completelyRemoveAllData();
|
||||
account<FeedlyServiceRoot>()->syncIn();
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditFeedlyAccount::setEditableAccount(ServiceRoot* editable_account) {
|
||||
FormAccountDetails::setEditableAccount(editable_account);
|
||||
|
||||
FeedlyServiceRoot* existing_root = account<FeedlyServiceRoot>();
|
||||
|
||||
#if defined (FEEDLY_OFFICIAL_SUPPORT)
|
||||
m_details->m_oauth = account<FeedlyServiceRoot>()->network()->oauth();
|
||||
m_details->hookNetwork();
|
||||
#endif
|
||||
|
||||
m_details->m_ui.m_txtUsername->lineEdit()->setText(existing_root->network()->username());
|
||||
m_details->m_ui.m_txtDeveloperAccessToken->lineEdit()->setText(existing_root->network()->developerAccessToken());
|
||||
m_details->m_ui.m_spinLimitMessages->setValue(existing_root->network()->batchSize());
|
||||
}
|
||||
|
||||
void FormEditFeedlyAccount::performTest() {
|
||||
m_details->performTest(m_proxyDetails->proxy());
|
||||
}
|
30
src/librssguard/services/feedly/gui/formeditfeedlyaccount.h
Executable file
30
src/librssguard/services/feedly/gui/formeditfeedlyaccount.h
Executable file
@ -0,0 +1,30 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FORMEDITFEEDLYACCOUNT_H
|
||||
#define FORMEDITFEEDLYACCOUNT_H
|
||||
|
||||
#include "services/abstract/gui/formaccountdetails.h"
|
||||
|
||||
class FeedlyAccountDetails;
|
||||
class FeedlyServiceRoot;
|
||||
|
||||
class FormEditFeedlyAccount : public FormAccountDetails {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormEditFeedlyAccount(QWidget* parent = nullptr);
|
||||
|
||||
protected slots:
|
||||
virtual void apply();
|
||||
|
||||
protected:
|
||||
virtual void setEditableAccount(ServiceRoot* editable_account);
|
||||
|
||||
private slots:
|
||||
void performTest();
|
||||
|
||||
private:
|
||||
FeedlyAccountDetails* m_details;
|
||||
};
|
||||
|
||||
#endif // FORMEDITFEEDLYACCOUNT_H
|
@ -32,7 +32,7 @@ QString GreaderEntryPoint::code() const {
|
||||
|
||||
QString GreaderEntryPoint::description() const {
|
||||
return QObject::tr("Google Reader API is used by many online RSS readers. This is here to support") +
|
||||
QSL(" FreshRSS, Bazqux, TheOldReader.");
|
||||
QSL(" FreshRSS, Bazqux, TheOldReader, Reedah, ...");
|
||||
}
|
||||
|
||||
QString GreaderEntryPoint::author() const {
|
||||
|
Loading…
x
Reference in New Issue
Block a user