/** * This file is part of TelepathyQt * * @copyright Copyright (C) 2008 Collabora Ltd. * @copyright Copyright (C) 2008 Nokia Corporation * @license LGPL 2.1 * * 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 #include "TelepathyQt/_gen/pending-account.moc.hpp" #include "TelepathyQt/debug-internal.h" #include #include #include #include #include namespace Tp { struct TP_QT_NO_EXPORT PendingAccount::Private { AccountPtr account; }; /** * \class PendingAccount * \ingroup clientaccount * \headerfile TelepathyQt/pending-account.h * * \brief The PendingAccount class represents the parameters of and the reply to * an asynchronous account request. * * Instances of this class cannot be constructed directly; the only way to get * one is via AccountManager. * * See \ref async_model */ /** * Construct a new PendingAccount object. * * \param manager AccountManager to use. * \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. * \param properties An optional map from fully qualified D-Bus property * names such as "org.freedesktop.Telepathy.Account.Enabled" * to their values. */ PendingAccount::PendingAccount(const AccountManagerPtr &manager, const QString &connectionManager, const QString &protocol, const QString &displayName, const QVariantMap ¶meters, const QVariantMap &properties) : PendingOperation(manager), mPriv(new Private) { QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher( manager->baseInterface()->CreateAccount(connectionManager, protocol, displayName, parameters, properties), this); connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), SLOT(onCallFinished(QDBusPendingCallWatcher*))); } /** * Class destructor. */ PendingAccount::~PendingAccount() { delete mPriv; } /** * Return the account manager through which the request was made. * * \return A pointer to the AccountManager object. */ AccountManagerPtr PendingAccount::manager() const { return AccountManagerPtr(qobject_cast((AccountManager*) object().data())); } /** * Return the newly created account. * * \return A pointer to an Account object, or a null AccountPtr if an error occurred. */ AccountPtr PendingAccount::account() const { if (!isFinished()) { warning() << "PendingAccount::account called before finished, returning 0"; return AccountPtr(); } else if (!isValid()) { warning() << "PendingAccount::account called when not valid, returning 0"; return AccountPtr(); } return mPriv->account; } void PendingAccount::onCallFinished(QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if (!reply.isError()) { QString objectPath = reply.value().path(); debug() << "Got reply to AccountManager.CreateAccount - object path:" << objectPath; PendingReady *readyOp = manager()->accountFactory()->proxy(manager()->busName(), objectPath, manager()->connectionFactory(), manager()->channelFactory(), manager()->contactFactory()); mPriv->account = AccountPtr::qObjectCast(readyOp->proxy()); connect(readyOp, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onAccountBuilt(Tp::PendingOperation*))); } else { debug().nospace() << "CreateAccount failed: " << reply.error().name() << ": " << reply.error().message(); setFinishedWithError(reply.error()); } watcher->deleteLater(); } void PendingAccount::onAccountBuilt(Tp::PendingOperation *op) { Q_ASSERT(op->isFinished()); if (op->isError()) { warning() << "Making account ready using the factory failed:" << op->errorName() << op->errorMessage(); setFinishedWithError(op->errorName(), op->errorMessage()); } else { // AM is stateless, so the only way for it to become invalid is in the introspection phase, // and a PendingAccount should never be created if AM introspection hasn't succeeded Q_ASSERT(!manager().isNull() && manager()->isValid()); if (manager()->allAccounts().contains(mPriv->account)) { setFinished(); debug() << "New account" << mPriv->account->objectPath() << "built"; } else { // Have to wait for the AM to pick up the change and signal it so the world can be // assumed to be ~round when we finish connect(manager().data(), SIGNAL(newAccount(Tp::AccountPtr)), SLOT(onNewAccount(Tp::AccountPtr))); } } } void PendingAccount::onNewAccount(const AccountPtr &account) { if (account != mPriv->account) { return; } debug() << "Account" << account->objectPath() << "added to AM, finishing PendingAccount"; setFinished(); } } // Tp