/**
* This file is part of TelepathyQt
*
* @copyright Copyright (C) 2009 Collabora Ltd.
* @copyright Copyright (C) 2009 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/cli-channel-request-body.hpp"
#include "TelepathyQt/_gen/cli-channel-request.moc.hpp"
#include "TelepathyQt/_gen/channel-request.moc.hpp"
#include "TelepathyQt/debug-internal.h"
#include
#include
#include
#include
#include
#include
#include
namespace Tp
{
struct TP_QT_NO_EXPORT ChannelRequest::Private
{
Private(ChannelRequest *parent, const QVariantMap &immutableProperties,
const AccountFactoryConstPtr &, const ConnectionFactoryConstPtr &,
const ChannelFactoryConstPtr &, const ContactFactoryConstPtr &);
~Private();
static void introspectMain(Private *self);
// \param lastCall Is this the last call to extractMainProps ie. should actions that only must
// be done once be done in this call
void extractMainProps(const QVariantMap &props, bool lastCall);
// Public object
ChannelRequest *parent;
// Context
AccountFactoryConstPtr accFact;
ConnectionFactoryConstPtr connFact;
ChannelFactoryConstPtr chanFact;
ContactFactoryConstPtr contactFact;
// Instance of generated interface class
Client::ChannelRequestInterface *baseInterface;
// Mandatory properties interface proxy
Client::DBus::PropertiesInterface *properties;
QVariantMap immutableProperties;
ReadinessHelper *readinessHelper;
// Introspection
AccountPtr account;
QDateTime userActionTime;
QString preferredHandler;
QualifiedPropertyValueMapList requests;
ChannelRequestHints hints;
bool propertiesDone;
bool gotSWC;
ChannelPtr chan;
};
ChannelRequest::Private::Private(ChannelRequest *parent,
const QVariantMap &immutableProperties,
const AccountFactoryConstPtr &accFact,
const ConnectionFactoryConstPtr &connFact,
const ChannelFactoryConstPtr &chanFact,
const ContactFactoryConstPtr &contactFact)
: parent(parent),
accFact(accFact),
connFact(connFact),
chanFact(chanFact),
contactFact(contactFact),
baseInterface(new Client::ChannelRequestInterface(parent)),
properties(parent->interface()),
immutableProperties(immutableProperties),
readinessHelper(parent->readinessHelper()),
propertiesDone(false),
gotSWC(false)
{
debug() << "Creating new ChannelRequest:" << parent->objectPath();
parent->connect(baseInterface,
SIGNAL(Failed(QString,QString)),
SIGNAL(failed(QString,QString)));
parent->connect(baseInterface,
SIGNAL(Succeeded()),
SLOT(onLegacySucceeded()));
parent->connect(baseInterface,
SIGNAL(SucceededWithChannel(QDBusObjectPath,QVariantMap,QDBusObjectPath,QVariantMap)),
SLOT(onSucceededWithChannel(QDBusObjectPath,QVariantMap,QDBusObjectPath,QVariantMap)));
ReadinessHelper::Introspectables introspectables;
// As ChannelRequest does not have predefined statuses let's simulate one (0)
ReadinessHelper::Introspectable introspectableCore(
QSet() << 0, // makesSenseForStatuses
Features(), // dependsOnFeatures
QStringList(), // dependsOnInterfaces
(ReadinessHelper::IntrospectFunc) &Private::introspectMain,
this);
introspectables[FeatureCore] = introspectableCore;
readinessHelper->addIntrospectables(introspectables);
// For early access to the immutable properties through the friendly getters - will be called
// again with lastCall = true eventually, if/when becomeReady is called, though
QVariantMap mainProps;
foreach (QString key, immutableProperties.keys()) {
// The key.count thing is so that we don't match "org.fdo.Tp.CR.OptionalInterface.Prop" too
if (key.startsWith(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String("."))
&& key.count(QLatin1Char('.')) ==
QString(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".")).count(QLatin1Char('.'))) {
QVariant value = immutableProperties.value(key);
mainProps.insert(key.remove(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".")), value);
}
}
extractMainProps(mainProps, false);
}
ChannelRequest::Private::~Private()
{
}
void ChannelRequest::Private::introspectMain(ChannelRequest::Private *self)
{
QVariantMap props;
QString key;
bool needIntrospectMainProps = false;
const char *propertiesNames[] = { "Account", "UserActionTime",
"PreferredHandler", "Requests", "Interfaces",
NULL };
for (unsigned i = 0; propertiesNames[i] != NULL; ++i) {
key = TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".");
key += QLatin1String(propertiesNames[i]);
if (!self->immutableProperties.contains(key)) {
needIntrospectMainProps = true;
break;
}
props.insert(QLatin1String(propertiesNames[i]),
self->immutableProperties[key]);
}
if (needIntrospectMainProps) {
debug() << "Calling Properties::GetAll(ChannelRequest)";
QDBusPendingCallWatcher *watcher =
new QDBusPendingCallWatcher(
self->properties->GetAll(TP_QT_IFACE_CHANNEL_REQUEST),
self->parent);
// FIXME: This is a Qt bug fixed upstream, should be in the next Qt release.
// We should not need to check watcher->isFinished() here, remove the
// check when a fixed Qt version is released.
if (watcher->isFinished()) {
self->parent->gotMainProperties(watcher);
} else {
self->parent->connect(watcher,
SIGNAL(finished(QDBusPendingCallWatcher*)),
SLOT(gotMainProperties(QDBusPendingCallWatcher*)));
}
} else {
self->extractMainProps(props, true);
}
}
void ChannelRequest::Private::extractMainProps(const QVariantMap &props, bool lastCall)
{
PendingReady *readyOp = 0;
if (props.contains(QLatin1String("Account"))) {
QDBusObjectPath accountObjectPath =
qdbus_cast(props.value(QLatin1String("Account")));
if (!account.isNull()) {
if (accountObjectPath.path() == account->objectPath()) {
// Most often a no-op, but we want this to guarantee the old behavior in all cases
readyOp = account->becomeReady();
} else {
warning() << "The account" << accountObjectPath.path() << "was not the expected"
<< account->objectPath() << "for CR" << parent->objectPath();
// Construct a new one instead
account.reset();
}
}
// We need to check again because we might have dropped the expected account just a sec ago
if (account.isNull() && !accountObjectPath.path().isEmpty()) {
if (!accFact.isNull()) {
readyOp = accFact->proxy(
TP_QT_ACCOUNT_MANAGER_BUS_NAME, accountObjectPath.path(),
connFact, chanFact, contactFact);
account = AccountPtr::qObjectCast(readyOp->proxy());
} else {
account = Account::create(
TP_QT_ACCOUNT_MANAGER_BUS_NAME,
accountObjectPath.path(), connFact, chanFact, contactFact);
readyOp = account->becomeReady();
}
}
}
// FIXME See http://bugs.freedesktop.org/show_bug.cgi?id=21690
uint stamp = (uint) qdbus_cast(props.value(QLatin1String("UserActionTime")));
if (stamp != 0) {
userActionTime = QDateTime::fromTime_t(stamp);
}
preferredHandler = qdbus_cast(props.value(QLatin1String("PreferredHandler")));
requests = qdbus_cast(props.value(QLatin1String("Requests")));
parent->setInterfaces(qdbus_cast(props[QLatin1String("Interfaces")]));
readinessHelper->setInterfaces(parent->interfaces());
if (props.contains(QLatin1String("Hints"))) {
hints = qdbus_cast(props.value(QLatin1String("Hints")));
}
if (lastCall) {
propertiesDone = true;
}
if (account) {
parent->connect(readyOp,
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onAccountReady(Tp::PendingOperation*)));
} else if (lastCall) {
warning() << "No account for ChannelRequest" << parent->objectPath();
readinessHelper->setIntrospectCompleted(FeatureCore, true);
}
}
/**
* \class ChannelRequest
* \ingroup clientchannelrequest
* \headerfile TelepathyQt/channel-request.h
*
* \brief The ChannelRequest class represents a Telepathy channel request.
*
* A channel request is an object in the channel dispatcher representing an
* ongoing request for some channels to be created or found. There can be any
* number of channel request objects at the same time.
*
* A channel request can be cancelled by any client (not just the one that
* requested it). This means that the channel dispatcher will close the
* resulting channel, or refrain from requesting it at all, rather than
* dispatching it to a handler.
*
* See \ref async_model
*/
/**
* Feature representing the core that needs to become ready to make the
* ChannelRequest object usable.
*
* Note that this feature must be enabled in order to use most
* ChannelRequest methods.
*
* When calling isReady(), becomeReady(), this feature is implicitly added
* to the requested features.
*/
const Feature ChannelRequest::FeatureCore = Feature(QLatin1String(ChannelRequest::staticMetaObject.className()), 0, true);
/**
* Create a new channel request object using the given \a bus and the given factories.
*
* \param objectPath The channel request object path.
* \param immutableProperties The channel request immutable properties.
* \param accountFactory The account factory to use.
* \param connectionFactory The connection factory to use.
* \param channelFactory The channel factory to use.
* \param contactFactory The contact factory to use.
* \return A ChannelRequestPtr object pointing to the newly created ChannelRequest object.
*/
ChannelRequestPtr ChannelRequest::create(const QDBusConnection &bus, const QString &objectPath,
const QVariantMap &immutableProperties,
const AccountFactoryConstPtr &accountFactory,
const ConnectionFactoryConstPtr &connectionFactory,
const ChannelFactoryConstPtr &channelFactory,
const ContactFactoryConstPtr &contactFactory)
{
return ChannelRequestPtr(new ChannelRequest(bus, objectPath, immutableProperties,
accountFactory, connectionFactory, channelFactory, contactFactory));
}
/**
* Create a new channel request object for the given \a account.
*
* The returned instance will use factories from the account.
*
* \param account The account that the request was made through.
* \param objectPath The channel request object path.
* \param immutableProperties The channel request immutable properties.
* \return A ChannelRequestPtr object pointing to the newly created ChannelRequest object.
*/
ChannelRequestPtr ChannelRequest::create(const AccountPtr &account, const QString &objectPath,
const QVariantMap &immutableProperties)
{
return ChannelRequestPtr(new ChannelRequest(account, objectPath, immutableProperties));
}
/**
* Construct a new channel request object using the given \a bus and the given factories.
*
* \param bus QDBusConnection to use.
* \param objectPath The channel request object path.
* \param accountFactory The account factory to use.
* \param connectionFactory The connection factory to use.
* \param channelFactory The channel factory to use.
* \param contactFactory The contact factory to use.
* \param immutableProperties The immutable properties of the channel request.
* \return A ChannelRequestPtr object pointing to the newly created ChannelRequest.
*/
ChannelRequest::ChannelRequest(const QDBusConnection &bus,
const QString &objectPath, const QVariantMap &immutableProperties,
const AccountFactoryConstPtr &accountFactory,
const ConnectionFactoryConstPtr &connectionFactory,
const ChannelFactoryConstPtr &channelFactory,
const ContactFactoryConstPtr &contactFactory)
: StatefulDBusProxy(bus,
TP_QT_IFACE_CHANNEL_DISPATCHER,
objectPath, FeatureCore),
OptionalInterfaceFactory(this),
mPriv(new Private(this, immutableProperties, accountFactory, connectionFactory,
channelFactory, contactFactory))
{
if (accountFactory->dbusConnection().name() != bus.name()) {
warning() << " The D-Bus connection in the account factory is not the proxy connection";
}
if (connectionFactory->dbusConnection().name() != bus.name()) {
warning() << " The D-Bus connection in the connection factory is not the proxy connection";
}
if (channelFactory->dbusConnection().name() != bus.name()) {
warning() << " The D-Bus connection in the channel factory is not the proxy connection";
}
}
/**
* Construct a new channel request object using the given \a account.
*
* The constructed instance will use the factories from the account.
*
* \param account Account to use.
* \param objectPath The channel request object path.
* \param immutableProperties The immutable properties of the channel request.
* \return A ChannelRequestPtr object pointing to the newly created ChannelRequest.
*/
ChannelRequest::ChannelRequest(const AccountPtr &account,
const QString &objectPath, const QVariantMap &immutableProperties)
: StatefulDBusProxy(account->dbusConnection(),
TP_QT_IFACE_CHANNEL_DISPATCHER,
objectPath, FeatureCore),
OptionalInterfaceFactory(this),
mPriv(new Private(this, immutableProperties, AccountFactoryPtr(),
account->connectionFactory(),
account->channelFactory(),
account->contactFactory()))
{
mPriv->account = account;
}
/**
* Class destructor.
*/
ChannelRequest::~ChannelRequest()
{
delete mPriv;
}
/**
* Return the account on which this request was made.
*
* This method can be used even before the ChannelRequest is ready, in which case the account object
* corresponding to the immutable properties is returned. In this case, the Account object is not
* necessarily ready either. This is useful for eg. matching ChannelRequests from
* ClientHandlerInterface::addRequest() with existing accounts in the application: either by object
* path, or if account factories are in use, even by object identity.
*
* If the account is not provided in the immutable properties, this will only return a non-\c NULL
* AccountPtr once ChannelRequest::FeatureCore is ready on this object.
*
* \return A pointer to the Account object.
*/
AccountPtr ChannelRequest::account() const
{
return mPriv->account;
}
/**
* Return the time at which the user action occurred, or 0 if this channel
* request is for some reason not involving user action.
*
* Unix developers: this corresponds to the _NET_WM_USER_TIME property in EWMH.
*
* This property is set when the channel request is created, and can never
* change.
*
* This method can be used even before the ChannelRequest is ready: in this case, the user action
* time from the immutable properties, if any, is returned.
*
* \return The time at which the user action occurred as QDateTime.
*/
QDateTime ChannelRequest::userActionTime() const
{
return mPriv->userActionTime;
}
/**
* Return either the well-known bus name (starting with
* org.freedesktop.Telepathy.Client.) of the preferred handler for this channel,
* or an empty string to indicate that any handler would be acceptable.
*
* This property is set when the channel request is created, and can never
* change.
*
* This method can be used even before the ChannelRequest is ready: in this case, the preferred
* handler from the immutable properties, if any, is returned.
*
* \return The preferred handler, or an empty string if any handler would be
* acceptable.
*/
QString ChannelRequest::preferredHandler() const
{
return mPriv->preferredHandler;
}
/**
* Return the desirable properties for the channel or channels to be created, as specified when
* placing the request in the first place.
*
* This property is set when the channel request is created, and can never
* change.
*
* This method can be used even before the ChannelRequest is ready: in this case, the requested
* channel properties from the immutable properties, if any, are returned. This is useful for e.g.
* matching ChannelRequests from ClientHandlerInterface::addRequest() with existing requests in the
* application (by the target ID or handle, most likely).
*
* \return The requested desirable channel properties as a list of
* QualifiedPropertyValueMap objects.
*/
QualifiedPropertyValueMapList ChannelRequest::requests() const
{
return mPriv->requests;
}
/**
* Return the dictionary of metadata provided by the channel requester when requesting the channel.
*
* This property is set when the channel request is created, and can never change.
*
* This method can be used even before the ChannelRequest is ready: in this case, the requested
* channel properties from the immutable properties, if any, are returned. This is useful for e.g.
* matching ChannelRequests from ClientHandlerInterface::addRequest() with existing requests in the
* application (by the target ID or handle, most likely).
*
* \sa Account::supportsRequestHints()
* \return The hints in the request as a ChannelRequestHints object, if any.
*/
ChannelRequestHints ChannelRequest::hints() const
{
return mPriv->hints;
}
/**
* Return all of the immutable properties passed to this object when created.
*
* This is useful for e.g. getting to domain-specific properties of channel requests.
*
* \return The immutable properties as QVariantMap.
*/
QVariantMap ChannelRequest::immutableProperties() const
{
QVariantMap props = mPriv->immutableProperties;
if (!account().isNull()) {
props.insert(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".Account"),
QVariant::fromValue(QDBusObjectPath(account()->objectPath())));
}
if (userActionTime().isValid()) {
props.insert(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".UserActionTime"),
QVariant::fromValue(userActionTime().toTime_t()));
}
if (!preferredHandler().isNull()) {
props.insert(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".PreferredHandler"),
preferredHandler());
}
if (!requests().isEmpty()) {
props.insert(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".Requests"),
QVariant::fromValue(requests()));
}
props.insert(TP_QT_IFACE_CHANNEL_REQUEST + QLatin1String(".Interfaces"),
QVariant::fromValue(interfaces()));
return props;
}
/**
* Cancel the channel request.
*
* If failed() is emitted in response to this method, the error will be
* #TP_QT_ERROR_CANCELLED.
*
* If the channel has already been dispatched to a handler, then it's too late
* to call this method, and the channel request will no longer exist.
*
* \return A PendingOperation which will emit PendingOperation::finished
* when the call has finished.
*/
PendingOperation *ChannelRequest::cancel()
{
return new PendingVoid(mPriv->baseInterface->Cancel(),
ChannelRequestPtr(this));
}
/**
* Return the Channel which this request succeeded with, if any.
*
* This will only ever be populated if Account::requestsSucceedWithChannel() is \c true, and
* succeeded() has already been emitted on this ChannelRequest. Note that a PendingChannelRequest
* being successfully finished already implies succeeded() has been emitted.
*
* \return A pointer to the Channel object, or a null ChannelPtr if there isn't any.
*/
ChannelPtr ChannelRequest::channel() const
{
return mPriv->chan;
}
/**
* Proceed with the channel request.
*
* The client that created this object calls this method when it has connected
* signal handlers for succeeded() and failed(). Note that this is done
* automatically when using PendingChannelRequest.
*
* \return A PendingOperation which will emit PendingOperation::finished
* when the call has finished.
*/
PendingOperation *ChannelRequest::proceed()
{
return new PendingVoid(mPriv->baseInterface->Proceed(),
ChannelRequestPtr(this));
}
/**
* Return the ChannelRequestInterface for this ChannelRequest class. This method is
* protected since the convenience methods provided by this class should
* always be used instead of the interface by users of the class.
*
* \return A pointer to the existing Client::ChannelRequestInterface object for this
* ChannelRequest object.
*/
Client::ChannelRequestInterface *ChannelRequest::baseInterface() const
{
return mPriv->baseInterface;
}
void ChannelRequest::gotMainProperties(QDBusPendingCallWatcher *watcher)
{
QDBusPendingReply reply = *watcher;
QVariantMap props;
if (!reply.isError()) {
debug() << "Got reply to Properties::GetAll(ChannelRequest)";
props = reply.value();
mPriv->extractMainProps(props, true);
} else {
mPriv->readinessHelper->setIntrospectCompleted(FeatureCore,
false, reply.error());
warning().nospace() << "Properties::GetAll(ChannelRequest) failed with "
<< reply.error().name() << ": " << reply.error().message();
}
watcher->deleteLater();
}
void ChannelRequest::onAccountReady(PendingOperation *op)
{
if (op->isError()) {
warning() << "Unable to make ChannelRequest.Account ready";
mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false,
op->errorName(), op->errorMessage());
return;
}
if (mPriv->propertiesDone && !isReady()) {
mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
}
}
void ChannelRequest::onLegacySucceeded()
{
if (mPriv->gotSWC) {
return;
}
emit succeeded(ChannelPtr());
}
void ChannelRequest::onSucceededWithChannel(
const QDBusObjectPath &connPath,
const QVariantMap &connProps,
const QDBusObjectPath &chanPath,
const QVariantMap &chanProps)
{
if (mPriv->gotSWC) {
warning().nospace() << "Got SucceededWithChannel again for CR(" << objectPath() << ")!";
return;
}
mPriv->gotSWC = true;
QList readyOps;
QString connBusName = connPath.path().mid(1).replace(
QLatin1String("/"), QLatin1String("."));
PendingReady *connReady = mPriv->connFact->proxy(connBusName, connPath.path(),
mPriv->chanFact, mPriv->contactFact);
ConnectionPtr conn = ConnectionPtr::qObjectCast(connReady->proxy());
readyOps.append(connReady);
PendingReady *chanReady = mPriv->chanFact->proxy(conn, chanPath.path(), chanProps);
mPriv->chan = ChannelPtr::qObjectCast(chanReady->proxy());
readyOps.append(chanReady);
connect(new PendingComposite(readyOps, ChannelRequestPtr(this)),
SIGNAL(finished(Tp::PendingOperation*)),
SLOT(onChanBuilt(Tp::PendingOperation*)));
}
void ChannelRequest::onChanBuilt(Tp::PendingOperation *op)
{
if (op->isError()) {
warning() << "Failed to build Channel which the ChannelRequest succeeded with,"
<< "succeeding with NULL channel:" << op->errorName() << ',' << op->errorMessage();
mPriv->chan.reset();
}
emit succeeded(mPriv->chan);
}
/**
* \fn void ChannelRequest::failed(const QString &errorName,
* const QString &errorMessage)
*
* Emitted when the channel request has failed. No further
* methods must not be called on it.
*
* \param errorName The name of a D-Bus error.
* \param errorMessage The error message.
* \sa succeeded()
*/
/**
* \fn void ChannelRequest::succeeded(const Tp::ChannelPtr &channel)
*
* Emitted when the channel request has succeeded. No further
* methods must not be called on it.
*
* The \a channel parameter can be used to observe the channel resulting from the request (e.g. for
* it getting closed). The pointer may be NULL if the Channel Dispatcher implementation is too old.
* Whether a non-NULL channel can be expected can be checked with
* Account::requestsSucceedWithChannel().
*
* If there is a channel, it will be of the subclass determined by and made ready (or not) according
* to the settings of the ChannelFactory on the Account the request was made through.
*
* \param channel Pointer to a proxy for the resulting channel, if the Channel Dispatcher reported it.
* \sa failed()
*/
/**
* \class ChannelRequestHints
* \ingroup clientchannelrequest
* \headerfile TelepathyQt/channel-request.h
*
* \brief The ChannelRequestHints class represents a dictionary of metadata
* provided by the channel requester when requesting a channel.
*/
struct TP_QT_NO_EXPORT ChannelRequestHints::Private : public QSharedData
{
Private() {}
Private(const QVariantMap &hints) : hints(hints) {}
QVariantMap hints;
};
ChannelRequestHints::ChannelRequestHints()
{
}
ChannelRequestHints::ChannelRequestHints(const QVariantMap &hints)
: mPriv(new Private(hints))
{
}
ChannelRequestHints::ChannelRequestHints(const ChannelRequestHints &crh)
: mPriv(crh.mPriv)
{
}
ChannelRequestHints::~ChannelRequestHints()
{
}
ChannelRequestHints &ChannelRequestHints::operator=(const ChannelRequestHints &other)
{
if (this == &other) {
return *this;
}
this->mPriv = other.mPriv;
return *this;
}
bool ChannelRequestHints::isValid() const
{
return mPriv.constData() != 0;
}
bool ChannelRequestHints::hasHint(const QString &reversedDomain, const QString &localName) const
{
if (!isValid()) {
return false;
}
const QString qualifiedName = reversedDomain + QLatin1Char('.') + localName;
return mPriv->hints.contains(qualifiedName);
}
QVariant ChannelRequestHints::hint(const QString &reversedDomain, const QString &localName) const
{
if (!isValid()) {
return QVariant();
}
const QString qualifiedName = reversedDomain + QLatin1Char('.') + localName;
return mPriv->hints.value(qualifiedName);
}
void ChannelRequestHints::setHint(const QString &reversedDomain, const QString &localName, const QVariant &value)
{
const QString qualifiedName = reversedDomain + QLatin1Char('.') + localName;
if (!isValid()) {
mPriv = new Private();
}
mPriv->hints.insert(qualifiedName, value);
}
QVariantMap ChannelRequestHints::allHints() const
{
return isValid() ? mPriv->hints : QVariantMap();
}
} // Tp