Work on loading of gmail messages.

This commit is contained in:
Martin Rotter 2017-10-19 10:43:34 +02:00
parent 5d51b8d28d
commit b072d41d84
8 changed files with 82 additions and 27 deletions

View file

@ -136,7 +136,13 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
// Moreover, sort everything alphabetically or // Moreover, sort everything alphabetically or
// by item counts, depending on the sort column. // by item counts, depending on the sort column.
if (left_item->kind() == right_item->kind()) { if (left_item->keepOnTop()) {
return sortOrder() == Qt::AscendingOrder;
}
else if (right_item->keepOnTop()) {
return sortOrder() == Qt::DescendingOrder;
}
else if (left_item->kind() == right_item->kind()) {
// Both items are feeds or both items are categories. // Both items are feeds or both items are categories.
if (left.column() == FDS_MODEL_COUNTS_INDEX) { if (left.column() == FDS_MODEL_COUNTS_INDEX) {
// User wants to sort according to counts. // User wants to sort according to counts.

View file

@ -13,7 +13,7 @@
RootItem::RootItem(RootItem* parent_item) RootItem::RootItem(RootItem* parent_item)
: QObject(nullptr), m_kind(RootItemKind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QSL("")), : QObject(nullptr), m_kind(RootItemKind::Root), m_id(NO_PARENT_CATEGORY), m_customId(QSL("")),
m_title(QString()), m_description(QString()), m_icon(QIcon()), m_creationDate(QDateTime()), m_title(QString()), m_description(QString()), m_icon(QIcon()), m_creationDate(QDateTime()),
m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {} m_keepOnTop(false), m_childItems(QList<RootItem*>()), m_parentItem(parent_item) {}
RootItem::RootItem(const RootItem& other) : RootItem(nullptr) { RootItem::RootItem(const RootItem& other) : RootItem(nullptr) {
setTitle(other.title()); setTitle(other.title());
@ -438,6 +438,14 @@ ServiceRoot* RootItem::toServiceRoot() const {
return static_cast<ServiceRoot*>(const_cast<RootItem*>(this)); return static_cast<ServiceRoot*>(const_cast<RootItem*>(this));
} }
bool RootItem::keepOnTop() const {
return m_keepOnTop;
}
void RootItem::setKeepOnTop(bool keep_on_top) {
m_keepOnTop = keep_on_top;
}
int RootItem::countOfUnreadMessages() const { int RootItem::countOfUnreadMessages() const {
int total_count = 0; int total_count = 0;

View file

@ -54,6 +54,7 @@ class RootItem : public QObject {
explicit RootItem(const RootItem& other); explicit RootItem(const RootItem& other);
virtual ~RootItem(); virtual ~RootItem();
// Determines if this item should be kept always in the beginning of feeds list.
virtual QString hashCode() const; virtual QString hashCode() const;
virtual QString additionalTooltip() const; virtual QString additionalTooltip() const;
@ -202,6 +203,9 @@ class RootItem : public QObject {
Feed* toFeed() const; Feed* toFeed() const;
ServiceRoot* toServiceRoot() const; ServiceRoot* toServiceRoot() const;
bool keepOnTop() const;
void setKeepOnTop(bool keep_on_top);
private: private:
RootItemKind::Kind m_kind; RootItemKind::Kind m_kind;
int m_id; int m_id;
@ -210,6 +214,7 @@ class RootItem : public QObject {
QString m_description; QString m_description;
QIcon m_icon; QIcon m_icon;
QDateTime m_creationDate; QDateTime m_creationDate;
bool m_keepOnTop;
QList<RootItem*> m_childItems; QList<RootItem*> m_childItems;
RootItem* m_parentItem; RootItem* m_parentItem;

View file

@ -8,6 +8,7 @@
#define GMAIL_OAUTH_SCOPE "https://mail.google.com/" #define GMAIL_OAUTH_SCOPE "https://mail.google.com/"
#define GMAIL_API_LABELS_LIST "https://www.googleapis.com/gmail/v1/users/me/labels" #define GMAIL_API_LABELS_LIST "https://www.googleapis.com/gmail/v1/users/me/labels"
#define GMAIL_API_MSGS_LIST "https://www.googleapis.com/gmail/v1/users/me/messages"
#define GMAIL_DEFAULT_BATCH_SIZE 100 #define GMAIL_DEFAULT_BATCH_SIZE 100
#define GMAIL_MAX_BATCH_SIZE 999 #define GMAIL_MAX_BATCH_SIZE 999

View file

@ -23,15 +23,14 @@ GmailServiceRoot* GmailFeed::serviceRoot() const {
QList<Message> GmailFeed::obtainNewMessages(bool* error_during_obtaining) { QList<Message> GmailFeed::obtainNewMessages(bool* error_during_obtaining) {
Feed::Status error; Feed::Status error;
QList<Message> messages = serviceRoot()->network()->messages(customId(), error);
// TODO: dodělat setStatus(error);
QList<Message> messages;/* = serviceRoot()->network()->messages(customId(), error);
setStatus(error); if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError ||
error == Feed::Status::ParsingError) {
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) { *error_during_obtaining = true;
* error_during_obtaining = true; }
}*/
return messages; return messages;
} }

View file

@ -48,7 +48,11 @@ void GmailServiceRoot::updateTitle() {
} }
void GmailServiceRoot::loadFromDatabase() { void GmailServiceRoot::loadFromDatabase() {
appendChild(new GmailFeed(tr("Inbox"), QSL("INBOX"), qApp->icons()->fromTheme(QSL("mail-inbox")), this)); GmailFeed* inbox = new GmailFeed(tr("Inbox"), QSL("INBOX"), qApp->icons()->fromTheme(QSL("mail-inbox")), this);
inbox->setKeepOnTop(true);
appendChild(inbox);
appendChild(new GmailFeed(tr("Sent"), QSL("SENT"), qApp->icons()->fromTheme(QSL("mail-sent")), this)); appendChild(new GmailFeed(tr("Sent"), QSL("SENT"), qApp->icons()->fromTheme(QSL("mail-sent")), this));
appendChild(new GmailFeed(tr("Drafts"), QSL("DRAFT"), qApp->icons()->fromTheme(QSL("gtk-edit")), this)); appendChild(new GmailFeed(tr("Drafts"), QSL("DRAFT"), qApp->icons()->fromTheme(QSL("gtk-edit")), this));
appendChild(new GmailFeed(tr("Spam"), QSL("SPAM"), qApp->icons()->fromTheme(QSL("mail-mark-junk")), this)); appendChild(new GmailFeed(tr("Spam"), QSL("SPAM"), qApp->icons()->fromTheme(QSL("mail-mark-junk")), this));

View file

@ -101,33 +101,60 @@ void GmailNetworkFactory::setUsername(const QString& username) {
QList<Message> GmailNetworkFactory::messages(const QString& stream_id, Feed::Status& error) { QList<Message> GmailNetworkFactory::messages(const QString& stream_id, Feed::Status& error) {
Downloader downloader; Downloader downloader;
QEventLoop loop; QEventLoop loop;
QString target_url;// TODO: dodělat
// = INOREADER_API_FEED_CONTENTS;
QString bearer = m_oauth2->bearer().toLocal8Bit(); QString bearer = m_oauth2->bearer().toLocal8Bit();
QString next_page_token;
QList<Message> messages;
if (bearer.isEmpty()) { if (bearer.isEmpty()) {
error = Feed::Status::AuthError; error = Feed::Status::AuthError;
return QList<Message>(); return QList<Message>();
} }
target_url += QSL("/") + QUrl::toPercentEncoding(stream_id) + QString("?n=%1").arg(batchSize()); downloader.appendRawHeader(QString(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit());
downloader.appendRawHeader(QString("Authorization").toLocal8Bit(), bearer.toLocal8Bit());
// We need to quit event loop when the download finishes. // We need to quit event loop when the download finishes.
connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit);
downloader.manipulateData(target_url, QNetworkAccessManager::Operation::GetOperation); QString target_url;
loop.exec();
if (downloader.lastOutputError() != QNetworkReply::NetworkError::NoError) { do {
error = Feed::Status::NetworkError; target_url = GMAIL_API_MSGS_LIST;
return QList<Message>(); target_url += QString("?labelIds=%1").arg(stream_id);
}
else {
QString messages_data = downloader.lastOutputData();
error = Feed::Status::Normal; if (batchSize() > 0) {
return decodeMessages(messages_data, stream_id); target_url += QString("&maxResults=%1").arg(batchSize());
} }
if (!next_page_token.isEmpty()) {
target_url += QString("&pageToken=%1").arg(next_page_token);
}
downloader.manipulateData(target_url, QNetworkAccessManager::Operation::GetOperation);
loop.exec();
if (downloader.lastOutputError() == QNetworkReply::NetworkError::NoError) {
// We parse this chunk.
QString messages_data = downloader.lastOutputData();
QList<Message> more_messages = decodeLiteMessages(messages_data, stream_id);
// Now, we via batch HTTP request obtain full data for each message.
bool obtained = obtainAndDecodeFullMessages(more_messages);
if (obtained) {
messages.append(more_messages);
error = Feed::Status::NetworkError;
return messages;
}
}
else {
error = Feed::Status::NetworkError;
return messages;
}
} while (!next_page_token.isEmpty());
error = Feed::Status::Normal;
return messages;
} }
void GmailNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids, bool async) { void GmailNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const QStringList& custom_ids, bool async) {
@ -292,7 +319,11 @@ void GmailNetworkFactory::onAuthFailed() {
}); });
} }
QList<Message> GmailNetworkFactory::decodeMessages(const QString& messages_json_data, const QString& stream_id) { bool GmailNetworkFactory::obtainAndDecodeFullMessages(const QList<Message>& lite_messages) {
return false;
}
QList<Message> GmailNetworkFactory::decodeLiteMessages(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

@ -47,7 +47,8 @@ class GmailNetworkFactory : public QObject {
void onAuthFailed(); void onAuthFailed();
private: private:
QList<Message> decodeMessages(const QString& messages_json_data, const QString& stream_id); bool obtainAndDecodeFullMessages(const QList<Message>& lite_messages);
QList<Message> decodeLiteMessages(const QString& messages_json_data, const QString& stream_id);
//RootItem* decodeFeedCategoriesData(const QString& categories); //RootItem* decodeFeedCategoriesData(const QString& categories);