[Telepathy-commits] [telepathy-qt4/master] Added initial Account impl.

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Thu Jan 8 14:49:37 PST 2009


---
 TelepathyQt4/Client/account-internal.h |  101 +++++++
 TelepathyQt4/Client/account.cpp        |  501 +++++++++++++++++++++++++++++++-
 TelepathyQt4/Client/account.h          |  152 +++++++++-
 TelepathyQt4/Makefile.am               |    3 +
 4 files changed, 743 insertions(+), 14 deletions(-)
 create mode 100644 TelepathyQt4/Client/account-internal.h

diff --git a/TelepathyQt4/Client/account-internal.h b/TelepathyQt4/Client/account-internal.h
new file mode 100644
index 0000000..19e9d22
--- /dev/null
+++ b/TelepathyQt4/Client/account-internal.h
@@ -0,0 +1,101 @@
+/*
+ * This file is part of TelepathyQt4
+ *
+ * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+ * Copyright (C) 2008 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
+ */
+
+#ifndef _TelepathyQt4_cli_account_internal_h_HEADER_GUARD_
+#define _TelepathyQt4_cli_account_internal_h_HEADER_GUARD_
+
+#include <TelepathyQt4/Client/PendingOperation>
+#include <TelepathyQt4/Constants>
+#include <TelepathyQt4/Types>
+
+#include <QByteArray>
+#include <QQueue>
+#include <QString>
+#include <QStringList>
+#include <QVariantMap>
+
+namespace Telepathy
+{
+namespace Client
+{
+
+class Account;
+class AccountInterface;
+
+class Account::Private : public QObject
+{
+    Q_OBJECT
+
+public:
+    Private(Account *parent);
+    ~Private();
+
+    void callGetAll();
+    void callGetAvatar();
+    void updateProperties(const QVariantMap &props);
+
+    class PendingReady;
+
+    AccountInterface *baseInterface;
+    bool ready;
+    PendingReady *pendingReady;
+    QQueue<void (Private::*)()> introspectQueue;
+    QStringList interfaces;
+    Account::Features features;
+    QVariantMap parameters;
+    bool valid;
+    bool enabled;
+    bool connectsAutomatically;
+    QString cmName;
+    QString protocol;
+    QString displayName;
+    QString nickname;
+    QString icon;
+    QString connectionObjectPath;
+    QString normalizedName;
+    QString avatarMimeType;
+    QByteArray avatarData;
+    Telepathy::ConnectionStatus connectionStatus;
+    Telepathy::ConnectionStatusReason connectionStatusReason;
+    Telepathy::SimplePresence automaticPresence;
+    Telepathy::SimplePresence currentPresence;
+    Telepathy::SimplePresence requestedPresence;
+
+private Q_SLOTS:
+    void onGetAllAccountReturn(QDBusPendingCallWatcher *);
+    void onPropertyChanged(const QVariantMap &delta);
+    void onRemoved();
+    void continueIntrospection();
+};
+
+class Account::Private::PendingReady : public PendingOperation
+{
+    // Account::Private is a friend so it can call finished() etc.
+    friend class Account::Private;
+
+public:
+    PendingReady(Account *parent);
+};
+
+} // Telepathy::Client
+} // Telepathy
+
+#endif
diff --git a/TelepathyQt4/Client/account.cpp b/TelepathyQt4/Client/account.cpp
index 08ccb17..2e727cc 100644
--- a/TelepathyQt4/Client/account.cpp
+++ b/TelepathyQt4/Client/account.cpp
@@ -20,6 +20,505 @@
  */
 
 #include <TelepathyQt4/Client/Account>
+#include "TelepathyQt4/Client/account-internal.h"
 
-#include "TelepathyQt4/_gen/cli-account-body.hpp"
+#include "TelepathyQt4/Client/_gen/account.moc.hpp"
+#include "TelepathyQt4/Client/_gen/account-internal.moc.hpp"
 #include "TelepathyQt4/_gen/cli-account.moc.hpp"
+#include "TelepathyQt4/_gen/cli-account-body.hpp"
+
+#include "TelepathyQt4/debug-internal.h"
+
+#include <TelepathyQt4/Client/AccountManager>
+#include <TelepathyQt4/Client/PendingVoidMethodCall>
+#include <TelepathyQt4/Constants>
+#include <TelepathyQt4/Debug>
+
+#include <QQueue>
+#include <QRegExp>
+#include <QTimer>
+
+/**
+ * \addtogroup clientsideproxies Client-side proxies
+ *
+ * Proxy objects representing remote service objects accessed via D-Bus.
+ *
+ * In addition to providing direct access to methods, signals and properties
+ * exported by the remote objects, some of these proxies offer features like
+ * automatic inspection of remote object capabilities, property tracking,
+ * backwards compatibility helpers for older services and other utilities.
+ */
+
+namespace Telepathy
+{
+namespace Client
+{
+
+Account::Private::PendingReady::PendingReady(Account *parent)
+    : PendingOperation(parent)
+{
+}
+
+Account::Private::Private(Account *parent)
+    : QObject(parent),
+      baseInterface(new AccountInterface(parent->dbusConnection(),
+                        parent->busName(), parent->objectPath(), parent)),
+      ready(false),
+      pendingReady(0),
+      features(0),
+      valid(false),
+      enabled(false),
+      connectsAutomatically(false),
+      connectionStatus(Telepathy::ConnectionStatusDisconnected),
+      connectionStatusReason(Telepathy::ConnectionStatusReasonNoneSpecified)
+{
+    // FIXME: QRegExp probably isn't the most efficient possible way to parse
+    //        this :-)
+    QRegExp rx("^" TELEPATHY_ACCOUNT_OBJECT_PATH_BASE
+               "/([_A-Za-z][_A-Za-z0-9]*)"  // cap(1) is the CM
+               "/([_A-Za-z][_A-Za-z0-9]*)"  // cap(2) is the protocol
+               "/" // account-specific part
+               );
+
+    if (rx.exactMatch(parent->objectPath())) {
+        cmName = rx.cap(1);
+        protocol = rx.cap(2);
+    } else {
+        warning() << "Not a valid Account object path:" <<
+            parent->objectPath();
+    }
+
+    connect(baseInterface,
+            SIGNAL(Removed()),
+            SLOT(onRemoved()));
+    connect(baseInterface,
+            SIGNAL(AccountPropertyChanged(QVariantMap *)),
+            SLOT(onPropertyChanged(QVariantMap *)));
+
+    introspectQueue.enqueue(&Private::callGetAll);
+    QTimer::singleShot(0, this, SLOT(continueIntrospection()));
+}
+
+Account::Private::~Private()
+{
+    delete baseInterface;
+}
+
+void Account::Private::callGetAll()
+{
+    debug() << "Calling Properties::GetAll(Account)";
+    Account *ac = static_cast<Account *>(parent());
+    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+            ac->propertiesInterface()->GetAll(
+                TELEPATHY_INTERFACE_ACCOUNT), this);
+    connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(onGetAllAccountReturn(QDBusPendingCallWatcher *)));
+}
+
+#if 0
+void Account::Private::callGetAvatar()
+{
+}
+#endif
+
+void Account::Private::updateProperties(const QVariantMap &props)
+{
+    if (props.contains("Interfaces")) {
+        interfaces = qdbus_cast<QStringList>(props["Interfaces"]);
+    }
+
+    if (props.contains("DisplayName")) {
+        displayName = qdbus_cast<QString>(props["DisplayName"]);
+    }
+
+    if (props.contains("Icon")) {
+        icon = qdbus_cast<QString>(props["Icon"]);
+    }
+
+    if (props.contains("Nickname")) {
+        nickname = qdbus_cast<QString>(props["Nickname"]);
+    }
+
+    if (props.contains("NormalizedName")) {
+        normalizedName = qdbus_cast<QString>(props["NormalizedName"]);
+    }
+
+    if (props.contains("Valid")) {
+        valid = qdbus_cast<bool>(props["Valid"]);
+    }
+
+    if (props.contains("Enabled")) {
+        enabled = qdbus_cast<bool>(props["Enabled"]);
+    }
+
+    if (props.contains("ConnectAutomatically")) {
+        connectsAutomatically =
+                qdbus_cast<bool>(props["ConnectAutomatically"]);
+    }
+
+    if (props.contains("Parameters")) {
+        parameters = qdbus_cast<QVariantMap>(props["Parameters"]);
+    }
+
+    if (props.contains("AutomaticPresence")) {
+        automaticPresence = qdbus_cast<Telepathy::SimplePresence>(
+                props["AutomaticPresence"]);
+    }
+
+    if (props.contains("CurrentPresence")) {
+        currentPresence = qdbus_cast<Telepathy::SimplePresence>(
+                props["CurrentPresence"]);
+    }
+
+    if (props.contains("RequestedPresence")) {
+        requestedPresence = qdbus_cast<Telepathy::SimplePresence>(
+                props["RequestedPresence"]);
+    }
+
+    if (props.contains("Connection")) {
+        QString path = qdbus_cast<QDBusObjectPath>(props["Connection"]).path();
+        if (path == QLatin1String("/")) {
+            connectionObjectPath = QString();
+        } else {
+            connectionObjectPath = path;
+        }
+    }
+
+    if (props.contains("ConnectionStatus")) {
+        connectionStatus = Telepathy::ConnectionStatus(
+                qdbus_cast<uint>(props["ConnectionStatus"]));
+    }
+
+    if (props.contains("ConnectionStatusReason")) {
+        connectionStatusReason = Telepathy::ConnectionStatusReason(
+                qdbus_cast<uint>(props["ConnectionStatusReason"]));
+    }
+}
+
+void Account::Private::onGetAllAccountReturn(QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<QVariantMap> reply = *watcher;
+
+    if (!reply.isError()) {
+        debug() << "Got reply to Properties.GetAll(Account)";
+        updateProperties(reply.value());
+    } else {
+        warning().nospace() <<
+            "GetAll(Account) failed: " <<
+            reply.error().name() << ": " << reply.error().message();
+    }
+}
+
+void Account::Private::onPropertyChanged(const QVariantMap &delta)
+{
+    updateProperties(delta);
+}
+
+void Account::Private::onRemoved()
+{
+    ready = false;
+    valid = false;
+    enabled = false;
+}
+
+void Account::Private::continueIntrospection()
+{
+    if (!ready) {
+        if (introspectQueue.isEmpty()) {
+            debug() << "Account is ready";
+            ready = true;
+
+            if (pendingReady) {
+                pendingReady->setFinished();
+                // it will delete itself later
+                pendingReady = 0;
+            }
+        }
+        else {
+            (this->*(introspectQueue.dequeue()))();
+        }
+    }
+}
+
+/**
+ * \class Account
+ * \ingroup clientaccount
+ * \headerfile TelepathyQt4/Client/account.h> <TelepathyQt4/Client/Account>
+ *
+ * Object representing a Telepathy account.
+ */
+
+/**
+ * Construct a new Account object.
+ *
+ * \param am Account manager.
+ * \param objectPath Account object path.
+ * \param parent Object parent.
+ */
+Account::Account(AccountManager *am, const QDBusObjectPath &objectPath,
+        QObject *parent)
+    : StatelessDBusProxy(am->dbusConnection(), am->busName(), objectPath.path(),
+            parent),
+      mPriv(new Private(this))
+{
+}
+
+/**
+ * Class destructor.
+ */
+Account::~Account()
+{
+    delete mPriv;
+}
+
+QStringList Account::interfaces() const
+{
+    return mPriv->interfaces;
+}
+
+/**
+ * \fn DBus::propertiesInterface *Account::propertiesInterface() const
+ *
+ * Convenience function for getting a Properties interface proxy. The
+ * Account interface relies on properties, so this interface is
+ * always assumed to be present.
+ */
+
+/**
+ * Get the AccountManager from which this Account was created.
+ *
+ * \return A pointer to the AccountManager object that owns this Account.
+ */
+AccountManager *Account::manager() const
+{
+    return qobject_cast<AccountManager *>(parent());
+}
+
+/**
+ * Return whether this is a valid account.
+ *
+ * \return \c true if the account is valid, \c false otherwise.
+ */
+bool Account::isValid() const
+{
+    return mPriv->valid;
+}
+
+/**
+ * Return whether this account is enabled.
+ *
+ * \return \c true if the account is enabled, \c false otherwise.
+ */
+bool Account::isEnabled() const
+{
+    return mPriv->enabled;
+}
+
+PendingOperation *Account::setEnabled(bool value)
+{
+    return new PendingVoidMethodCall(this,
+            propertiesInterface()->Set(TELEPATHY_INTERFACE_ACCOUNT,
+                "Enabled", QDBusVariant(value)));
+}
+
+QString Account::cmName() const
+{
+    return mPriv->cmName;
+}
+
+QString Account::protocol() const
+{
+    return mPriv->protocol;
+}
+
+QString Account::displayName() const
+{
+    return mPriv->displayName;
+}
+
+PendingOperation *Account::setDisplayName(const QString &value)
+{
+    return new PendingVoidMethodCall(this,
+            propertiesInterface()->Set(TELEPATHY_INTERFACE_ACCOUNT,
+                "DisplayName", QDBusVariant(value)));
+}
+
+QString Account::icon() const
+{
+    return mPriv->icon;
+}
+
+PendingOperation *Account::setIcon(const QString &value)
+{
+    return new PendingVoidMethodCall(this,
+            propertiesInterface()->Set(TELEPATHY_INTERFACE_ACCOUNT,
+                "Icon", QDBusVariant(value)));
+}
+
+QString Account::nickname() const
+{
+    return mPriv->nickname;
+}
+
+PendingOperation *Account::setNickname(const QString &value)
+{
+    return new PendingVoidMethodCall(this,
+            propertiesInterface()->Set(TELEPATHY_INTERFACE_ACCOUNT,
+                "Nickname", QDBusVariant(value)));
+}
+
+QByteArray Account::avatarData() const
+{
+    return mPriv->avatarData;
+}
+
+QString Account::avatarMimeType() const
+{
+    return mPriv->avatarMimeType;
+}
+
+#if 0
+PendingOperation *Account::setAvatar(const QByteArray &data,
+        const QString &mimeType)
+{
+}
+#endif
+
+QVariantMap Account::parameters() const
+{
+    return mPriv->parameters;
+}
+
+#if 0
+PendingOperation *Account::updateParameters(const QVariantMap &set,
+        const QStringList &unset)
+{
+    return 0;
+}
+
+ProtocolInfo *Account::protocolInfo() const
+{
+    return 0;
+}
+#endif
+
+Telepathy::SimplePresence Account::automaticPresence() const
+{
+    return mPriv->automaticPresence;
+}
+
+#if 0
+PendingOperation *Account::setAutomaticPresence(
+        const Telepathy::SimplePresence &value)
+{
+    return 0;
+}
+#endif
+
+bool Account::connectsAutomatically() const
+{
+    return mPriv->connectsAutomatically;
+}
+
+#if 0
+PendingOperation *Account::setConnectsAutomatically(bool value)
+{
+    return 0;
+}
+#endif
+
+Telepathy::ConnectionStatus Account::connectionStatus() const
+{
+    return mPriv->connectionStatus;
+}
+
+Telepathy::ConnectionStatusReason Account::connectionStatusReason() const
+{
+    return mPriv->connectionStatusReason;
+}
+
+// PendingConnection *Account::getConnection(Connection::Features features = 0) const
+// {
+//     return 0;
+// }
+
+Telepathy::SimplePresence Account::currentPresence() const
+{
+    return mPriv->currentPresence;
+}
+
+Telepathy::SimplePresence Account::requestedPresence() const
+{
+    return mPriv->requestedPresence;
+}
+
+#if 0
+PendingOperation *Account::setRequestedPresence(
+        const Telepathy::SimplePresence &value)
+{
+    return 0;
+}
+
+QString Account::uniqueIdentifier() const
+{
+    QString result;
+    // TODO
+    return result;
+}
+#endif
+
+QString Account::connectionObjectPath() const
+{
+    return mPriv->connectionObjectPath;
+}
+
+QString Account::normalizedName() const
+{
+    return mPriv->normalizedName;
+}
+
+PendingOperation *Account::remove()
+{
+    return new PendingVoidMethodCall(this, baseInterface()->Remove());
+}
+
+bool Account::isReady(Features features) const
+{
+    return mPriv->ready
+        && ((mPriv->features & features) == features);
+}
+
+PendingOperation *Account::becomeReady(Features features)
+{
+    if (isReady(features)) {
+        return new PendingSuccess(this);
+    }
+
+    if (features != 0) {
+        return new PendingFailure(this, "org.freedesktop.Telepathy.Qt.DoesntWork",
+                "Unimplemented");
+    }
+
+    if (!mPriv->pendingReady) {
+        mPriv->pendingReady = new Private::PendingReady(this);
+    }
+    return mPriv->pendingReady;
+}
+
+/**
+ * Get the AccountInterface for this Account. This
+ * method is protected since the convenience methods provided by this
+ * class should generally be used instead of calling D-Bus methods
+ * directly.
+ *
+ * \return A pointer to the existing AccountInterface for this
+ *         Account.
+ */
+AccountInterface *Account::baseInterface() const
+{
+    return mPriv->baseInterface;
+}
+
+} // Telepathy::Client
+} // Telepathy
diff --git a/TelepathyQt4/Client/account.h b/TelepathyQt4/Client/account.h
index d0abf55..a2e0aa2 100644
--- a/TelepathyQt4/Client/account.h
+++ b/TelepathyQt4/Client/account.h
@@ -26,20 +26,146 @@
 #error IN_TELEPATHY_QT4_HEADER
 #endif
 
-/**
- * \addtogroup clientsideproxies Client-side proxies
- *
- * Proxy objects representing remote service objects accessed via D-Bus.
- *
- * In addition to providing direct access to methods, signals and properties
- * exported by the remote objects, some of these proxies offer features like
- * automatic inspection of remote object capabilities, property tracking,
- * backwards compatibility helpers for older services and other utilities.
- */
+#include <TelepathyQt4/_gen/cli-account.h>
 
-/* See account-manager.h for doxygen */
+#include <TelepathyQt4/Client/DBus>
+#include <TelepathyQt4/Client/DBusProxy>
+#include <TelepathyQt4/Client/OptionalInterfaceFactory>
+#include <TelepathyQt4/Constants>
+#include <TelepathyQt4/Types>
 
-#include <TelepathyQt4/_gen/cli-account.h>
+#include <QDBusObjectPath>
+#include <QString>
+#include <QStringList>
+#include <QVariantMap>
 
-#endif
+namespace Telepathy
+{
+namespace Client
+{
+
+class AccountManager;
+class PendingConnection;
+class PendingOperation;
+class ProtocolInfo;
+
+class Account : public StatelessDBusProxy,
+        private OptionalInterfaceFactory
+{
+    Q_OBJECT
+
+public:
+    enum Feature {
+        /** Get the avatar data */
+        FeatureAvatar = 1,
+        FeatureProtocolInfo = 2,
+        _Padding = 0xFFFFFFFF
+    };
+    Q_DECLARE_FLAGS(Features, Feature)
+
+    Account(AccountManager *am, const QDBusObjectPath &objectPath,
+            QObject *parent = 0);
+
+    virtual ~Account();
+
+    QStringList interfaces() const;
+
+    inline DBus::PropertiesInterface *propertiesInterface() const
+    {
+        return OptionalInterfaceFactory::interface<DBus::PropertiesInterface>(
+                *baseInterface());
+    }
+
+    AccountManager *manager() const;
+
+    bool isValid() const;
+
+    bool isEnabled() const;
+    PendingOperation *setEnabled(bool value);
+
+    QString cmName() const;
+
+    QString protocol() const;
+
+    QString displayName() const;
+    PendingOperation *setDisplayName(const QString &value);
+
+    QString icon() const;
+    PendingOperation *setIcon(const QString &value);
+
+    QString nickname() const;
+    PendingOperation *setNickname(const QString &value);
 
+    // requires spec 0.17.16
+    QByteArray avatarData() const;
+    QString avatarMimeType() const;
+    PendingOperation *setAvatar(const QByteArray &data, const QString &mimeType);
+
+    QVariantMap parameters() const;
+    PendingOperation *updateParameters(const QVariantMap &set,
+            const QStringList &unset);
+
+    // comes from the ConnectionManager
+    ProtocolInfo *protocolInfo() const;
+
+    Telepathy::SimplePresence automaticPresence() const;
+    PendingOperation *setAutomaticPresence(
+            const Telepathy::SimplePresence &value);
+
+    bool connectsAutomatically() const;
+    PendingOperation *setConnectsAutomatically(bool value);
+
+    Telepathy::ConnectionStatus connectionStatus() const;
+    Telepathy::ConnectionStatusReason connectionStatusReason() const;
+    // not finished until the Connection is ready
+    // PendingConnection *getConnection(Connection::Features features = 0) const;
+
+    Telepathy::SimplePresence currentPresence() const;
+
+    Telepathy::SimplePresence requestedPresence() const;
+    PendingOperation *setRequestedPresence(
+            const Telepathy::SimplePresence &value);
+
+    // Unique per AccountManager implementation, i.e. at least per
+    // QDBusConnection.
+    //
+    // returns the tail of the object path, i.e.
+    // /org/freedesktop/Account/gabble/jabber/smcv_5eexample_2bcom ->
+    // gabble/jabber/smcv_5eexample_2bcom
+    QString uniqueIdentifier() const;
+
+    // doc as for advanced users
+    QString connectionObjectPath() const;
+
+    QString normalizedName() const;
+
+    PendingOperation *remove();
+
+    bool isReady(Features features = 0) const;
+
+    PendingOperation *becomeReady(Features features = 0);
+
+Q_SIGNALS:
+    void displayNameChanged(const QString &);
+    void presenceChanged(const Telepathy::SimplePresence &) const;
+    void avatarChanged(const QByteArray &data, const QString &mimeType);
+    void connectionStatusChanged(Telepathy::ConnectionStatus,
+            Telepathy::ConnectionStatusReason);
+
+protected:
+    AccountInterface *baseInterface() const;
+
+private:
+    Q_DISABLE_COPY(Account);
+
+    class Private;
+    friend class Private;
+    Private *mPriv;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(Account::Features)
+
+} // Telepathy::Client
+} // Telepathy
+
+#endif
diff --git a/TelepathyQt4/Makefile.am b/TelepathyQt4/Makefile.am
index 906ab6c..00911d5 100644
--- a/TelepathyQt4/Makefile.am
+++ b/TelepathyQt4/Makefile.am
@@ -36,6 +36,7 @@ libtelepathy_qt4_la_DEPENDENCIES = Makefile.am
 
 libtelepathy_qt4_la_SOURCES = \
     Client/account.cpp \
+    Client/account-internal.h \
     Client/account-manager.cpp \
     Client/account-manager-internal.h \
     Client/channel.cpp \
@@ -78,6 +79,8 @@ nodist_libtelepathy_qt4_la_SOURCES = \
     _gen/cli-properties-body.hpp \
     _gen/cli-properties.moc.hpp \
     _gen/types-body.hpp \
+    Client/_gen/account.moc.hpp \
+    Client/_gen/account-internal.moc.hpp \
     Client/_gen/account-manager.moc.hpp \
     Client/_gen/account-manager-internal.moc.hpp \
     Client/_gen/channel.moc.hpp \
-- 
1.5.6.5




More information about the Telepathy-commits mailing list