diff options
Diffstat (limited to 'TelepathyQt/channel-factory.cpp')
-rw-r--r-- | TelepathyQt/channel-factory.cpp | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/TelepathyQt/channel-factory.cpp b/TelepathyQt/channel-factory.cpp new file mode 100644 index 00000000..10bf4cbd --- /dev/null +++ b/TelepathyQt/channel-factory.cpp @@ -0,0 +1,529 @@ +/** + * This file is part of TelepathyQt + * + * @copyright Copyright (C) 2009-2010 Collabora Ltd. <http://www.collabora.co.uk/> + * @copyright Copyright (C) 2009-2010 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 <TelepathyQt/ChannelFactory> + +#include "TelepathyQt/_gen/channel-factory.moc.hpp" + +#include "TelepathyQt/_gen/future-constants.h" + +#include "TelepathyQt/debug-internal.h" + +#include <TelepathyQt/Channel> +#include <TelepathyQt/ChannelClassSpec> +#include <TelepathyQt/ChannelClassFeatures> +#include <TelepathyQt/Connection> +#include <TelepathyQt/Constants> +#include <TelepathyQt/ContactSearchChannel> +#include <TelepathyQt/FileTransferChannel> +#include <TelepathyQt/IncomingFileTransferChannel> +#include <TelepathyQt/IncomingStreamTubeChannel> +#include <TelepathyQt/OutgoingFileTransferChannel> +#include <TelepathyQt/OutgoingStreamTubeChannel> +#include <TelepathyQt/RoomListChannel> +#include <TelepathyQt/StreamTubeChannel> +#include <TelepathyQt/StreamedMediaChannel> +#include <TelepathyQt/TextChannel> + +namespace Tp +{ + +struct TP_QT_NO_EXPORT ChannelFactory::Private +{ + Private(); + + QList<ChannelClassFeatures> features; + + typedef QPair<ChannelClassSpec, ConstructorConstPtr> CtorPair; + QList<CtorPair> ctors; +}; + +ChannelFactory::Private::Private() +{ +} + +/** + * \class ChannelFactory + * \ingroup utils + * \headerfile TelepathyQt/channel-factory.h <TelepathyQt/ChannelFactory> + * + * \brief The ChannelFactory class is responsible for constructing Channel + * objects according to application-defined settings. + */ + +/** + * Create a new ChannelFactory object. + * + * The returned factory will construct channel subclasses provided by TelepathyQt as appropriate + * for the channel immutable properties, but not make any features ready. + * + * \param bus The QDBusConnection the proxies constructed using this factory should use. + * \return An ChannelFactoryPtr pointing to the newly created factory. + */ +ChannelFactoryPtr ChannelFactory::create(const QDBusConnection &bus) +{ + return ChannelFactoryPtr(new ChannelFactory(bus)); +} + +/** + * Construct a new ChannelFactory object. + * + * The constructed factory will construct channel subclasses provided by TelepathyQt as appropriate + * for the channel immutable properties, but not make any features ready. + * + * \param bus The QDBusConnection the proxies constructed using this factory should use. + */ +ChannelFactory::ChannelFactory(const QDBusConnection &bus) + : DBusProxyFactory(bus), mPriv(new Private) +{ + setSubclassForTextChats<TextChannel>(); + setSubclassForTextChatrooms<TextChannel>(); + setSubclassForStreamedMediaCalls<StreamedMediaChannel>(); + setSubclassForRoomLists<RoomListChannel>(); + setSubclassForIncomingFileTransfers<IncomingFileTransferChannel>(); + setSubclassForOutgoingFileTransfers<OutgoingFileTransferChannel>(); + setSubclassForIncomingStreamTubes<IncomingStreamTubeChannel>(); + setSubclassForOutgoingStreamTubes<OutgoingStreamTubeChannel>(); + setSubclassForIncomingRoomStreamTubes<IncomingStreamTubeChannel>(); + setSubclassForOutgoingRoomStreamTubes<OutgoingStreamTubeChannel>(); + setSubclassForContactSearches<ContactSearchChannel>(); + setFallbackSubclass<Channel>(); +} + +/** + * Class destructor. + */ +ChannelFactory::~ChannelFactory() +{ + delete mPriv; +} + +Features ChannelFactory::featuresForTextChats(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::textChat(additionalProps)); +} + +void ChannelFactory::addFeaturesForTextChats(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::textChat(additionalProps), features); + addFeaturesFor(ChannelClassSpec::unnamedTextChat(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForTextChats( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::textChat(additionalProps)); +} + +void ChannelFactory::setConstructorForTextChats(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::textChat(additionalProps), ctor); + setConstructorFor(ChannelClassSpec::unnamedTextChat(additionalProps), ctor); +} + +Features ChannelFactory::featuresForTextChatrooms(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::textChatroom(additionalProps)); +} + +void ChannelFactory::addFeaturesForTextChatrooms(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::textChatroom(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForTextChatrooms( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::textChatroom(additionalProps)); +} + +void ChannelFactory::setConstructorForTextChatrooms(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::textChatroom(additionalProps), ctor); +} + +Features ChannelFactory::featuresForStreamedMediaCalls(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::streamedMediaCall(additionalProps)); +} + +void ChannelFactory::addFeaturesForStreamedMediaCalls(const Features &features, + const QVariantMap &additionalProps) +{ + ChannelClassSpec smSpec = ChannelClassSpec::streamedMediaCall(additionalProps); + ChannelClassSpec unnamedSMSpec = ChannelClassSpec::unnamedStreamedMediaCall(additionalProps); + + addFeaturesFor(smSpec, features); + addFeaturesFor(unnamedSMSpec, features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForStreamedMediaCalls( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::streamedMediaCall(additionalProps)); +} + +void ChannelFactory::setConstructorForStreamedMediaCalls(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + ChannelClassSpec smSpec = ChannelClassSpec::streamedMediaCall(additionalProps); + ChannelClassSpec unnamedSMSpec = ChannelClassSpec::unnamedStreamedMediaCall(additionalProps); + + setConstructorFor(smSpec, ctor); + setConstructorFor(unnamedSMSpec, ctor); +} + +Features ChannelFactory::featuresForRoomLists(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::roomList(additionalProps)); +} + +void ChannelFactory::addFeaturesForRoomLists(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::roomList(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForRoomLists( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::roomList(additionalProps)); +} + +void ChannelFactory::setConstructorForRoomLists(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::roomList(additionalProps), ctor); +} + +Features ChannelFactory::featuresForOutgoingFileTransfers(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::outgoingFileTransfer(additionalProps)); +} + +void ChannelFactory::addFeaturesForOutgoingFileTransfers(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::outgoingFileTransfer(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForOutgoingFileTransfers( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::outgoingFileTransfer(additionalProps)); +} + +void ChannelFactory::setConstructorForOutgoingFileTransfers(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::outgoingFileTransfer(additionalProps), ctor); +} + +Features ChannelFactory::featuresForIncomingFileTransfers(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::incomingFileTransfer(additionalProps)); +} + +void ChannelFactory::addFeaturesForIncomingFileTransfers(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::incomingFileTransfer(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForIncomingFileTransfers( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::incomingFileTransfer(additionalProps)); +} + +void ChannelFactory::setConstructorForIncomingFileTransfers(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::incomingFileTransfer(additionalProps), ctor); +} + +Features ChannelFactory::featuresForOutgoingStreamTubes(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::outgoingStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::addFeaturesForOutgoingStreamTubes(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::outgoingStreamTube(QString(), additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForOutgoingStreamTubes( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::outgoingStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::setConstructorForOutgoingStreamTubes(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::outgoingStreamTube(QString(), additionalProps), ctor); +} + +Features ChannelFactory::featuresForIncomingStreamTubes(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::incomingStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::addFeaturesForIncomingStreamTubes(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::incomingStreamTube(QString(), additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForIncomingStreamTubes( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::incomingStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::setConstructorForIncomingStreamTubes(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::incomingStreamTube(QString(), additionalProps), ctor); +} + +Features ChannelFactory::featuresForOutgoingRoomStreamTubes(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::outgoingRoomStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::addFeaturesForOutgoingRoomStreamTubes(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::outgoingRoomStreamTube(QString(), additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForOutgoingRoomStreamTubes( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::outgoingRoomStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::setConstructorForOutgoingRoomStreamTubes(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::outgoingRoomStreamTube(QString(), additionalProps), ctor); +} + +Features ChannelFactory::featuresForIncomingRoomStreamTubes(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::incomingRoomStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::addFeaturesForIncomingRoomStreamTubes(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::incomingRoomStreamTube(QString(), additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForIncomingRoomStreamTubes( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::incomingRoomStreamTube(QString(), additionalProps)); +} + +void ChannelFactory::setConstructorForIncomingRoomStreamTubes(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::incomingRoomStreamTube(QString(), additionalProps), ctor); +} + +Features ChannelFactory::featuresForContactSearches(const QVariantMap &additionalProps) const +{ + return featuresFor(ChannelClassSpec::contactSearch(additionalProps)); +} + +void ChannelFactory::addFeaturesForContactSearches(const Features &features, + const QVariantMap &additionalProps) +{ + addFeaturesFor(ChannelClassSpec::contactSearch(additionalProps), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorForContactSearches( + const QVariantMap &additionalProps) const +{ + return constructorFor(ChannelClassSpec::contactSearch(additionalProps)); +} + +void ChannelFactory::setConstructorForContactSearches(const ConstructorConstPtr &ctor, + const QVariantMap &additionalProps) +{ + setConstructorFor(ChannelClassSpec::contactSearch(additionalProps), ctor); +} + +Features ChannelFactory::commonFeatures() const +{ + return featuresFor(ChannelClassSpec()); +} + +void ChannelFactory::addCommonFeatures(const Features &features) +{ + addFeaturesFor(ChannelClassSpec(), features); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::fallbackConstructor() const +{ + return constructorFor(ChannelClassSpec()); +} + +void ChannelFactory::setFallbackConstructor(const ConstructorConstPtr &ctor) +{ + setConstructorFor(ChannelClassSpec(), ctor); +} + +Features ChannelFactory::featuresFor(const ChannelClassSpec &channelClass) const +{ + Features features; + + foreach (const ChannelClassFeatures &pair, mPriv->features) { + if (pair.first.isSubsetOf(channelClass)) { + features.unite(pair.second); + } + } + + return features; +} + +void ChannelFactory::addFeaturesFor(const ChannelClassSpec &channelClass, const Features &features) +{ + QList<ChannelClassFeatures>::iterator i; + for (i = mPriv->features.begin(); i != mPriv->features.end(); ++i) { + if (channelClass.allProperties().size() > i->first.allProperties().size()) { + break; + } + + if (i->first == channelClass) { + i->second.unite(features); + return; + } + } + + // We ran out of feature specifications (for the given size/specificity of a channel class) + // before finding a matching one, so let's create a new entry + mPriv->features.insert(i, qMakePair(channelClass, features)); +} + +ChannelFactory::ConstructorConstPtr ChannelFactory::constructorFor(const ChannelClassSpec &cc) const +{ + QList<Private::CtorPair>::iterator i; + for (i = mPriv->ctors.begin(); i != mPriv->ctors.end(); ++i) { + if (i->first.isSubsetOf(cc)) { + return i->second; + } + } + + // If this is reached, we didn't have a proper fallback constructor + Q_ASSERT(false); + return ConstructorConstPtr(); +} + +void ChannelFactory::setConstructorFor(const ChannelClassSpec &channelClass, + const ConstructorConstPtr &ctor) +{ + if (ctor.isNull()) { + warning().nospace() << "Tried to set a NULL ctor for ChannelClass(" + << channelClass.channelType() << ", " << channelClass.targetHandleType() << ", " + << channelClass.allProperties().size() << "props in total)"; + return; + } + + QList<Private::CtorPair>::iterator i; + for (i = mPriv->ctors.begin(); i != mPriv->ctors.end(); ++i) { + if (channelClass.allProperties().size() > i->first.allProperties().size()) { + break; + } + + if (i->first == channelClass) { + i->second = ctor; + return; + } + } + + // We ran out of constructors (for the given size/specificity of a channel class) + // before finding a matching one, so let's create a new entry + mPriv->ctors.insert(i, qMakePair(channelClass, ctor)); +} + +/** + * Constructs a Channel proxy and begins making it ready. + * + * If a valid proxy already exists in the factory cache for the given combination of \a busName and + * \a objectPath, it is returned instead. All newly created proxies are automatically cached until + * they're either DBusProxy::invalidated() or the last reference to them outside the factory has + * been dropped. + * + * The proxy can be accessed immediately after this function returns using PendingReady::proxy(). + * + * \param connection Proxy for the owning connection of the channel. + * \param channelPath The object path of the channel. + * \param immutableProperties The immutable properties of the channel. + * \return A PendingReady operation with the proxy in PendingReady::proxy(). + */ +PendingReady *ChannelFactory::proxy(const ConnectionPtr &connection, const QString &channelPath, + const QVariantMap &immutableProperties) const +{ + DBusProxyPtr proxy = cachedProxy(connection->busName(), channelPath); + if (proxy.isNull()) { + proxy = constructorFor(ChannelClassSpec(immutableProperties))->construct(connection, + channelPath, immutableProperties); + } + + return nowHaveProxy(proxy); +} + +/** + * Transforms well-known names to the corresponding unique names, as is appropriate for Channel + * + * \param uniqueOrWellKnown The name to transform. + * \return The unique name corresponding to \a uniqueOrWellKnown (which may be it itself). + */ +QString ChannelFactory::finalBusNameFrom(const QString &uniqueOrWellKnown) const +{ + return StatefulDBusProxy::uniqueNameFrom(dbusConnection(), uniqueOrWellKnown); +} + +/** + * Return features as configured for the channel class given by the Channel::immutableProperties() + * of \a proxy. + * + * \param proxy The Channel proxy to determine the features for. + * \return A list of Feature objects. + */ +Features ChannelFactory::featuresFor(const DBusProxyPtr &proxy) const +{ + ChannelPtr chan = ChannelPtr::qObjectCast(proxy); + Q_ASSERT(!chan.isNull()); + + return featuresFor(ChannelClassSpec(chan->immutableProperties())); +} + +} // Tp |