Refactoring of tooltips.

This commit is contained in:
Martin Rotter 2017-10-05 11:10:16 +02:00
parent ab4bb279b7
commit 25c8725029
20 changed files with 162 additions and 124 deletions

View File

@ -57,7 +57,6 @@
#include <QProgressBar> #include <QProgressBar>
#include <QSplitter> #include <QSplitter>
#include <QStatusBar> #include <QStatusBar>
#include <QThread>
#include <QToolBar> #include <QToolBar>
#include <QToolButton> #include <QToolButton>
#include <QVBoxLayout> #include <QVBoxLayout>

View File

@ -108,9 +108,6 @@ int main(int argc, char* argv[]) {
Application::setOrganizationDomain(APP_URL); Application::setOrganizationDomain(APP_URL);
Application::setWindowIcon(QIcon(APP_ICON_PATH)); Application::setWindowIcon(QIcon(APP_ICON_PATH));
// Load activated accounts.
qApp->feedReader()->feedsModel()->loadActivatedServiceAccounts();
// Setup single-instance behavior. // Setup single-instance behavior.
QObject::connect(&application, &Application::messageReceived, &application, &Application::processExecutionMessage); QObject::connect(&application, &Application::messageReceived, &application, &Application::processExecutionMessage);
qDebug().nospace() << "Creating main application form in thread: \'" << QThread::currentThreadId() << "\'."; qDebug().nospace() << "Creating main application form in thread: \'" << QThread::currentThreadId() << "\'.";
@ -139,6 +136,9 @@ int main(int argc, char* argv[]) {
qApp->showTrayIcon(); qApp->showTrayIcon();
} }
// Load activated accounts.
qApp->feedReader()->feedsModel()->loadActivatedServiceAccounts();
if (qApp->isFirstRun() || qApp->isFirstRun(APP_VERSION)) { if (qApp->isFirstRun() || qApp->isFirstRun(APP_VERSION)) {
qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n" qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n"
"version by clicking this popup notification.").arg(APP_LONG_NAME), "version by clicking this popup notification.").arg(APP_LONG_NAME),

View File

@ -69,12 +69,26 @@ OAuth2Service::OAuth2Service(QString authUrl, QString tokenUrl, QString clientId
} }
QString OAuth2Service::bearer() { QString OAuth2Service::bearer() {
if (login()) { if (!isFullyLoggedIn()) {
return QString("Bearer %1").arg(m_accessToken); qApp->showGuiMessage(tr("Inoreader: you have to login first"),
} tr("Click here to login."),
else { QSystemTrayIcon::Critical,
nullptr, false,
[this]() {
login();
});
return QString(); return QString();
} }
else {
return QString("Bearer %1").arg(m_accessToken);
}
}
bool OAuth2Service::isFullyLoggedIn() const {
bool is_expiration_valid = m_tokensExpireIn > QDateTime::currentDateTime();
bool do_tokens_exist = !m_refreshToken.isEmpty() && !m_accessToken.isEmpty();
return is_expiration_valid && do_tokens_exist;
} }
void OAuth2Service::setOAuthTokenGrantType(QString grant_type) { void OAuth2Service::setOAuthTokenGrantType(QString grant_type) {
@ -124,15 +138,15 @@ void OAuth2Service::refreshAccessToken(QString refresh_token) {
.arg(refresh_token) .arg(refresh_token)
.arg("refresh_token"); .arg("refresh_token");
qApp->showGuiMessage(tr("Logging in via OAuth 2.0..."),
tr("Refreshing login tokens for '%1'...").arg(m_tokenUrl.toString()),
QSystemTrayIcon::MessageIcon::Information);
m_networkManager.post(networkRequest, content.toUtf8()); m_networkManager.post(networkRequest, content.toUtf8());
} }
void OAuth2Service::cleanTokens() { void OAuth2Service::tokenRequestFinished(QNetworkReply* network_reply) {
m_refreshToken = m_accessToken = QString(); QJsonDocument jsonDocument = QJsonDocument::fromJson(network_reply->readAll());
}
void OAuth2Service::tokenRequestFinished(QNetworkReply* networkReply) {
QJsonDocument jsonDocument = QJsonDocument::fromJson(networkReply->readAll());
QJsonObject rootObject = jsonDocument.object(); QJsonObject rootObject = jsonDocument.object();
qDebug() << "Token response:"; qDebug() << "Token response:";
@ -142,8 +156,7 @@ void OAuth2Service::tokenRequestFinished(QNetworkReply* networkReply) {
QString error = rootObject.value("error").toString(); QString error = rootObject.value("error").toString();
QString error_description = rootObject.value("error_description").toString(); QString error_description = rootObject.value("error_description").toString();
cleanTokens(); logout();
login();
emit tokensRetrieveError(error, error_description); emit tokensRetrieveError(error, error_description);
} }
@ -160,7 +173,7 @@ void OAuth2Service::tokenRequestFinished(QNetworkReply* networkReply) {
emit tokensReceived(m_accessToken, m_refreshToken, rootObject.value("expires_in").toInt()); emit tokensReceived(m_accessToken, m_refreshToken, rootObject.value("expires_in").toInt());
} }
networkReply->deleteLater(); network_reply->deleteLater();
} }
QString OAuth2Service::accessToken() const { QString OAuth2Service::accessToken() const {
@ -248,8 +261,13 @@ void OAuth2Service::retrieveAuthCode() {
connect(&login_page, &OAuthLogin::authGranted, this, &OAuth2Service::authCodeObtained); connect(&login_page, &OAuthLogin::authGranted, this, &OAuth2Service::authCodeObtained);
connect(&login_page, &OAuthLogin::authRejected, [this]() { connect(&login_page, &OAuthLogin::authRejected, [this]() {
cleanTokens(); logout();
emit authFailed(); emit authFailed();
}); });
qApp->showGuiMessage(tr("Logging in via OAuth 2.0..."),
tr("Requesting access authorization for '%1'...").arg(m_authUrl),
QSystemTrayIcon::MessageIcon::Information);
login_page.login(auth_url, m_redirectUrl); login_page.login(auth_url, m_redirectUrl);
} }

View File

@ -52,7 +52,13 @@ class OAuth2Service : public QObject {
explicit OAuth2Service(QString authUrl, QString tokenUrl, QString clientId, explicit OAuth2Service(QString authUrl, QString tokenUrl, QString clientId,
QString clientSecret, QString scope, QObject* parent = 0); QString clientSecret, QString scope, QObject* parent = 0);
// Returns bearer HTTP header value.
// NOTE: Only call this if isFullyLoggedIn()
// returns true. If isFullyLoggedIn() returns
// false, then you must call login() on
// main GUI thread.
QString bearer(); QString bearer();
bool isFullyLoggedIn() const;
void setOAuthTokenGrantType(QString grant_type); void setOAuthTokenGrantType(QString grant_type);
QString oAuthTokenGrantType(); QString oAuthTokenGrantType();
@ -95,12 +101,14 @@ class OAuth2Service : public QObject {
// access token is made. // access token is made.
// Returns true, if user is already logged in (final state). // Returns true, if user is already logged in (final state).
// Returns false, if user is NOT logged in (asynchronous flow). // Returns false, if user is NOT logged in (asynchronous flow).
//
// NOTE: This can be called ONLY on main GUI thread,
// because widgets may be displayed.
bool login(); bool login();
void logout(); void logout();
private slots: private slots:
void cleanTokens(); void tokenRequestFinished(QNetworkReply* network_reply);
void tokenRequestFinished(QNetworkReply* networkReply);
private: private:
QDateTime m_tokensExpireIn; QDateTime m_tokensExpireIn;

View File

@ -81,19 +81,6 @@ QList<Message> Feed::undeletedMessages() const {
QVariant Feed::data(int column, int role) const { QVariant Feed::data(int column, int role) const {
switch (role) { switch (role) {
case Qt::ToolTipRole:
if (column == FDS_MODEL_TITLE_INDEX) {
//: Tooltip for feed.
return tr("%1"
"%2\n\n"
"Auto-update status: %3").arg(title(),
description().isEmpty() ? QString() : QString('\n') + description(),
getAutoUpdateStatusDescription());
}
else {
return RootItem::data(column, role);
}
case Qt::ForegroundRole: case Qt::ForegroundRole:
switch (status()) { switch (status()) {
case NewMessages: case NewMessages:
@ -308,3 +295,27 @@ QString Feed::getAutoUpdateStatusDescription() const {
return auto_update_string; return auto_update_string;
} }
QString Feed::getStatusDescription() const {
switch (m_status) {
case Status::Normal:
return tr("no errors");
case Status::NewMessages:
return tr("has new messages");
case Status::AuthError:
return tr("authentication error");
case Status::NetworkError:
return tr("network error");
default:
return tr("unspecified error");
}
}
QString Feed::additionalTooltip() const {
return tr("Auto-update status: %1\n"
"Status: %2").arg(getAutoUpdateStatusDescription(), getStatusDescription());
}

View File

@ -46,8 +46,9 @@ class Feed : public RootItem, public QRunnable {
Normal = 0, Normal = 0,
NewMessages = 1, NewMessages = 1,
NetworkError = 2, NetworkError = 2,
ParsingError = 3, AuthError = 3,
OtherError = 4 ParsingError = 4,
OtherError = 5
}; };
// Constructors. // Constructors.
@ -58,6 +59,8 @@ class Feed : public RootItem, public QRunnable {
QList<Message> undeletedMessages() const; QList<Message> undeletedMessages() const;
QString additionalTooltip() const;
int countOfAllMessages() const; int countOfAllMessages() const;
int countOfUnreadMessages() const; int countOfUnreadMessages() const;
@ -93,6 +96,7 @@ class Feed : public RootItem, public QRunnable {
protected: protected:
QString getAutoUpdateStatusDescription() const; QString getAutoUpdateStatusDescription() const;
QString getStatusDescription() const;
signals: signals:
void messagesObtained(QList<Message> messages, bool error_during_obtaining); void messagesObtained(QList<Message> messages, bool error_during_obtaining);

View File

@ -39,6 +39,10 @@ RecycleBin::RecycleBin(RootItem* parent_item) : RootItem(parent_item), m_totalCo
RecycleBin::~RecycleBin() {} RecycleBin::~RecycleBin() {}
QString RecycleBin::additionalTooltip() const {
return tr("%n deleted message(s).", 0, countOfAllMessages());
}
int RecycleBin::countOfUnreadMessages() const { int RecycleBin::countOfUnreadMessages() const {
return m_unreadCount; return m_unreadCount;
} }
@ -60,16 +64,6 @@ void RecycleBin::updateCounts(bool update_total_count) {
} }
} }
QVariant RecycleBin::data(int column, int role) const {
switch (role) {
case Qt::ToolTipRole:
return tr("Recycle bin\n\n%1").arg(tr("%n deleted message(s).", 0, countOfAllMessages()));
default:
return RootItem::data(column, role);
}
}
QList<QAction*> RecycleBin::contextMenu() { QList<QAction*> RecycleBin::contextMenu() {
if (m_contextMenu.isEmpty()) { if (m_contextMenu.isEmpty()) {
QAction* restore_action = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")), QAction* restore_action = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")),

View File

@ -28,7 +28,7 @@ class RecycleBin : public RootItem {
explicit RecycleBin(RootItem* parent_item = nullptr); explicit RecycleBin(RootItem* parent_item = nullptr);
virtual ~RecycleBin(); virtual ~RecycleBin();
QVariant data(int column, int role) const; QString additionalTooltip() const;
QList<QAction*> contextMenu(); QList<QAction*> contextMenu();
QList<Message> undeletedMessages() const; QList<Message> undeletedMessages() const;

View File

@ -58,6 +58,10 @@ QString RootItem::hashCode() const {
QString::number(id()); QString::number(id());
} }
QString RootItem::additionalTooltip() const {
return QString();
}
QList<QAction*> RootItem::contextMenu() { QList<QAction*> RootItem::contextMenu() {
return QList<QAction*>(); return QList<QAction*>();
} }
@ -142,7 +146,13 @@ QVariant RootItem::data(int column, int role) const {
QString tool_tip = m_title; QString tool_tip = m_title;
if (!m_description.isEmpty()) { if (!m_description.isEmpty()) {
tool_tip += QL1S("\n\n") + m_description; tool_tip += QL1S("\n") + m_description;
}
QString extra_tooltip = additionalTooltip();
if (!extra_tooltip.isEmpty()) {
tool_tip += QL1S("\n\n") + extra_tooltip;
} }
return tool_tip; return tool_tip;

View File

@ -71,6 +71,7 @@ class RootItem : public QObject {
virtual ~RootItem(); virtual ~RootItem();
virtual QString hashCode() const; virtual QString hashCode() const;
virtual QString additionalTooltip() const;
// Returns list of specific actions which can be done with the item. // Returns list of specific actions which can be done with the item.
// Do not include general actions here like actions: Mark as read, Update, ... // Do not include general actions here like actions: Mark as read, Update, ...

View File

@ -32,7 +32,14 @@ InoreaderServiceRoot* InoreaderFeed::serviceRoot() const {
} }
QList<Message> InoreaderFeed::obtainNewMessages(bool* error_during_obtaining) { QList<Message> InoreaderFeed::obtainNewMessages(bool* error_during_obtaining) {
QList<Message> messages = serviceRoot()->network()->messages(customId(), error_during_obtaining); Feed::Status error;
QList<Message> messages = serviceRoot()->network()->messages(customId(), error);
setStatus(error);
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
*error_during_obtaining = true;
}
return messages; return messages;
} }

View File

@ -120,9 +120,10 @@ void InoreaderServiceRoot::start(bool freshly_activated) {
Q_UNUSED(freshly_activated) Q_UNUSED(freshly_activated)
loadFromDatabase(); loadFromDatabase();
m_network->oauth()->login();
loadCacheFromFile(accountId()); loadCacheFromFile(accountId());
m_network->oauth()->login();
if (childCount() <= 1) { if (childCount() <= 1) {
syncIn(); syncIn();
} }

View File

@ -66,17 +66,18 @@ void InoreaderNetworkFactory::setBatchSize(int batch_size) {
} }
void InoreaderNetworkFactory::initializeOauth() { void InoreaderNetworkFactory::initializeOauth() {
connect(m_oauth2, &OAuth2Service::tokensRetrieveError, [](QString error, QString error_description) { connect(m_oauth2, &OAuth2Service::tokensRetrieveError, this, &InoreaderNetworkFactory::onTokensError);
Q_UNUSED(error) connect(m_oauth2, &OAuth2Service::authFailed, this, &InoreaderNetworkFactory::onAuthFailed);
qApp->showGuiMessage("Authentication error - Inoreader", error_description, QSystemTrayIcon::Critical);
});
connect(m_oauth2, &OAuth2Service::tokensReceived, [this](QString access_token, QString refresh_token, int expires_in) { connect(m_oauth2, &OAuth2Service::tokensReceived, [this](QString access_token, QString refresh_token, int expires_in) {
Q_UNUSED(expires_in) Q_UNUSED(expires_in)
if (m_service != nullptr && !access_token.isEmpty() && !refresh_token.isEmpty()) { if (m_service != nullptr && !access_token.isEmpty() && !refresh_token.isEmpty()) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
DatabaseQueries::storeNewInoreaderTokens(database, refresh_token, m_service->accountId()); DatabaseQueries::storeNewInoreaderTokens(database, refresh_token, m_service->accountId());
qApp->showGuiMessage(tr("Logged in successfully"),
tr("Your login to Inoreader was authorized."),
QSystemTrayIcon::MessageIcon::Information);
} }
}); });
} }
@ -121,13 +122,14 @@ RootItem* InoreaderNetworkFactory::feedsCategories(bool obtain_icons) {
return decodeFeedCategoriesData(category_data, feed_data, obtain_icons); return decodeFeedCategoriesData(category_data, feed_data, obtain_icons);
} }
QList<Message> InoreaderNetworkFactory::messages(const QString& stream_id, bool* is_error) { QList<Message> InoreaderNetworkFactory::messages(const QString& stream_id, Feed::Status& error) {
Downloader downloader; Downloader downloader;
QEventLoop loop; QEventLoop loop;
QString target_url = INOREADER_API_FEED_CONTENTS; QString target_url = INOREADER_API_FEED_CONTENTS;
QString bearer = m_oauth2->bearer().toLocal8Bit(); QString bearer = m_oauth2->bearer().toLocal8Bit();
if (bearer.isEmpty()) { if (bearer.isEmpty()) {
error == Feed::Status::AuthError;
return QList<Message>(); return QList<Message>();
} }
@ -140,12 +142,13 @@ QList<Message> InoreaderNetworkFactory::messages(const QString& stream_id, bool*
loop.exec(); loop.exec();
if (downloader.lastOutputError() != QNetworkReply::NetworkError::NoError) { if (downloader.lastOutputError() != QNetworkReply::NetworkError::NoError) {
*is_error = true; error == Feed::Status::NetworkError;
return QList<Message>(); return QList<Message>();
} }
else { else {
QString messages_data = downloader.lastOutputData(); QString messages_data = downloader.lastOutputData();
error == Feed::Status::Normal;
return decodeMessages(messages_data, stream_id); return decodeMessages(messages_data, stream_id);
} }
} }
@ -204,6 +207,28 @@ void InoreaderNetworkFactory::markMessagesRead(RootItem::ReadStatus status, cons
void InoreaderNetworkFactory::markMessagesStarred(RootItem::Importance importance, const QStringList& custom_ids) {} void InoreaderNetworkFactory::markMessagesStarred(RootItem::Importance importance, const QStringList& custom_ids) {}
void InoreaderNetworkFactory::onTokensError(const QString& error, const QString& error_description) {
Q_UNUSED(error)
qApp->showGuiMessage(tr("Inoreader: authentication error"),
tr("Click this to login again. Error is: '%1'").arg(error_description),
QSystemTrayIcon::Critical,
nullptr, false,
[this]() {
m_oauth2->login();
});
}
void InoreaderNetworkFactory::onAuthFailed() {
qApp->showGuiMessage(tr("Inoreader: authorization denied"),
tr("Click this to login again."),
QSystemTrayIcon::Critical,
nullptr, false,
[this]() {
m_oauth2->login();
});
}
QList<Message> InoreaderNetworkFactory::decodeMessages(const QString& messages_json_data, const QString& stream_id) { QList<Message> InoreaderNetworkFactory::decodeMessages(const QString& messages_json_data, const QString& stream_id) {
QList<Message> messages; QList<Message> messages;
QJsonArray json = QJsonDocument::fromJson(messages_json_data.toUtf8()).object()["items"].toArray(); QJsonArray json = QJsonDocument::fromJson(messages_json_data.toUtf8()).object()["items"].toArray();

View File

@ -23,6 +23,7 @@
#include "core/message.h" #include "core/message.h"
#include "services/abstract/feed.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QNetworkReply> #include <QNetworkReply>
@ -53,10 +54,14 @@ class InoreaderNetworkFactory : public QObject {
// Returned items do not have primary IDs assigned. // Returned items do not have primary IDs assigned.
RootItem* feedsCategories(bool obtain_icons); RootItem* feedsCategories(bool obtain_icons);
QList<Message> messages(const QString& stream_id, bool* is_error); QList<Message> messages(const QString& stream_id, Feed::Status& error);
void markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids); void markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids);
void markMessagesStarred(RootItem::Importance importance, const QStringList& custom_ids); void markMessagesStarred(RootItem::Importance importance, const QStringList& custom_ids);
private slots:
void onTokensError(const QString& error, const QString& error_description);
void onAuthFailed();
private: private:
QList<Message> decodeMessages(const QString& messages_json_data, const QString& stream_id); QList<Message> decodeMessages(const QString& messages_json_data, const QString& stream_id);
RootItem* decodeFeedCategoriesData(const QString& categories, const QString& feeds, bool obtain_icons); RootItem* decodeFeedCategoriesData(const QString& categories, const QString& feeds, bool obtain_icons);

View File

@ -71,6 +71,14 @@ QList<QAction*> StandardFeed::contextMenu() {
return serviceRoot()->getContextMenuForFeed(this); return serviceRoot()->getContextMenuForFeed(this);
} }
QString StandardFeed::additionalTooltip() const {
return Feed::additionalTooltip() + tr("\nNetwork status: %1\n"
"Encoding: %2\n"
"Type: %3").arg(NetworkFactory::networkErrorText(m_networkError),
encoding(),
StandardFeed::typeToString(type()));
}
bool StandardFeed::canBeEdited() const { bool StandardFeed::canBeEdited() const {
return true; return true;
} }
@ -99,31 +107,6 @@ bool StandardFeed::deleteViaGui() {
} }
} }
QVariant StandardFeed::data(int column, int role) const {
switch (role) {
case Qt::ToolTipRole:
if (column == FDS_MODEL_TITLE_INDEX) {
//: Tooltip for feed.
return tr("%1 (%2)"
"%3\n\n"
"Network status: %6\n"
"Encoding: %4\n"
"Auto-update status: %5").arg(title(),
StandardFeed::typeToString(type()),
description().isEmpty() ? QString() : QString('\n') + description(),
encoding(),
getAutoUpdateStatusDescription(),
NetworkFactory::networkErrorText(m_networkError));
}
else {
return Feed::data(column, role);
}
default:
return Feed::data(column, role);
}
}
QString StandardFeed::typeToString(StandardFeed::Type type) { QString StandardFeed::typeToString(StandardFeed::Type type) {
switch (type) { switch (type) {
case Atom10: case Atom10:
@ -452,7 +435,6 @@ QList<Message> StandardFeed::obtainNewMessages(bool* error_during_obtaining) {
return QList<Message>(); return QList<Message>();
} }
else if (status() != NewMessages) { else if (status() != NewMessages) {
setStatus(Normal);
*error_during_obtaining = false; *error_during_obtaining = false;
} }

View File

@ -53,14 +53,14 @@ class StandardFeed : public Feed {
QList<QAction*> contextMenu(); QList<QAction*> contextMenu();
QString additionalTooltip() const;
bool canBeEdited() const; bool canBeEdited() const;
bool canBeDeleted() const; bool canBeDeleted() const;
bool editViaGui(); bool editViaGui();
bool deleteViaGui(); bool deleteViaGui();
QVariant data(int column, int role) const;
// Obtains data related to this feed. // Obtains data related to this feed.
Qt::ItemFlags additionalFlags() const; Qt::ItemFlags additionalFlags() const;
bool performDragDropChange(RootItem* target_item); bool performDragDropChange(RootItem* target_item);

View File

@ -141,21 +141,6 @@ void StandardServiceRoot::addNewFeed(const QString& url) {
qApp->feedUpdateLock()->unlock(); qApp->feedUpdateLock()->unlock();
} }
QVariant StandardServiceRoot::data(int column, int role) const {
switch (role) {
case Qt::ToolTipRole:
if (column == FDS_MODEL_TITLE_INDEX) {
return tr("This is service account for standard RSS/RDF/ATOM feeds.\n\nAccount ID: %1").arg(accountId());
}
else {
return ServiceRoot::data(column, role);
}
default:
return ServiceRoot::data(column, role);
}
}
Qt::ItemFlags StandardServiceRoot::additionalFlags() const { Qt::ItemFlags StandardServiceRoot::additionalFlags() const {
return Qt::ItemIsDropEnabled; return Qt::ItemIsDropEnabled;
} }

View File

@ -48,7 +48,6 @@ class StandardServiceRoot : public ServiceRoot {
bool supportsFeedAdding() const; bool supportsFeedAdding() const;
bool supportsCategoryAdding() const; bool supportsCategoryAdding() const;
QVariant data(int column, int role) const;
Qt::ItemFlags additionalFlags() const; Qt::ItemFlags additionalFlags() const;
// Returns menu to be shown in "Services -> service" menu. // Returns menu to be shown in "Services -> service" menu.

View File

@ -125,28 +125,6 @@ bool TtRssServiceRoot::canBeDeleted() const {
return true; return true;
} }
QVariant TtRssServiceRoot::data(int column, int role) const {
switch (role) {
case Qt::ToolTipRole:
if (column == FDS_MODEL_TITLE_INDEX) {
return tr("Tiny Tiny RSS\n\nAccount ID: %3\nUsername: %1\nServer: %2\n"
"Last error: %4\nLast login on: %5").arg(m_network->username(),
m_network->url(),
QString::number(accountId()),
NetworkFactory::networkErrorText(m_network->lastError()),
m_network->lastLoginTime().isValid() ?
m_network->lastLoginTime().toString(Qt::DefaultLocaleShortDate) :
QSL("-"));
}
else {
return ServiceRoot::data(column, role);
}
default:
return ServiceRoot::data(column, role);
}
}
void TtRssServiceRoot::saveAllCachedData() { void TtRssServiceRoot::saveAllCachedData() {
QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache(); QPair<QMap<RootItem::ReadStatus, QStringList>, QMap<RootItem::Importance, QList<Message>>> msgCache = takeMessageCache();
QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first); QMapIterator<RootItem::ReadStatus, QStringList> i(msgCache.first);
@ -193,6 +171,16 @@ QList<QAction*> TtRssServiceRoot::serviceMenu() {
return m_serviceMenu; return m_serviceMenu;
} }
QString TtRssServiceRoot::additionalTooltip() const {
return tr("Username: %1\nServer: %2\n"
"Last error: %3\nLast login on: %4").arg(m_network->username(),
m_network->url(),
NetworkFactory::networkErrorText(m_network->lastError()),
m_network->lastLoginTime().isValid() ?
m_network->lastLoginTime().toString(Qt::DefaultLocaleShortDate) :
QSL("-"));
}
TtRssNetworkFactory* TtRssServiceRoot::network() const { TtRssNetworkFactory* TtRssServiceRoot::network() const {
return m_network; return m_network;
} }

View File

@ -44,9 +44,10 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
bool deleteViaGui(); bool deleteViaGui();
bool supportsFeedAdding() const; bool supportsFeedAdding() const;
bool supportsCategoryAdding() const; bool supportsCategoryAdding() const;
QVariant data(int column, int role) const;
QList<QAction*> serviceMenu(); QList<QAction*> serviceMenu();
QString additionalTooltip() const;
void saveAllCachedData(); void saveAllCachedData();
// Access to network. // Access to network.