summaryrefslogtreecommitdiff
path: root/qt4/TelepathyQt4/profile-manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt4/TelepathyQt4/profile-manager.cpp')
-rw-r--r--qt4/TelepathyQt4/profile-manager.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/qt4/TelepathyQt4/profile-manager.cpp b/qt4/TelepathyQt4/profile-manager.cpp
new file mode 100644
index 000000000..4c283f478
--- /dev/null
+++ b/qt4/TelepathyQt4/profile-manager.cpp
@@ -0,0 +1,332 @@
+/**
+ * This file is part of TelepathyQt4
+ *
+ * @copyright Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+ * @copyright Copyright (C) 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 <TelepathyQt4/ProfileManager>
+
+#include "TelepathyQt4/_gen/profile-manager.moc.hpp"
+#include "TelepathyQt4/debug-internal.h"
+
+#include <TelepathyQt4/ConnectionManager>
+#include <TelepathyQt4/PendingComposite>
+#include <TelepathyQt4/PendingReady>
+#include <TelepathyQt4/PendingStringList>
+#include <TelepathyQt4/Profile>
+#include <TelepathyQt4/ReadinessHelper>
+
+#include <QFile>
+#include <QFileInfo>
+#include <QString>
+#include <QStringList>
+
+namespace Tp
+{
+
+struct TELEPATHY_QT4_NO_EXPORT ProfileManager::Private
+{
+ Private(ProfileManager *parent, const QDBusConnection &bus);
+
+ static void introspectMain(Private *self);
+ static void introspectFakeProfiles(Private *self);
+
+ ProfileManager *parent;
+ ReadinessHelper *readinessHelper;
+ QDBusConnection bus;
+ QHash<QString, ProfilePtr> profiles;
+ QList<ConnectionManagerPtr> cms;
+};
+
+ProfileManager::Private::Private(ProfileManager *parent, const QDBusConnection &bus)
+ : parent(parent),
+ readinessHelper(parent->readinessHelper()),
+ bus(bus)
+{
+ ReadinessHelper::Introspectables introspectables;
+
+ ReadinessHelper::Introspectable introspectableCore(
+ QSet<uint>() << 0, // makesSenseForStatuses
+ Features(), // dependsOnFeatures
+ QStringList(), // dependsOnInterfaces
+ (ReadinessHelper::IntrospectFunc) &Private::introspectMain,
+ this);
+ introspectables[FeatureCore] = introspectableCore;
+
+ ReadinessHelper::Introspectable introspectableFakeProfiles(
+ QSet<uint>() << 0, // makesSenseForStatuses
+ Features() << FeatureCore, // dependsOnFeatures
+ QStringList(), // dependsOnInterfaces
+ (ReadinessHelper::IntrospectFunc) &Private::introspectFakeProfiles,
+ this);
+ introspectables[FeatureFakeProfiles] = introspectableFakeProfiles;
+
+ readinessHelper->addIntrospectables(introspectables);
+}
+
+void ProfileManager::Private::introspectMain(ProfileManager::Private *self)
+{
+ QStringList searchDirs = Profile::searchDirs();
+
+ foreach (const QString searchDir, searchDirs) {
+ QDir dir(searchDir);
+ dir.setFilter(QDir::Files);
+
+ QFileInfoList list = dir.entryInfoList();
+ for (int i = 0; i < list.size(); ++i) {
+ QFileInfo fi = list.at(i);
+
+ if (fi.completeSuffix() != QLatin1String("profile")) {
+ continue;
+ }
+
+ QString fileName = fi.absoluteFilePath();
+ QString serviceName = fi.baseName();
+
+ if (self->profiles.contains(serviceName)) {
+ debug() << "Profile for service" << serviceName << "already "
+ "exists. Ignoring profile file:" << fileName;
+ continue;
+ }
+
+ ProfilePtr profile = Profile::createForFileName(fileName);
+ if (!profile->isValid()) {
+ continue;
+ }
+
+ if (profile->type() != QLatin1String("IM")) {
+ debug() << "Ignoring profile for service" << serviceName <<
+ ": type != IM. Profile file:" << fileName;
+ continue;
+ }
+
+ debug() << "Found profile for service" << serviceName <<
+ "- profile file:" << fileName;
+ self->profiles.insert(serviceName, profile);
+ }
+ }
+
+ self->readinessHelper->setIntrospectCompleted(FeatureCore, true);
+}
+
+void ProfileManager::Private::introspectFakeProfiles(ProfileManager::Private *self)
+{
+ PendingStringList *pendingCmNames = ConnectionManager::listNames(self->bus);
+ self->parent->connect(pendingCmNames,
+ SIGNAL(finished(Tp::PendingOperation *)),
+ SLOT(onCmNamesRetrieved(Tp::PendingOperation *)));
+}
+
+/**
+ * \class ProfileManager
+ * \headerfile TelepathyQt4/profile-manager.h <TelepathyQt4/ProfileManager>
+ *
+ * \brief The ProfileManager class provides helper methods to retrieve Profile
+ * objects.
+ */
+
+/**
+ * Feature representing the core that needs to become ready to make the ProfileManager
+ * object usable.
+ *
+ * Note that this feature must be enabled in order to use all ProfileManager methods.
+ *
+ * When calling isReady(), becomeReady(), this feature is implicitly added
+ * to the requested features.
+ */
+const Feature ProfileManager::FeatureCore = Feature(QLatin1String(ProfileManager::staticMetaObject.className()), 0, true);
+
+/**
+ * Enabling this feature will make ProfileManager create fake Profile objects to all protocols
+ * supported on the installed connection managers, even if they don't have .profile files installed
+ * making use of them.
+ *
+ * Fake profiles are identified by Profile::isFake() returning \c true.
+ *
+ * The fake profile will contain the following info:
+ * - Profile::type() will return "IM"
+ * - Profile::provider() will return an empty string
+ * - Profile::serviceName() will return cmName-protocolName
+ * - Profile::name() and Profile::protocolName() will return protocolName
+ * - Profile::iconName() will return "im-protocolName"
+ * - Profile::cmName() will return cmName
+ * - Profile::parameters() will return a list matching CM default parameters for protocol with name
+ * protocolName.
+ * - Profile::presences() will return an empty list and
+ * Profile::allowOtherPresences() will return \c true, meaning that CM
+ * presences should be used
+ * - Profile::unsupportedChannelClassSpecs() will return an empty list
+ *
+ * Where cmName and protocolName are the name of the connection manager and the name of the protocol
+ * for which this fake Profile is created, respectively.
+ */
+const Feature ProfileManager::FeatureFakeProfiles = Feature(QLatin1String(ProfileManager::staticMetaObject.className()), 1);
+
+/**
+ * Create a new ProfileManager object.
+ */
+ProfileManagerPtr ProfileManager::create(const QDBusConnection &bus)
+{
+ return ProfileManagerPtr(new ProfileManager(bus));
+}
+
+/**
+ * Construct a new ProfileManager object.
+ */
+ProfileManager::ProfileManager(const QDBusConnection &bus)
+ : Object(),
+ ReadyObject(this, FeatureCore),
+ mPriv(new Private(this, bus))
+{
+}
+
+/**
+ * Class destructor.
+ */
+ProfileManager::~ProfileManager()
+{
+ delete mPriv;
+}
+
+/**
+ * Return a list of all available profiles.
+ *
+ * \return A list of all available profiles.
+ */
+QList<ProfilePtr> ProfileManager::profiles() const
+{
+ return mPriv->profiles.values();
+}
+
+/**
+ * Return a list of all available profiles for a given connection manager.
+ *
+ * \param cmName Connection manager name.
+ * \return A list of all available profiles for a given connection manager.
+ */
+QList<ProfilePtr> ProfileManager::profilesForCM(const QString &cmName) const
+{
+ QList<ProfilePtr> ret;
+ foreach (const ProfilePtr &profile, mPriv->profiles) {
+ if (profile->cmName() == cmName) {
+ ret << profile;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Return a list of all available profiles for a given \a protocol.
+ *
+ * \param protocolName Protocol name.
+ * \return A list of all available profiles for a given \a protocol.
+ */
+QList<ProfilePtr> ProfileManager::profilesForProtocol(
+ const QString &protocolName) const
+{
+ QList<ProfilePtr> ret;
+ foreach (const ProfilePtr &profile, mPriv->profiles) {
+ if (profile->protocolName() == protocolName) {
+ ret << profile;
+ }
+ }
+ return ret;
+}
+
+/**
+ * Return the profile for a given \a service.
+ *
+ * \param serviceName Service name.
+ * \return The profile for \a service.
+ */
+ProfilePtr ProfileManager::profileForService(const QString &serviceName) const
+{
+ return mPriv->profiles.value(serviceName);
+}
+
+void ProfileManager::onCmNamesRetrieved(Tp::PendingOperation *op)
+{
+ if (op->isError()) {
+ warning().nospace() << "Getting available CMs failed with " <<
+ op->errorName() << ":" << op->errorMessage();
+ mPriv->readinessHelper->setIntrospectCompleted(FeatureFakeProfiles, false,
+ op->errorName(), op->errorMessage());
+ return;
+ }
+
+ PendingStringList *pendingCmNames = qobject_cast<PendingStringList *>(op);
+ QStringList cmNames(pendingCmNames->result());
+ if (cmNames.isEmpty()) {
+ mPriv->readinessHelper->setIntrospectCompleted(FeatureFakeProfiles, true);
+ return;
+ }
+
+ QList<PendingOperation *> ops;
+ foreach (const QString &cmName, cmNames) {
+ ConnectionManagerPtr cm = ConnectionManager::create(mPriv->bus, cmName);
+ mPriv->cms.append(cm);
+ ops.append(cm->becomeReady());
+ }
+
+ PendingComposite *pc = new PendingComposite(ops, false, ProfileManagerPtr(this));
+ connect(pc,
+ SIGNAL(finished(Tp::PendingOperation *)),
+ SLOT(onCMsReady(Tp::PendingOperation *)));
+}
+
+void ProfileManager::onCMsReady(Tp::PendingOperation *op)
+{
+ if (op->isError()) {
+ warning() << "Failed introspecting all CMs, trying to create fake profiles anyway";
+ }
+
+ ProfilePtr profile;
+ foreach (const ConnectionManagerPtr &cm, mPriv->cms) {
+ if (!cm->isReady()) {
+ continue;
+ }
+
+ foreach (const QString &protocolName, cm->supportedProtocols()) {
+ /* check if there is a profile whose service name is protocolName, and if found,
+ * check if the profile is for cm, if not check if there is a profile whose service
+ * name is cm-protocolName, and if not found create one named cm-protocolName. */
+ profile = profileForService(protocolName);
+ if (profile && profile->cmName() == cm->name()) {
+ continue;
+ }
+
+ QString serviceName = QString(QLatin1String("%1-%2")).arg(cm->name()).arg(protocolName);
+ profile = profileForService(serviceName);
+ if (profile) {
+ continue;
+ }
+
+ profile = ProfilePtr(new Profile(
+ serviceName,
+ cm->name(),
+ protocolName,
+ cm->protocol(protocolName)));
+ mPriv->profiles.insert(serviceName, profile);
+ }
+ }
+
+ mPriv->readinessHelper->setIntrospectCompleted(FeatureFakeProfiles, true);
+}
+
+} // Tp