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

Andre Moreira Magalhaes (andrunko) andre.magalhaes at collabora.co.uk
Wed Jan 7 13:14:39 PST 2009


---
 TelepathyQt4/Client/account-manager-internal.h |   85 +++++
 TelepathyQt4/Client/account-manager.cpp        |  440 ++++++++++++++++++++++++
 TelepathyQt4/Client/account-manager.h          |   97 +++++-
 TelepathyQt4/Makefile.am                       |    2 +
 4 files changed, 607 insertions(+), 17 deletions(-)
 create mode 100644 TelepathyQt4/Client/account-manager-internal.h

diff --git a/TelepathyQt4/Client/account-manager-internal.h b/TelepathyQt4/Client/account-manager-internal.h
new file mode 100644
index 0000000..82457b0
--- /dev/null
+++ b/TelepathyQt4/Client/account-manager-internal.h
@@ -0,0 +1,85 @@
+/*
+ * 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_manager_internal_h_HEADER_GUARD_
+#define _TelepathyQt4_cli_account_manager_internal_h_HEADER_GUARD_
+
+#include <TelepathyQt4/Client/PendingOperation>
+
+#include <QQueue>
+#include <QSet>
+#include <QStringList>
+
+namespace Telepathy
+{
+namespace Client
+{
+
+class AccountManager;
+class AccountManagerInterface;
+
+class AccountManager::Private : public QObject
+{
+    Q_OBJECT
+
+public:
+    Private(AccountManager *parent);
+    ~Private();
+
+    void callGetAll();
+    void setAccountPaths(QSet<QDBusObjectPath> &set, const QVariant &variant);
+
+    class PendingReady;
+
+    AccountManagerInterface *baseInterface;
+    bool ready;
+    PendingReady *pendingReady;
+    QQueue<void (Private::*)()> introspectQueue;
+    QStringList interfaces;
+    AccountManager::Features features;
+    QSet<QDBusObjectPath> validAccountPaths;
+    QSet<QDBusObjectPath> invalidAccountPaths;
+
+Q_SIGNALS:
+    void accountCreated(const QDBusObjectPath &path);
+    void accountRemoved(const QDBusObjectPath &path);
+    void accountValidityChanged(const QDBusObjectPath &path, bool valid);
+
+private Q_SLOTS:
+    void onGetAllAccountManagerReturn(QDBusPendingCallWatcher *);
+    void onAccountValidityChanged(const QDBusObjectPath &, bool);
+    void onAccountRemoved(const QDBusObjectPath &);
+    void continueIntrospection();
+};
+
+class AccountManager::Private::PendingReady : public PendingOperation
+{
+    // AccountManager::Private is a friend so it can call finished() etc.
+    friend class AccountManager::Private;
+
+public:
+    PendingReady(AccountManager *parent);
+};
+
+} // Telepathy::Client
+} // Telepathy
+
+#endif
diff --git a/TelepathyQt4/Client/account-manager.cpp b/TelepathyQt4/Client/account-manager.cpp
index d2901b8..38ac8cb 100644
--- a/TelepathyQt4/Client/account-manager.cpp
+++ b/TelepathyQt4/Client/account-manager.cpp
@@ -20,6 +20,446 @@
  */
 
 #include <TelepathyQt4/Client/AccountManager>
+#include "account-manager-internal.h"
+
+#include "account-manager.moc.hpp"
+#include "account-manager-internal.moc.hpp"
 
 #include "TelepathyQt4/_gen/cli-account-manager.moc.hpp"
 #include "TelepathyQt4/_gen/cli-account-manager-body.hpp"
+#include "TelepathyQt4/debug-internal.h"
+
+#include <TelepathyQt4/Client/PendingSuccess>
+#include <TelepathyQt4/Constants>
+
+#include <QQueue>
+#include <QSet>
+#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.
+ */
+
+/**
+ * \defgroup clientaccount Account and Account Manager proxies
+ * \ingroup clientsideproxies
+ *
+ * Proxy objects representing the Telepathy Account Manager and the Accounts
+ * that it manages, and their optional interfaces.
+ */
+
+namespace Telepathy
+{
+namespace Client
+{
+
+AccountManager::Private::PendingReady::PendingReady(AccountManager *parent)
+    : PendingOperation(parent)
+{
+}
+
+AccountManager::Private::Private(AccountManager *parent)
+    : QObject(parent),
+      baseInterface(new AccountManagerInterface(parent->dbusConnection(),
+                            parent->busName(), parent->objectPath(), parent)),
+      ready(false),
+      pendingReady(0),
+      introspectQueue(),
+      features(0)
+{
+    debug() << "Creating new AccountManager:" << parent->busName();
+
+    connect(baseInterface,
+            SIGNAL(AccountValidityChanged(const QDBusObjectPath &, bool)),
+            SLOT(onAccountValidityChanged(const QDBusObjectPath &, bool)));
+    connect(baseInterface,
+            SIGNAL(AccountRemoved(const QDBusObjectPath &)),
+            SLOT(onAccountRemoved(const QDBusObjectPath &)));
+
+    introspectQueue.enqueue(&Private::callGetAll);
+    QTimer::singleShot(0, this, SLOT(continueIntrospection()));
+}
+
+AccountManager::Private::~Private()
+{
+}
+
+void AccountManager::Private::callGetAll()
+{
+    debug() << "Calling Properties::GetAll(AccountManager)";
+    AccountManager *am = static_cast<AccountManager *>(parent());
+    QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(
+            am->propertiesInterface()->GetAll(
+                TELEPATHY_INTERFACE_ACCOUNT_MANAGER), this);
+    connect(watcher,
+            SIGNAL(finished(QDBusPendingCallWatcher *)),
+            SLOT(onGetAllAccountManagerReturn(QDBusPendingCallWatcher *)));
+}
+
+void AccountManager::Private::setAccountPaths(QSet<QDBusObjectPath> &set,
+        const QVariant &variant)
+{
+    Telepathy::ObjectPathList paths = qdbus_cast<Telepathy::ObjectPathList>(variant);
+
+    if (paths.size() == 0) {
+        // maybe the AccountManager is buggy, like Mission Control
+        // 5.0.beta45, and returns an array of strings rather than
+        // an array of object paths?
+
+        QStringList wronglyTypedPaths = qdbus_cast<QStringList>(variant);
+        if (wronglyTypedPaths.size() > 0) {
+            warning() << "AccountManager returned wrong type "
+                "(expected 'ao', got 'as'); working around it";
+            Q_FOREACH (QString path, wronglyTypedPaths) {
+                paths << QDBusObjectPath(path);
+            }
+        }
+    }
+
+    Q_FOREACH (const QDBusObjectPath &path, paths) {
+        set << path;
+    }
+}
+
+void AccountManager::Private::onGetAllAccountManagerReturn(
+        QDBusPendingCallWatcher *watcher)
+{
+    QDBusPendingReply<QVariantMap> reply = *watcher;
+    QVariantMap props;
+
+    if (!reply.isError()) {
+        debug() << "Got reply to Properties.GetAll(AccountManager)";
+        props = reply.value();
+    } else {
+        warning().nospace() <<
+            "GetAll(AccountManager) failed: " <<
+            reply.error().name() << ": " << reply.error().message();
+    }
+
+    if (props.contains("Interfaces")) {
+        interfaces = qdbus_cast<QStringList>(props["Interfaces"]);
+    }
+
+    if (props.contains("ValidAccounts")) {
+        setAccountPaths(validAccountPaths,
+                props["ValidAccounts"]);
+    }
+
+    if (props.contains("InvalidAccounts")) {
+        setAccountPaths(invalidAccountPaths,
+                props["InvalidAccounts"]);
+    }
+
+    continueIntrospection();
+}
+
+void AccountManager::Private::onAccountValidityChanged(const QDBusObjectPath &path,
+        bool nowValid)
+{
+    bool newAccount = false;
+
+    if (!validAccountPaths.contains(path) && !invalidAccountPaths.contains(path)) {
+        newAccount = true;
+    }
+
+    if (nowValid) {
+        debug() << "Account created or became valid:" << path.path();
+        invalidAccountPaths.remove(path);
+        validAccountPaths.insert(path);
+    }
+    else {
+        debug() << "Account became invalid:" << path.path();
+        validAccountPaths.remove(path);
+        invalidAccountPaths.insert(path);
+    }
+
+    if (newAccount) {
+        Q_EMIT accountCreated(path);
+        // if the newly created account is invalid (shouldn't be the case)
+        // emit also accountValidityChanged indicating this
+        if (!nowValid) {
+            Q_EMIT accountValidityChanged(path, nowValid);
+        }
+    }
+    else {
+        Q_EMIT accountValidityChanged(path, nowValid);
+    }
+}
+
+void AccountManager::Private::onAccountRemoved(const QDBusObjectPath &path)
+{
+    debug() << "Account removed:" << path.path();
+    validAccountPaths.remove(path);
+    invalidAccountPaths.remove(path);
+
+    Q_EMIT accountRemoved(path);
+}
+
+void AccountManager::Private::continueIntrospection()
+{
+    if (!ready) {
+        if (introspectQueue.isEmpty()) {
+            debug() << "AccountManager is ready";
+            ready = true;
+
+            if (pendingReady) {
+                pendingReady->setFinished();
+                // it will delete itself later
+                pendingReady = 0;
+            }
+        }
+        else {
+            (this->*(introspectQueue.dequeue()))();
+        }
+    }
+}
+
+/**
+ * \class AccountManager
+ * \ingroup clientaccount
+ * \headerfile TelepathyQt4/Client/account-manager.h> <TelepathyQt4/Client/AccountManager>
+ *
+ * Object representing a Telepathy account manager.
+ *
+ * \param parent Object parent.
+ */
+AccountManager::AccountManager(QObject* parent)
+    : StatelessDBusProxy(QDBusConnection::sessionBus(),
+            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
+            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
+      mPriv(new Private(this))
+{
+    init();
+}
+
+/**
+ * \class AccountManager
+ * \ingroup clientaccount
+ * \headerfile TelepathyQt4/Client/account-manager.h> <TelepathyQt4/Client/AccountManager>
+ *
+ * Object representing a Telepathy account manager.
+ *
+ * \param bus QDBusConnection to use.
+ * \param parent Object parent.
+ */
+AccountManager::AccountManager(const QDBusConnection& bus,
+        QObject* parent)
+    : StatelessDBusProxy(bus,
+            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_BUS_NAME),
+            QLatin1String(TELEPATHY_ACCOUNT_MANAGER_OBJECT_PATH), parent),
+      mPriv(new Private(this))
+{
+    init();
+}
+
+/**
+ * Class destructor.
+ */
+AccountManager::~AccountManager()
+{
+    delete mPriv;
+}
+
+QStringList AccountManager::interfaces() const
+{
+    return mPriv->interfaces;
+}
+
+/**
+ * \fn DBus::propertiesInterface *AccountManager::propertiesInterface() const
+ *
+ * Convenience function for getting a Properties interface proxy. The
+ * AccountManager interface relies on properties, so this interface is
+ * always assumed to be present.
+ */
+
+/**
+ * Return a list of QDBusObjectPath for all valid accounts.
+ *
+ * \return A list of QDBusObjectPath.
+ */
+Telepathy::ObjectPathList AccountManager::validAccountPaths() const
+{
+    Telepathy::ObjectPathList result;
+    result.append(mPriv->validAccountPaths.values());
+    return result;
+}
+
+/**
+ * Return a list of QDBusObjectPath for all invalid accounts.
+ *
+ * \return A list of QDBusObjectPath.
+ */
+Telepathy::ObjectPathList AccountManager::invalidAccountPaths() const
+{
+    Telepathy::ObjectPathList result;
+    result.append(mPriv->invalidAccountPaths.values());
+    return result;
+}
+
+/**
+ * Return a list of QDBusObjectPath for all accounts.
+ *
+ * \return A list of QDBusObjectPath.
+ */
+Telepathy::ObjectPathList AccountManager::allAccountPaths() const
+{
+    ObjectPathList result;
+    result.append(mPriv->validAccountPaths.values());
+    result.append(mPriv->invalidAccountPaths.values());
+    return result;
+}
+
+#if 0
+/**
+ * Return a list of pending operations for all valid accounts from which
+ * Accounts can be retrieved if it succeeds.
+ *
+ * Note that the account objects won't be cached by account manager, and
+ * should be done by the application itself.
+ *
+ * \return A list of PendingAccount which each one will emit
+ *         PendingAccount::finished when it has finished or failed creating the
+ *         account object.
+ */
+PendingAccounts *AccountManager::validAccounts() const
+{
+    return 0;
+}
+
+/**
+ * Return a list of pending operations for all invalid accounts from which
+ * Accounts can be retrieved if it succeeds.
+ *
+ * Note that the account objects won't be cached by account manager, and
+ * should be done by the application itself.
+ *
+ * \return A list of PendingAccount which each one will emit
+ *         PendingAccount::finished when it has finished or failed creating the
+ *         account object.
+ */
+PendingAccounts *AccountManager::invalidAccounts() const
+{
+    return 0;
+}
+
+/**
+ * Return a list of pending operations for all accounts from which
+ * Accounts can be retrieved if it succeeds.
+ *
+ * Note that the account objects won't be cached by account manager, and
+ * should be done by the application itself.
+ *
+ * \return A list of PendingAccount which each one will emit
+ *         PendingAccount::finished when it has finished or failed creating the
+ *         account object.
+ */
+PendingAccounts *AccountManager::allAccounts() const
+{
+    return 0;
+}
+
+PendingAccount *AccountManager::accountForPath(const QString &path) const
+{
+    return 0;
+}
+
+/**
+ * Create an account with the given parameters.
+ *
+ * Return a pending operation representing the account which will succeed
+ * when the account has been created or fail if an error occurred.
+ *
+ * \param connectionManager Name of the connection manager to create the account for.
+ * \param protocol Name of the protocol to create the account for.
+ * \param displayName Account display name.
+ * \param parameters Account parameters.
+ * \return A PendingOperation which will emit PendingAccount::finished
+ *         when the account has been created of failed its creation process.
+ */
+PendingAccount *AccountManager::createAccount(const QString &connectionManager,
+        const QString &protocol, const QString &displayName,
+        const QVariantMap &parameters)
+{
+    return 0;
+}
+#endif
+
+/**
+ * Return whether this object has finished its initial setup.
+ *
+ * This is mostly useful as a sanity check, in code that shouldn't be run
+ * until the object is ready. To wait for the object to be ready, call
+ * becomeReady() and connect to the finished signal on the result.
+ *
+ * \param features Which features should be tested.
+ * \return \c true if the object has finished initial setup.
+ */
+bool AccountManager::isReady(Features features) const
+{
+    return mPriv->ready
+        && ((mPriv->features & features) == features);
+}
+
+/**
+ * Return a pending operation which will succeed when this object finishes
+ * its initial setup, or will fail if a fatal error occurs during this
+ * initial setup.
+ *
+ * \param features Which features should be tested.
+ * \return A PendingOperation which will emit PendingOperation::finished
+ *         when this object has finished or failed its initial setup.
+ */
+PendingOperation *AccountManager::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 AccountManagerInterface for this AccountManager. 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 AccountManagerInterface for this
+ *         AccountManager.
+ */
+AccountManagerInterface *AccountManager::baseInterface() const
+{
+    return mPriv->baseInterface;
+}
+
+void AccountManager::init()
+{
+    connect(mPriv,
+            SIGNAL(accountCreated(const QDBusObjectPath &)),
+            SIGNAL(accountCreated(const QDBusObjectPath &)));
+    connect(mPriv,
+            SIGNAL(accountRemoved(const QDBusObjectPath &)),
+            SIGNAL(accountRemoved(const QDBusObjectPath &)));
+    connect(mPriv,
+            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)),
+            SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)));
+}
+
+} // Telepathy::Client
+} // Telepathy
diff --git a/TelepathyQt4/Client/account-manager.h b/TelepathyQt4/Client/account-manager.h
index 9ec6c2e..8a57951 100644
--- a/TelepathyQt4/Client/account-manager.h
+++ b/TelepathyQt4/Client/account-manager.h
@@ -26,24 +26,87 @@
 #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-manager.h>
 
-/**
- * \defgroup clientaccount Account and Account Manager proxies
- * \ingroup clientsideproxies
- *
- * ...
- */
+#include <TelepathyQt4/Client/DBus>
+#include <TelepathyQt4/Client/DBusProxy>
+#include <TelepathyQt4/Client/OptionalInterfaceFactory>
 
-#include <TelepathyQt4/_gen/cli-account-manager.h>
+#include <QString>
+#include <QVariantMap>
+
+namespace Telepathy
+{
+namespace Client
+{
+
+class PendingAccount;
+class PendingAccounts;
+class PendingOperation;
+
+class AccountManager : public StatelessDBusProxy,
+        private OptionalInterfaceFactory
+{
+    Q_OBJECT
+
+public:
+    enum Feature {
+        _Padding = 0xFFFFFFFF
+    };
+    Q_DECLARE_FLAGS(Features, Feature)
+
+    AccountManager(QObject *parent = 0);
+    AccountManager(const QDBusConnection &bus, QObject *parent = 0);
+
+    virtual ~AccountManager();
+
+    QStringList interfaces() const;
+
+    inline DBus::PropertiesInterface *propertiesInterface() const
+    {
+        return OptionalInterfaceFactory::interface<DBus::PropertiesInterface>(
+                *baseInterface());
+    }
+
+    Telepathy::ObjectPathList validAccountPaths() const;
+    Telepathy::ObjectPathList invalidAccountPaths() const;
+    Telepathy::ObjectPathList allAccountPaths() const;
+
+    PendingAccounts *validAccounts() const;
+    PendingAccounts *invalidAccounts() const;
+    PendingAccounts *allAccounts() const;
+
+    PendingAccount *accountForPath(const QString &path) const;
+
+    PendingAccount *createAccount(const QString &connectionManager,
+            const QString &protocol, const QString &displayName,
+            const QVariantMap &parameters);
+
+    // TODO: enabledAccounts(), accountsByProtocol(), ... ?
+
+    bool isReady(Features features = 0) const;
+
+    PendingOperation *becomeReady(Features features = 0);
+
+Q_SIGNALS:
+    void accountCreated(const QDBusObjectPath &path);
+    void accountRemoved(const QDBusObjectPath &path);
+    void accountValidityChanged(const QDBusObjectPath &path, bool valid);
+
+protected:
+    AccountManagerInterface *baseInterface() const;
+
+private:
+    void init();
+
+    struct Private;
+    friend struct Private;
+    Private *mPriv;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(AccountManager::Features)
+
+} // Telepathy::Client
+} // Telepathy
 
 #endif
diff --git a/TelepathyQt4/Makefile.am b/TelepathyQt4/Makefile.am
index 2cc89bd..78d0e71 100644
--- a/TelepathyQt4/Makefile.am
+++ b/TelepathyQt4/Makefile.am
@@ -75,6 +75,8 @@ nodist_libtelepathy_qt4_la_SOURCES = \
     _gen/cli-properties-body.hpp \
     _gen/cli-properties.moc.hpp \
     _gen/types-body.hpp \
+    Client/account-manager.moc.hpp \
+    Client/account-manager-internal.moc.hpp \
     Client/channel.moc.hpp \
     Client/connection.moc.hpp \
     Client/connection-manager.moc.hpp \
-- 
1.5.6.5




More information about the Telepathy-commits mailing list