[Telepathy-commits] [telepathy-qt4/master] Move Message implementation to a separate source file, adding real API for things TextChannel needs to poke at
Simon McVittie
simon.mcvittie at collabora.co.uk
Fri Feb 20 10:57:45 PST 2009
In the process, fix Message::Private::textChannel: it was a pointer, but
should clearly have been a QPointer.
---
TelepathyQt4/Client/message.cpp | 551 ++++++++++++++++++++++++++++++++++
TelepathyQt4/Client/message.h | 18 +-
TelepathyQt4/Client/text-channel.cpp | 515 +------------------------------
TelepathyQt4/Client/text-channel.h | 1 -
TelepathyQt4/Makefile.am | 1 +
5 files changed, 585 insertions(+), 501 deletions(-)
create mode 100644 TelepathyQt4/Client/message.cpp
diff --git a/TelepathyQt4/Client/message.cpp b/TelepathyQt4/Client/message.cpp
new file mode 100644
index 0000000..6d0b12c
--- /dev/null
+++ b/TelepathyQt4/Client/message.cpp
@@ -0,0 +1,551 @@
+/* Message object used by text channel client-side proxy
+ *
+ * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <TelepathyQt4/Client/Message>
+#include <TelepathyQt4/Client/ReceivedMessage>
+
+#include <QDateTime>
+#include <QPointer>
+#include <QSet>
+
+#include <TelepathyQt4/Client/TextChannel>
+
+#include "TelepathyQt4/debug-internal.h"
+
+namespace Telepathy
+{
+namespace Client
+{
+
+class Message::Private : public QSharedData
+{
+public:
+ Private(const MessagePartList &parts);
+ ~Private();
+
+ MessagePartList parts;
+
+ // if the Text interface says "non-text" we still only have the text,
+ // because the interface can't tell us anything else...
+ bool forceNonText;
+
+ // for received messages only
+ QPointer<TextChannel> textChannel;
+ QSharedPointer<Contact> sender;
+
+ inline QVariant value(uint index, const char *key) const;
+ inline uint getUIntOrZero(uint index, const char *key) const;
+ inline QString getStringOrEmpty(uint index, const char *key) const;
+ inline bool getBoolean(uint index, const char *key,
+ bool assumeIfAbsent) const;
+ inline uint senderHandle() const;
+ inline uint pendingId() const;
+ void clearSenderHandle();
+};
+
+Message::Private::Private(const MessagePartList &parts)
+ : parts(parts),
+ forceNonText(false),
+ textChannel(0),
+ sender(0)
+{
+}
+
+Message::Private::~Private()
+{
+}
+
+inline QVariant Message::Private::value(uint index, const char *key) const
+{
+ return parts.at(index).value(QLatin1String(key)).variant();
+}
+
+inline QString Message::Private::getStringOrEmpty(uint index, const char *key)
+ const
+{
+ QString s = value(index, key).toString();
+ if (s.isNull()) {
+ s = QString::fromAscii("");
+ }
+ return s;
+}
+
+inline uint Message::Private::getUIntOrZero(uint index, const char *key)
+ const
+{
+ return value(index, key).toUInt();
+}
+
+inline bool Message::Private::getBoolean(uint index, const char *key,
+ bool assumeIfAbsent) const
+{
+ QVariant v = value(index, key);
+ if (v.isValid() && v.type() == QVariant::Bool) {
+ return v.toBool();
+ }
+ return assumeIfAbsent;
+}
+
+inline uint Message::Private::senderHandle() const
+{
+ return getUIntOrZero(0, "message-sender");
+}
+
+inline uint Message::Private::pendingId() const
+{
+ return getUIntOrZero(0, "pending-message-id");
+}
+
+void Message::Private::clearSenderHandle()
+{
+ parts[0].remove(QLatin1String("message-sender"));
+}
+
+/**
+ * \class Message
+ * \ingroup clientchannel
+ * \headerfile TelepathyQt4/Client/text-channel.h <TelepathyQt4/Client/TextChannel>
+ *
+ * Object representing a message. These objects are implicitly shared, like
+ * QString.
+ */
+
+/**
+ * Default constructor, only used internally.
+ */
+Message::Message()
+{
+}
+
+/**
+ * Constructor.
+ *
+ * \param parts The parts of a message as defined by the Telepathy D-Bus
+ * specification. This list must have length at least 1.
+ */
+Message::Message(const MessagePartList &parts)
+ : mPriv(new Private(parts))
+{
+ Q_ASSERT(parts.size() > 0);
+}
+
+/**
+ * Constructor, from the parameters of the old Sent signal.
+ *
+ * \param timestamp The time the message was sent
+ * \param type The message type
+ * \param text The text of the message
+ */
+Message::Message(uint timestamp, uint type, const QString &text)
+ : mPriv(new Private(MessagePartList() << MessagePart() << MessagePart()))
+{
+ mPriv->parts[0].insert(QString::fromAscii("message-sent"),
+ QDBusVariant(static_cast<qlonglong>(timestamp)));
+ mPriv->parts[0].insert(QString::fromAscii("message-type"),
+ QDBusVariant(type));
+
+ mPriv->parts[1].insert(QString::fromAscii("content-type"),
+ QDBusVariant(QString::fromAscii("text/plain")));
+ mPriv->parts[1].insert(QString::fromAscii("content"), QDBusVariant(text));
+}
+
+/**
+ * Copy constructor.
+ */
+Message::Message(const Message &other)
+ : mPriv(other.mPriv)
+{
+}
+
+/**
+ * Assignment operator.
+ */
+Message &Message::operator=(const Message &other)
+{
+ if (this != &other) {
+ mPriv = other.mPriv;
+ }
+
+ return *this;
+}
+
+/**
+ * Equality operator.
+ */
+bool Message::operator==(const Message &other) const
+{
+ return this->mPriv == other.mPriv;
+}
+
+/**
+ * Destructor.
+ */
+Message::~Message()
+{
+}
+
+/**
+ * Return the time the message was sent, or QDateTime() if that time is
+ * unknown.
+ *
+ * \return A timestamp
+ */
+QDateTime Message::sent() const
+{
+ // FIXME: Telepathy supports 64-bit time_t, but Qt only does so on
+ // ILP64 systems (e.g. sparc64, but not x86_64). If QDateTime
+ // gains a fromTimestamp64 method, we should use it instead.
+ uint stamp = mPriv->value(0, "message-sent").toUInt();
+ if (stamp != 0) {
+ return QDateTime::fromTime_t(stamp);
+ } else {
+ return QDateTime();
+ }
+}
+
+/**
+ * Return the type of message this is, or ChannelTextMessageTypeNormal
+ * if the type is not recognised.
+ *
+ * \return The ChannelTextMessageType for this message
+ */
+ChannelTextMessageType Message::messageType() const
+{
+ uint raw = mPriv->value(0, "message-type").toUInt();
+
+ if (raw < static_cast<uint>(NUM_CHANNEL_TEXT_MESSAGE_TYPES)) {
+ return ChannelTextMessageType(raw);
+ } else {
+ return ChannelTextMessageTypeNormal;
+ }
+}
+
+/**
+ * Return whether this message was truncated during delivery.
+ */
+bool Message::isTruncated() const
+{
+ for (int i = 1; i < size(); i++) {
+ if (mPriv->getBoolean(i, "truncated", false)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Return whether this message contains parts not representable as plain
+ * text.
+ *
+ * \return true if this message cannot completely be represented as plain text
+ */
+bool Message::hasNonTextContent() const
+{
+ if (mPriv->forceNonText || size() <= 1 || isSpecificToDBusInterface()) {
+ return true;
+ }
+
+ QSet<QString> texts;
+ QSet<QString> textNeeded;
+
+ for (int i = 1; i < size(); i++) {
+ QString altGroup = mPriv->getStringOrEmpty(i, "alternative");
+ QString contentType = mPriv->getStringOrEmpty(i, "content-type");
+
+ if (contentType == QLatin1String("text/plain")) {
+ if (!altGroup.isEmpty()) {
+ // we can use this as an alternative for a non-text part
+ // with the same altGroup
+ texts << altGroup;
+ }
+ } else {
+ QString alt = mPriv->getStringOrEmpty(i, "alternative");
+ if (altGroup.isEmpty()) {
+ // we can't possibly rescue this part by using a text/plain
+ // alternative, because it's not in any alternative group
+ return true;
+ } else {
+ // maybe we'll find a text/plain alternative for this
+ textNeeded << altGroup;
+ }
+ }
+ }
+
+ textNeeded -= texts;
+ return !textNeeded.isEmpty();
+}
+
+/**
+ * Return the unique token identifying this message (e.g. the id attribute
+ * for XMPP messages), or an empty string if there is no suitable token.
+ *
+ * \return A non-empty message identifier, or an empty string if none
+ */
+QString Message::messageToken() const
+{
+ return mPriv->getStringOrEmpty(0, "message-token");
+}
+
+/**
+ * Return whether this message is specific to a D-Bus interface. This is
+ * false in almost all cases.
+ *
+ * If this function returns true, the message is specific to the interface
+ * indicated by dbusInterface. Clients that don't understand that interface
+ * should not display the message. However, if the client would acknowledge
+ * an ordinary message, it must also acknowledge this interface-specific
+ * message.
+ *
+ * \return true if dbusInterface would return a non-empty string
+ */
+bool Message::isSpecificToDBusInterface() const
+{
+ return !dbusInterface().isEmpty();
+}
+
+/**
+ * Return the D-Bus interface to which this message is specific, or an
+ * empty string for normal messages.
+ */
+QString Message::dbusInterface() const
+{
+ return mPriv->getStringOrEmpty(0, "interface");
+}
+
+QString Message::text() const
+{
+ // Alternative-groups for which we've already emitted an alternative
+ QSet<QString> altGroupsUsed;
+ QString text;
+
+ for (int i = 1; i < size(); i++) {
+ QString altGroup = mPriv->getStringOrEmpty(i, "alternative");
+ QString contentType = mPriv->getStringOrEmpty(i, "content-type");
+
+ if (contentType == QLatin1String("text/plain")) {
+ if (!altGroup.isEmpty()) {
+ if (altGroupsUsed.contains(altGroup)) {
+ continue;
+ } else {
+ altGroupsUsed << altGroup;
+ }
+ }
+
+ QVariant content = mPriv->value(i, "content");
+ if (content.type() == QVariant::String) {
+ text += content.toString();
+ } else {
+ // O RLY?
+ debug() << "allegedly text/plain part wasn't";
+ }
+ }
+ }
+
+ return text;
+}
+
+/**
+ * Return the message's header part, as defined by the Telepathy D-Bus API
+ * specification. This is provided for advanced clients that need to access
+ * additional information not available through the normal Message API.
+ *
+ * \return The same thing as messagepart(0)
+ */
+MessagePart Message::header() const
+{
+ return part(0);
+}
+
+/**
+ * Return the number of parts in this message.
+ *
+ * \return 1 greater than the largest valid argument to part
+ */
+int Message::size() const
+{
+ return mPriv->parts.size();
+}
+
+/**
+ * Return the message's header part, as defined by the Telepathy D-Bus API
+ * specification. This is provided for advanced clients that need to access
+ * additional information not available through the normal Message API.
+ *
+ * \param index The part to access, which must be strictly less than size();
+ * part number 0 is the header, parts numbered 1 or greater
+ * are the body of the message.
+ * \return Part of the message
+ */
+MessagePart Message::part(uint index) const
+{
+ return mPriv->parts.at(index);
+}
+
+/**
+ * \class ReceivedMessage
+ * \ingroup clientchannel
+ * \headerfile TelepathyQt4/Client/text-channel.h <TelepathyQt4/Client/TextChannel>
+ *
+ * Subclass of Message, with additional information that's generally only
+ * available on received messages.
+ */
+
+/**
+ * Default constructor, only used internally.
+ */
+ReceivedMessage::ReceivedMessage()
+{
+}
+
+/**
+ * Constructor.
+ *
+ * \param parts The parts of a message as defined by the Telepathy D-Bus
+ * specification. This list must have length at least 1.
+ */
+ReceivedMessage::ReceivedMessage(const MessagePartList &parts,
+ TextChannel *channel)
+ : Message(parts)
+{
+ if (!mPriv->parts[0].contains(QLatin1String("message-received"))) {
+ mPriv->parts[0].insert(QLatin1String("message-received"),
+ QDBusVariant(static_cast<qlonglong>(
+ QDateTime::currentDateTime().toTime_t())));
+ }
+ mPriv->textChannel = channel;
+}
+
+/**
+ * Copy constructor.
+ */
+ReceivedMessage::ReceivedMessage(const ReceivedMessage &other)
+ : Message(other)
+{
+}
+
+/**
+ * Assignment operator.
+ */
+ReceivedMessage &ReceivedMessage::operator=(const ReceivedMessage &other)
+{
+ if (this != &other) {
+ mPriv = other.mPriv;
+ }
+
+ return *this;
+}
+
+/**
+ * Destructor.
+ */
+ReceivedMessage::~ReceivedMessage()
+{
+}
+
+/**
+ * Return the time the message was received.
+ *
+ * \return A timestamp
+ */
+QDateTime ReceivedMessage::received() const
+{
+ // FIXME: Telepathy supports 64-bit time_t, but Qt only does so on
+ // ILP64 systems (e.g. sparc64, but not x86_64). If QDateTime
+ // gains a fromTimestamp64 method, we should use it instead.
+ uint stamp = mPriv->value(0, "message-received").toUInt();
+ if (stamp != 0) {
+ return QDateTime::fromTime_t(stamp);
+ } else {
+ return QDateTime();
+ }
+}
+
+/**
+ * Return the Contact who sent the message, or
+ * QSharedPointer<Contact>(0) if unknown.
+ *
+ * \return The sender or QSharedPointer<Contact>(0)
+ */
+QSharedPointer<Contact> ReceivedMessage::sender() const
+{
+ return mPriv->sender;
+}
+
+/**
+ * Return whether the incoming message was part of a replay of message
+ * history.
+ *
+ * If true, loggers can use this to improve their heuristics for elimination
+ * of duplicate messages (a simple, correct implementation would be to avoid
+ * logging any message that has this flag).
+ *
+ * \return whether the scrollback flag is set
+ */
+bool ReceivedMessage::isScrollback() const
+{
+ return mPriv->getBoolean(0, "scrollback", false);
+}
+
+/**
+ * Return whether the incoming message was seen in a previous channel during
+ * the lifetime of this Connection, but was not acknowledged before that
+ * chanenl closed, causing the channel in which it now appears to open.
+ *
+ * If true, loggers should not log this message again.
+ *
+ * \return whether the rescued flag is set
+ */
+bool ReceivedMessage::isRescued() const
+{
+ return mPriv->getBoolean(0, "rescued", false);
+}
+
+bool ReceivedMessage::isFromChannel(const TextChannel *channel) const
+{
+ return mPriv->textChannel == channel;
+}
+
+uint ReceivedMessage::pendingId() const
+{
+ return mPriv->pendingId();
+}
+
+uint ReceivedMessage::senderHandle() const
+{
+ return mPriv->senderHandle();
+}
+
+void ReceivedMessage::setForceNonText()
+{
+ mPriv->forceNonText = true;
+}
+
+void ReceivedMessage::clearSenderHandle()
+{
+ mPriv->clearSenderHandle();
+}
+
+void ReceivedMessage::setSender(const QSharedPointer<Contact> &sender)
+{
+ mPriv->sender = sender;
+}
+
+} // Telepathy::Client
+} // Telepathy
diff --git a/TelepathyQt4/Client/message.h b/TelepathyQt4/Client/message.h
index 2a65467..a535840 100644
--- a/TelepathyQt4/Client/message.h
+++ b/TelepathyQt4/Client/message.h
@@ -26,11 +26,19 @@
#endif
#include <QSharedDataPointer>
+#include <QSharedPointer>
+
+#include <TelepathyQt4/Constants>
+#include <TelepathyQt4/Types>
+
+class QDateTime;
namespace Telepathy
{
namespace Client
{
+class Contact;
+class TextChannel;
class Message
{
@@ -89,10 +97,18 @@ public:
bool isScrollback() const;
bool isRescued() const;
+ bool isFromChannel(const TextChannel *channel) const;
+
private:
friend class TextChannel;
- ReceivedMessage(const MessagePartList &parts, const TextChannel *channel);
+ ReceivedMessage(const MessagePartList &parts, TextChannel *channel);
ReceivedMessage();
+ uint senderHandle() const;
+ uint pendingId() const;
+
+ void setForceNonText();
+ void clearSenderHandle();
+ void setSender(const QSharedPointer<Contact> &sender);
};
} // Telepathy::Client
diff --git a/TelepathyQt4/Client/text-channel.cpp b/TelepathyQt4/Client/text-channel.cpp
index 03bacb1..4ec020c 100644
--- a/TelepathyQt4/Client/text-channel.cpp
+++ b/TelepathyQt4/Client/text-channel.cpp
@@ -39,489 +39,6 @@ namespace Telepathy
namespace Client
{
-class Message::Private : public QSharedData
-{
-public:
- Private(const MessagePartList &parts);
- ~Private();
-
- MessagePartList parts;
-
- // if the Text interface says "non-text" we still only have the text,
- // because the interface can't tell us anything else...
- bool forceNonText;
-
- // for received messages only
- const TextChannel *textChannel;
- QSharedPointer<Contact> sender;
-
- inline QVariant value(uint index, const char *key) const;
- inline uint getUIntOrZero(uint index, const char *key) const;
- inline QString getStringOrEmpty(uint index, const char *key) const;
- inline bool getBoolean(uint index, const char *key,
- bool assumeIfAbsent) const;
- inline uint senderHandle() const;
- inline uint pendingId() const;
- void clearSenderHandle();
-};
-
-Message::Private::Private(const MessagePartList &parts)
- : parts(parts),
- forceNonText(false),
- textChannel(0),
- sender(0)
-{
-}
-
-Message::Private::~Private()
-{
-}
-
-inline QVariant Message::Private::value(uint index, const char *key) const
-{
- return parts.at(index).value(QLatin1String(key)).variant();
-}
-
-inline QString Message::Private::getStringOrEmpty(uint index, const char *key)
- const
-{
- QString s = value(index, key).toString();
- if (s.isNull()) {
- s = QString::fromAscii("");
- }
- return s;
-}
-
-inline uint Message::Private::getUIntOrZero(uint index, const char *key)
- const
-{
- return value(index, key).toUInt();
-}
-
-inline bool Message::Private::getBoolean(uint index, const char *key,
- bool assumeIfAbsent) const
-{
- QVariant v = value(index, key);
- if (v.isValid() && v.type() == QVariant::Bool) {
- return v.toBool();
- }
- return assumeIfAbsent;
-}
-
-inline uint Message::Private::senderHandle() const
-{
- return getUIntOrZero(0, "message-sender");
-}
-
-inline uint Message::Private::pendingId() const
-{
- return getUIntOrZero(0, "pending-message-id");
-}
-
-void Message::Private::clearSenderHandle()
-{
- parts[0].remove(QLatin1String("message-sender"));
-}
-
-/**
- * \class Message
- * \ingroup clientchannel
- * \headerfile TelepathyQt4/Client/text-channel.h <TelepathyQt4/Client/TextChannel>
- *
- * Object representing a message. These objects are implicitly shared, like
- * QString.
- */
-
-/**
- * Default constructor, only used internally.
- */
-Message::Message()
-{
-}
-
-/**
- * Constructor.
- *
- * \param parts The parts of a message as defined by the Telepathy D-Bus
- * specification. This list must have length at least 1.
- */
-Message::Message(const MessagePartList &parts)
- : mPriv(new Private(parts))
-{
- Q_ASSERT(parts.size() > 0);
-}
-
-/**
- * Constructor, from the parameters of the old Sent signal.
- *
- * \param timestamp The time the message was sent
- * \param type The message type
- * \param text The text of the message
- */
-Message::Message(uint timestamp, uint type, const QString &text)
- : mPriv(new Private(MessagePartList() << MessagePart() << MessagePart()))
-{
- mPriv->parts[0].insert(QString::fromAscii("message-sent"),
- QDBusVariant(static_cast<qlonglong>(timestamp)));
- mPriv->parts[0].insert(QString::fromAscii("message-type"),
- QDBusVariant(type));
-
- mPriv->parts[1].insert(QString::fromAscii("content-type"),
- QDBusVariant(QString::fromAscii("text/plain")));
- mPriv->parts[1].insert(QString::fromAscii("content"), QDBusVariant(text));
-}
-
-/**
- * Copy constructor.
- */
-Message::Message(const Message &other)
- : mPriv(other.mPriv)
-{
-}
-
-/**
- * Assignment operator.
- */
-Message &Message::operator=(const Message &other)
-{
- if (this != &other) {
- mPriv = other.mPriv;
- }
-
- return *this;
-}
-
-/**
- * Equality operator.
- */
-bool Message::operator==(const Message &other) const
-{
- return this->mPriv == other.mPriv;
-}
-
-/**
- * Destructor.
- */
-Message::~Message()
-{
-}
-
-/**
- * Return the time the message was sent, or QDateTime() if that time is
- * unknown.
- *
- * \return A timestamp
- */
-QDateTime Message::sent() const
-{
- // FIXME: Telepathy supports 64-bit time_t, but Qt only does so on
- // ILP64 systems (e.g. sparc64, but not x86_64). If QDateTime
- // gains a fromTimestamp64 method, we should use it instead.
- uint stamp = mPriv->value(0, "message-sent").toUInt();
- if (stamp != 0) {
- return QDateTime::fromTime_t(stamp);
- } else {
- return QDateTime();
- }
-}
-
-/**
- * Return the type of message this is, or ChannelTextMessageTypeNormal
- * if the type is not recognised.
- *
- * \return The ChannelTextMessageType for this message
- */
-ChannelTextMessageType Message::messageType() const
-{
- uint raw = mPriv->value(0, "message-type").toUInt();
-
- if (raw < static_cast<uint>(NUM_CHANNEL_TEXT_MESSAGE_TYPES)) {
- return ChannelTextMessageType(raw);
- } else {
- return ChannelTextMessageTypeNormal;
- }
-}
-
-/**
- * Return whether this message was truncated during delivery.
- */
-bool Message::isTruncated() const
-{
- for (int i = 1; i < size(); i++) {
- if (mPriv->getBoolean(i, "truncated", false)) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Return whether this message contains parts not representable as plain
- * text.
- *
- * \return true if this message cannot completely be represented as plain text
- */
-bool Message::hasNonTextContent() const
-{
- if (mPriv->forceNonText || size() <= 1 || isSpecificToDBusInterface()) {
- return true;
- }
-
- QSet<QString> texts;
- QSet<QString> textNeeded;
-
- for (int i = 1; i < size(); i++) {
- QString altGroup = mPriv->getStringOrEmpty(i, "alternative");
- QString contentType = mPriv->getStringOrEmpty(i, "content-type");
-
- if (contentType == QLatin1String("text/plain")) {
- if (!altGroup.isEmpty()) {
- // we can use this as an alternative for a non-text part
- // with the same altGroup
- texts << altGroup;
- }
- } else {
- QString alt = mPriv->getStringOrEmpty(i, "alternative");
- if (altGroup.isEmpty()) {
- // we can't possibly rescue this part by using a text/plain
- // alternative, because it's not in any alternative group
- return true;
- } else {
- // maybe we'll find a text/plain alternative for this
- textNeeded << altGroup;
- }
- }
- }
-
- textNeeded -= texts;
- return !textNeeded.isEmpty();
-}
-
-/**
- * Return the unique token identifying this message (e.g. the id attribute
- * for XMPP messages), or an empty string if there is no suitable token.
- *
- * \return A non-empty message identifier, or an empty string if none
- */
-QString Message::messageToken() const
-{
- return mPriv->getStringOrEmpty(0, "message-token");
-}
-
-/**
- * Return whether this message is specific to a D-Bus interface. This is
- * false in almost all cases.
- *
- * If this function returns true, the message is specific to the interface
- * indicated by dbusInterface. Clients that don't understand that interface
- * should not display the message. However, if the client would acknowledge
- * an ordinary message, it must also acknowledge this interface-specific
- * message.
- *
- * \return true if dbusInterface would return a non-empty string
- */
-bool Message::isSpecificToDBusInterface() const
-{
- return !dbusInterface().isEmpty();
-}
-
-/**
- * Return the D-Bus interface to which this message is specific, or an
- * empty string for normal messages.
- */
-QString Message::dbusInterface() const
-{
- return mPriv->getStringOrEmpty(0, "interface");
-}
-
-QString Message::text() const
-{
- // Alternative-groups for which we've already emitted an alternative
- QSet<QString> altGroupsUsed;
- QString text;
-
- for (int i = 1; i < size(); i++) {
- QString altGroup = mPriv->getStringOrEmpty(i, "alternative");
- QString contentType = mPriv->getStringOrEmpty(i, "content-type");
-
- if (contentType == QLatin1String("text/plain")) {
- if (!altGroup.isEmpty()) {
- if (altGroupsUsed.contains(altGroup)) {
- continue;
- } else {
- altGroupsUsed << altGroup;
- }
- }
-
- QVariant content = mPriv->value(i, "content");
- if (content.type() == QVariant::String) {
- text += content.toString();
- } else {
- // O RLY?
- debug() << "allegedly text/plain part wasn't";
- }
- }
- }
-
- return text;
-}
-
-/**
- * Return the message's header part, as defined by the Telepathy D-Bus API
- * specification. This is provided for advanced clients that need to access
- * additional information not available through the normal Message API.
- *
- * \return The same thing as messagepart(0)
- */
-MessagePart Message::header() const
-{
- return part(0);
-}
-
-/**
- * Return the number of parts in this message.
- *
- * \return 1 greater than the largest valid argument to part
- */
-int Message::size() const
-{
- return mPriv->parts.size();
-}
-
-/**
- * Return the message's header part, as defined by the Telepathy D-Bus API
- * specification. This is provided for advanced clients that need to access
- * additional information not available through the normal Message API.
- *
- * \param index The part to access, which must be strictly less than size();
- * part number 0 is the header, parts numbered 1 or greater
- * are the body of the message.
- * \return Part of the message
- */
-MessagePart Message::part(uint index) const
-{
- return mPriv->parts.at(index);
-}
-
-/**
- * \class ReceivedMessage
- * \ingroup clientchannel
- * \headerfile TelepathyQt4/Client/text-channel.h <TelepathyQt4/Client/TextChannel>
- *
- * Subclass of Message, with additional information that's generally only
- * available on received messages.
- */
-
-/**
- * Default constructor, only used internally.
- */
-ReceivedMessage::ReceivedMessage()
-{
-}
-
-/**
- * Constructor.
- *
- * \param parts The parts of a message as defined by the Telepathy D-Bus
- * specification. This list must have length at least 1.
- */
-ReceivedMessage::ReceivedMessage(const MessagePartList &parts,
- const TextChannel *channel)
- : Message(parts)
-{
- if (!mPriv->parts[0].contains(QLatin1String("message-received"))) {
- mPriv->parts[0].insert(QLatin1String("message-received"),
- QDBusVariant(static_cast<qlonglong>(
- QDateTime::currentDateTime().toTime_t())));
- }
- mPriv->textChannel = channel;
-}
-
-/**
- * Copy constructor.
- */
-ReceivedMessage::ReceivedMessage(const ReceivedMessage &other)
- : Message(other)
-{
-}
-
-/**
- * Assignment operator.
- */
-ReceivedMessage &ReceivedMessage::operator=(const ReceivedMessage &other)
-{
- if (this != &other) {
- mPriv = other.mPriv;
- }
-
- return *this;
-}
-
-/**
- * Destructor.
- */
-ReceivedMessage::~ReceivedMessage()
-{
-}
-
-/**
- * Return the time the message was received.
- *
- * \return A timestamp
- */
-QDateTime ReceivedMessage::received() const
-{
- // FIXME: Telepathy supports 64-bit time_t, but Qt only does so on
- // ILP64 systems (e.g. sparc64, but not x86_64). If QDateTime
- // gains a fromTimestamp64 method, we should use it instead.
- uint stamp = mPriv->value(0, "message-received").toUInt();
- if (stamp != 0) {
- return QDateTime::fromTime_t(stamp);
- } else {
- return QDateTime();
- }
-}
-
-/**
- * Return the Contact who sent the message, or
- * QSharedPointer<Contact>(0) if unknown.
- *
- * \return The sender or QSharedPointer<Contact>(0)
- */
-QSharedPointer<Contact> ReceivedMessage::sender() const
-{
- return mPriv->sender;
-}
-
-/**
- * Return whether the incoming message was part of a replay of message
- * history.
- *
- * If true, loggers can use this to improve their heuristics for elimination
- * of duplicate messages (a simple, correct implementation would be to avoid
- * logging any message that has this flag).
- *
- * \return whether the scrollback flag is set
- */
-bool ReceivedMessage::isScrollback() const
-{
- return mPriv->getBoolean(0, "scrollback", false);
-}
-
-/**
- * Return whether the incoming message was seen in a previous channel during
- * the lifetime of this Connection, but was not acknowledged before that
- * chanenl closed, causing the channel in which it now appears to open.
- *
- * If true, loggers should not log this message again.
- *
- * \return whether the rescued flag is set
- */
-bool ReceivedMessage::isRescued() const
-{
- return mPriv->getBoolean(0, "rescued", false);
-}
-
struct TextChannel::Private
{
inline Private();
@@ -837,10 +354,10 @@ void TextChannel::acknowledge(const QList<ReceivedMessage> &messages)
UIntList ids;
foreach (const ReceivedMessage &m, messages) {
- if (m.mPriv->textChannel != this) {
- warning() << "message did not come from this channel, ignoring";
+ if (m.isFromChannel(this)) {
+ ids << m.pendingId();
} else {
- ids << m.mPriv->getUIntOrZero(0, "pending-message-id");
+ warning() << "message did not come from this channel, ignoring";
}
}
@@ -877,7 +394,7 @@ void TextChannel::acknowledge(const QList<ReceivedMessage> &messages)
void TextChannel::forget(const QList<ReceivedMessage> &messages)
{
foreach (const ReceivedMessage &m, messages) {
- if (m.mPriv->textChannel != this) {
+ if (!m.isFromChannel(this)) {
warning() << "message did not come from this channel, ignoring";
} else if (mPriv->messages.removeOne(m)) {
emit pendingMessageRemoved(m);
@@ -1126,8 +643,8 @@ void TextChannel::processQueue()
debug() << "QueuedEvent:" << e;
if (e->isMessage) {
- if (e->message.mPriv->senderHandle() != 0 &&
- !e->message.mPriv->sender) {
+ if (e->message.senderHandle() != 0 &&
+ !e->message.sender()) {
// the message doesn't have a sender Contact, but needs one.
// We'll have to stop processing here, and come back to it
// when we have more Contact objects
@@ -1143,7 +660,7 @@ void TextChannel::processQueue()
// at most one under normal circumstances)
int i = 0;
while (i < mPriv->messages.size()) {
- if (mPriv->messages.at(i).mPriv->pendingId() == e->removed) {
+ if (mPriv->messages.at(i).pendingId() == e->removed) {
emit pendingMessageRemoved(mPriv->messages.at(i));
mPriv->messages.removeAt(i);
} else {
@@ -1172,8 +689,8 @@ void TextChannel::processQueue()
QSet<uint> contactsRequired;
foreach (const Private::QueuedEvent *e, mPriv->incompleteMessages) {
if (e->isMessage) {
- uint handle = e->message.mPriv->senderHandle();
- if (handle != 0 && !e->message.mPriv->sender
+ uint handle = e->message.senderHandle();
+ if (handle != 0 && !e->message.sender()
&& !mPriv->awaitingContacts.contains(handle)) {
contactsRequired << handle;
}
@@ -1193,9 +710,9 @@ void TextChannel::Private::contactLost(uint handle)
// we're not going to get a Contact object for this handle, so mark the
// messages from that handle as "unknown sender"
foreach (QueuedEvent *e, incompleteMessages) {
- if (e->isMessage && e->message.mPriv->senderHandle() == handle
- && !e->message.mPriv->sender) {
- e->message.mPriv->clearSenderHandle();
+ if (e->isMessage && e->message.senderHandle() == handle
+ && !e->message.sender()) {
+ e->message.clearSenderHandle();
}
}
}
@@ -1205,9 +722,9 @@ void TextChannel::Private::contactFound(QSharedPointer<Contact> contact)
uint handle = contact->handle().at(0);
foreach (QueuedEvent *e, incompleteMessages) {
- if (e->isMessage && e->message.mPriv->senderHandle() == handle
- && !e->message.mPriv->sender) {
- e->message.mPriv->sender = contact;
+ if (e->isMessage && e->message.senderHandle() == handle
+ && !e->message.sender()) {
+ e->message.setSender(contact);
}
}
}
@@ -1313,7 +830,7 @@ void TextChannel::onTextReceived(uint id, uint timestamp, uint sender,
if (flags & ChannelTextMessageFlagNonTextContent) {
// set the "you are not expected to understand this" flag
- m.mPriv->forceNonText = true;
+ m.setForceNonText();
}
mPriv->incompleteMessages << new Private::QueuedEvent(m);
diff --git a/TelepathyQt4/Client/text-channel.h b/TelepathyQt4/Client/text-channel.h
index 37af142..91f9c57 100644
--- a/TelepathyQt4/Client/text-channel.h
+++ b/TelepathyQt4/Client/text-channel.h
@@ -32,7 +32,6 @@ namespace Telepathy
namespace Client
{
-class TextChannel;
class PendingReadyChannel;
class Message;
class ReceivedMessage;
diff --git a/TelepathyQt4/Makefile.am b/TelepathyQt4/Makefile.am
index 0daa5c0..c7a5f6e 100644
--- a/TelepathyQt4/Makefile.am
+++ b/TelepathyQt4/Makefile.am
@@ -50,6 +50,7 @@ libtelepathy_qt4_la_SOURCES = \
Client/file-transfer.cpp \
Client/media-session-handler.cpp \
Client/media-stream-handler.cpp \
+ Client/message.cpp \
Client/optional-interface-factory.cpp \
Client/pending-account.cpp \
Client/pending-channel.cpp \
--
1.5.6.5
More information about the telepathy-commits
mailing list