Commit 7dc35298 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

FetchJob: deprecate all signals, add a new one

Deprecate all the overloaded signals with many complicated arguments,
which makes connecting to them using the new connect() syntax (and
the old as well) tedious. Instead introduce KIMAP::Message structure
and a new messagesAvailable() signal that has a map of the Message
structures as the only argument. This will make the API much more
comfortable to use.

Eventually the deprecated signals should be removed in order to
simplify and speed up the response parsing code.
parent 232850d2
cmake_minimum_required(VERSION 3.0)
set(PIM_VERSION "5.5.60")
set(PIM_VERSION "5.5.61")
project(KIMAP VERSION ${PIM_VERSION})
......
......@@ -40,6 +40,7 @@ private:
QMap<qint64, KIMAP::MessagePtr> m_messages;
QMap<qint64, KIMAP::MessageParts> m_parts;
QMap<qint64, KIMAP::MessageAttribute> m_attrs;
QMap<qint64, KIMAP::Message> m_msgs;
public Q_SLOTS:
void onHeadersReceived(const QString &/*mailBox*/,
......@@ -78,6 +79,12 @@ public Q_SLOTS:
m_parts.unite(parts);
}
void onMessagesAvailable(const QMap<qint64, KIMAP::Message> &messages)
{
m_signals << QStringLiteral("messagesAvailable");
m_msgs.unite(messages);
}
private Q_SLOTS:
void testFetch_data()
......@@ -194,6 +201,8 @@ private Q_SLOTS:
QMap<qint64, KIMAP::MessageAttribute>,
QMap<qint64, KIMAP::MessageFlags>,
QMap<qint64, KIMAP::MessagePtr>)));
connect(job, &KIMAP::FetchJob::messagesAvailable,
this, &FetchJobTest::onMessagesAvailable);
bool result = job->exec();
QEXPECT_FAIL("connection drop", "Expected failure on connection drop", Continue);
......@@ -203,6 +212,7 @@ private Q_SLOTS:
if (result) {
QVERIFY(m_signals.count() > 0);
QCOMPARE(m_uids.count(), expectedMessageCount);
QCOMPARE(m_msgs.count(), expectedMessageCount);
}
QVERIFY(fakeServer.isAllScenarioDone());
......@@ -215,6 +225,7 @@ private Q_SLOTS:
m_messages.clear();
m_parts.clear();
m_attrs.clear();
m_msgs.clear();
}
void testFetchStructure()
......@@ -248,6 +259,8 @@ private Q_SLOTS:
QMap<qint64, qint64>,
QMap<qint64, KIMAP::MessageAttribute>,
QMap<qint64, KIMAP::MessagePtr>)));
connect(job, &KIMAP::FetchJob::messagesAvailable,
this, &FetchJobTest::onMessagesAvailable);
bool result = job->exec();
QVERIFY(result);
......@@ -258,6 +271,13 @@ private Q_SLOTS:
QCOMPARE(m_messages[2]->contents().size(), 2);
QCOMPARE(m_messages[2]->contents()[0]->contents().size(), 2);
QCOMPARE(m_messages[2]->attachments().at(0)->contentDisposition()->filename(), QStringLiteral("photo.jpg"));
QCOMPARE(m_msgs.count(), 2);
QCOMPARE(m_msgs[1].message->attachments().count(), 0);
QCOMPARE(m_msgs[2].message->attachments().count(), 1);
QCOMPARE(m_msgs[2].message->contents().size(), 2);
QCOMPARE(m_msgs[2].message->contents()[0]->contents().size(), 2);
QCOMPARE(m_msgs[2].message->attachments().at(0)->contentDisposition()->filename(),
QStringLiteral("photo.jpg"));
fakeServer.quit();
......@@ -268,6 +288,7 @@ private Q_SLOTS:
m_messages.clear();
m_parts.clear();
m_attrs.clear();
m_msgs.clear();
}
void testFetchParts()
......@@ -314,7 +335,8 @@ private Q_SLOTS:
QMap<qint64, qint64>,
QMap<qint64, KIMAP::MessageAttribute>,
QMap<qint64, KIMAP::MessageParts>)));
connect(job, &KIMAP::FetchJob::messagesAvailable,
this, &FetchJobTest::onMessagesAvailable);
bool result = job->exec();
QVERIFY(result);
......@@ -322,18 +344,23 @@ private Q_SLOTS:
QCOMPARE(m_uids.count(), 1);
QCOMPARE(m_parts.count(), 1);
QCOMPARE(m_attrs.count(), 0);
QCOMPARE(m_msgs.count(), 1);
// Check that we received the message header
QCOMPARE(m_messages[2]->messageID()->identifier(), QByteArray("1234@example.com"));
QCOMPARE(m_msgs[2].message->messageID()->identifier(), QByteArray("1234@example.com"));
// Check that we recieved the flags
QMap<qint64, KIMAP::MessageFlags> expectedFlags;
expectedFlags.insert(2, KIMAP::MessageFlags() << "\\Seen");
QCOMPARE(m_flags, expectedFlags);
QCOMPARE(m_msgs[2].flags, expectedFlags[2]);
// Check that we didn't received the full message body, since we only requested a specific part
QCOMPARE(m_messages[2]->decodedText().length(), 0);
QCOMPARE(m_messages[2]->attachments().count(), 0);
QCOMPARE(m_msgs[2].message->decodedText().length(), 0);
QCOMPARE(m_msgs[2].message->attachments().count(), 0);
// Check that we received the part we requested
QByteArray partId = m_parts[2].keys().first();
......@@ -341,6 +368,10 @@ private Q_SLOTS:
QCOMPARE(partId, QByteArray("1.1.1"));
QCOMPARE(text, QStringLiteral("Hi Jane, nice to meet you!")) ;
QCOMPARE(m_msgs[2].parts.keys().first(), QByteArray("1.1.1"));
QCOMPARE(m_msgs[2].parts.value(partId)->decodedText(true, true),
QStringLiteral("Hi Jane, nice to meet you!"));
fakeServer.quit();
m_signals.clear();
......@@ -350,6 +381,7 @@ private Q_SLOTS:
m_messages.clear();
m_parts.clear();
m_attrs.clear();
m_msgs.clear();
}
};
......
......@@ -51,10 +51,12 @@ public:
void emitPendings()
{
if (pendingUids.isEmpty()) {
if (pendingMsgs.isEmpty()) {
return;
}
Q_EMIT q->messagesAvailable(pendingMsgs);
if (!pendingParts.isEmpty()) {
emit q->partsReceived(selectedMailBox,
pendingUids, pendingParts);
......@@ -85,6 +87,7 @@ public:
pendingSizes.clear();
pendingFlags.clear();
pendingAttributes.clear();
pendingMsgs.clear();
}
FetchJob *const q;
......@@ -102,6 +105,7 @@ public:
QMap<qint64, MessageAttribute> pendingAttributes;
QMap<qint64, qint64> pendingSizes;
QMap<qint64, qint64> pendingUids;
QMap<qint64, Message> pendingMsgs;
};
}
......@@ -175,6 +179,12 @@ void FetchJob::setGmailExtensionsEnabled(bool enabled)
d->gmailEnabled = enabled;
}
QString FetchJob::mailBox() const
{
Q_D(const FetchJob);
return d->selectedMailBox;
}
void FetchJob::doStart()
{
Q_D(FetchJob);
......@@ -270,6 +280,7 @@ void FetchJob::handleResponse(const Response &response)
qint64 id = response.content[1].toString().toLongLong();
QList<QByteArray> content = response.content[3].toList();
Message msg;
MessagePtr message(new KMime::Message);
bool shouldParseMessage = false;
MessageParts parts;
......@@ -284,10 +295,11 @@ void FetchJob::handleResponse(const Response &response)
break;
}
if (str == "UID") {
d->pendingUids[id] = it->toLongLong();
d->pendingUids[id] = msg.uid = it->toLongLong();
} else if (str == "RFC822.SIZE") {
d->pendingSizes[id] = it->toLongLong();
d->pendingSizes[id] = msg.size = it->toLongLong();
} else if (str == "INTERNALDATE") {
message->date()->setDateTime(QDateTime::fromString(QLatin1String(*it), Qt::RFC2822Date));
} else if (str == "FLAGS") {
......@@ -295,21 +307,28 @@ void FetchJob::handleResponse(const Response &response)
QByteArray str = *it;
str.chop(1);
str.remove(0, 1);
d->pendingFlags[id] = str.split(' ');
const auto flags = str.split(' ');
d->pendingFlags[id] = flags;
msg.flags = flags;
} else {
d->pendingFlags[id] << *it;
msg.flags << *it;
}
} else if (str == "X-GM-LABELS") {
d->pendingAttributes.insert(id, { "X-GM-LABELS", *it });
msg.attributes.insert("X-GM-LABELS", *it);
} else if (str == "X-GM-THRID") {
d->pendingAttributes.insert(id, { "X-GM-THRID", *it });
msg.attributes.insert("X-GM-THRID", *it);
} else if (str == "X-GM-MSGID") {
d->pendingAttributes.insert(id, { "X-GM-MSGID", *it });
msg.attributes.insert("X-GM-MSGID", *it);
} else if (str == "BODYSTRUCTURE") {
int pos = 0;
d->parseBodyStructure(*it, pos, message.data());
message->assemble();
d->pendingMessages[id] = message;
msg.message = message;
} else if (str.startsWith("BODY[")) { //krazy:exclude=strings
if (!str.endsWith(']')) { // BODY[ ... ] might have been split, skip until we find the ]
while (!(*it).endsWith(']')) {
......@@ -328,6 +347,7 @@ void FetchJob::handleResponse(const Response &response)
parts[partId]->setHead(*it);
parts[partId]->parse();
d->pendingParts[id] = parts;
msg.parts = parts;
} else {
message->setHead(*it);
shouldParseMessage = true;
......@@ -338,6 +358,7 @@ void FetchJob::handleResponse(const Response &response)
shouldParseMessage = true;
d->pendingMessages[id] = message;
msg.message = message;
} else {
QByteArray partId = str.mid(5, str.size() - 6);
if (!parts.contains(partId)) {
......@@ -347,6 +368,7 @@ void FetchJob::handleResponse(const Response &response)
parts[partId]->parse();
d->pendingParts[id] = parts;
msg.parts = parts;
}
}
}
......@@ -363,7 +385,10 @@ void FetchJob::handleResponse(const Response &response)
d->scope.mode == FetchScope::HeaderAndContent ||
d->scope.mode == FetchScope::FullHeaders) {
d->pendingMessages[id] = message;
msg.message = message;
}
d->pendingMsgs[id] = msg;
}
}
}
......
......@@ -43,6 +43,17 @@ typedef QList<QByteArray> MessageFlags;
typedef QPair<QByteArray, QVariant> MessageAttribute;
struct Message
{
qint64 uid;
qint64 size;
MessageFlags flags;
QMap<QByteArray, QVariant> attributes;
MessageParts parts;
MessagePtr message;
};
/**
* Fetch message data from the server
*
......@@ -245,6 +256,16 @@ public:
*/
bool setGmailExtensionsEnabled() const;
/**
* Returns the name of the mailbox the fetch job is executed on.
*
* Can only be accessed after the job is actually started, before that
* returns an empty string.
*
* @since 5.6
*/
QString mailBox() const;
Q_SIGNALS:
/**
* Provides header and message results.
......@@ -275,7 +296,10 @@ Q_SIGNALS:
* @param messages a map from message sequence numbers to message contents (including
* headers); populated if the scope is FetchScope::Full,
* FetchScope::Headers or FetchScope::Structure
*
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void headersReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, qint64> &sizes,
......@@ -306,7 +330,9 @@ Q_SIGNALS:
*
* @overload
* @since 4.14
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void headersReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, qint64> &sizes,
......@@ -331,7 +357,10 @@ Q_SIGNALS:
* executed on
* @param uids a map from message sequence numbers to message UIDs
* @param messages a map from message sequence numbers to message contents
*
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void messagesReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, KIMAP::MessagePtr> &messages);
......@@ -350,7 +379,10 @@ Q_SIGNALS:
*
* @overload
* @since 4.14
*
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void messagesReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, KIMAP::MessageAttribute > &attrs,
......@@ -371,7 +403,10 @@ Q_SIGNALS:
* executed on
* @param uids a map from message sequence numbers to message UIDs
* @param parts a map from message sequence numbers to message part collections
*
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void partsReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, KIMAP::MessageParts> &parts);
......@@ -389,12 +424,28 @@ Q_SIGNALS:
*
* @overload
* @since 4.14
*
* @deprecated Use messagesAvailable() instead.
*/
KIMAP_DEPRECATED
void partsReceived(const QString &mailBox,
const QMap<qint64, qint64> &uids,
const QMap<qint64, KIMAP::MessageAttribute > &attrs,
const QMap<qint64, KIMAP::MessageParts> &parts);
/**
* Provides received messages.
*
* This signal is emitted when some data are received. The signal can be
* emitted multiple times as the messages are being received.
*
* @param messages A map from message sequence number to message. Not all
* fields may be populated, depending on the fetch scope.
*
* @since 5.6
*/
void messagesAvailable(const QMap<qint64, KIMAP::Message> &messages);
protected:
void doStart() override;
void handleResponse(const Response &response) override;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment