1 /**
2 * This file is part of TelepathyQt
3 *
4 * @copyright Copyright (C) 2010-2011 Collabora Ltd. <http://www.collabora.co.uk/>
5 * @license LGPL 2.1
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <TelepathyQt/TubeChannel>
23
24 #include "TelepathyQt/_gen/tube-channel.moc.hpp"
25
26 #include "TelepathyQt/debug-internal.h"
27
28 #include <TelepathyQt/PendingVariantMap>
29
30 namespace Tp
31 {
32
33 struct TP_QT_NO_EXPORT TubeChannel::Private
34 {
35 Private(TubeChannel *parent);
36
37 static void introspectTube(TubeChannel::Private *self);
38
39 void extractTubeProperties(const QVariantMap &props);
40
41 // Public object
42 TubeChannel *parent;
43
44 ReadinessHelper *readinessHelper;
45
46 // Introspection
47 TubeChannelState state;
48 QVariantMap parameters;
49 };
50
Private(TubeChannel * parent)51 TubeChannel::Private::Private(TubeChannel *parent)
52 : parent(parent),
53 readinessHelper(parent->readinessHelper()),
54 state((TubeChannelState) -1)
55 {
56 ReadinessHelper::Introspectables introspectables;
57
58 ReadinessHelper::Introspectable introspectableTube(
59 QSet<uint>() << 0, // makesSenseForStatuses
60 Features() << Channel::FeatureCore, // dependsOnFeatures (core)
61 QStringList() << TP_QT_IFACE_CHANNEL_INTERFACE_TUBE, // dependsOnInterfaces
62 (ReadinessHelper::IntrospectFunc) &TubeChannel::Private::introspectTube,
63 this);
64 introspectables[TubeChannel::FeatureCore] = introspectableTube;
65
66 readinessHelper->addIntrospectables(introspectables);
67 }
68
introspectTube(TubeChannel::Private * self)69 void TubeChannel::Private::introspectTube(TubeChannel::Private *self)
70 {
71 TubeChannel *parent = self->parent;
72
73 debug() << "Introspecting tube properties";
74 Client::ChannelInterfaceTubeInterface *tubeInterface =
75 parent->interface<Client::ChannelInterfaceTubeInterface>();
76
77 parent->connect(tubeInterface,
78 SIGNAL(TubeChannelStateChanged(uint)),
79 SLOT(onTubeChannelStateChanged(uint)));
80
81 PendingVariantMap *pvm = tubeInterface->requestAllProperties();
82 parent->connect(pvm,
83 SIGNAL(finished(Tp::PendingOperation *)),
84 SLOT(gotTubeProperties(Tp::PendingOperation *)));
85 }
86
extractTubeProperties(const QVariantMap & props)87 void TubeChannel::Private::extractTubeProperties(const QVariantMap &props)
88 {
89 state = (Tp::TubeChannelState) qdbus_cast<uint>(props[QLatin1String("State")]);
90 parameters = qdbus_cast<QVariantMap>(props[QLatin1String("Parameters")]);
91 }
92
93 /**
94 * \class TubeChannel
95 * \ingroup clientchannel
96 * \headerfile TelepathyQt/tube-channel.h <TelepathyQt/TubeChannel>
97 *
98 * \brief The TubeChannel class is a base class for all tube types.
99 *
100 * A tube is a mechanism for arbitrary data transfer between two or more IM users,
101 * used to allow applications on the users' systems to communicate without having
102 * to establish network connections themselves.
103 *
104 * Note that TubeChannel should never be instantiated directly, instead one of its
105 * subclasses (e.g. IncomingStreamTubeChannel or OutgoingStreamTubeChannel) should be used.
106 *
107 * See \ref async_model, \ref shared_ptr
108 */
109
110 /**
111 * Feature representing the core that needs to become ready to make the
112 * TubeChannel object usable.
113 *
114 * Note that this feature must be enabled in order to use most
115 * TubeChannel methods.
116 * See specific methods documentation for more details.
117 */
118 const Feature TubeChannel::FeatureCore = Feature(QLatin1String(TubeChannel::staticMetaObject.className()), 0);
119
120 /**
121 * Create a new TubeChannel channel.
122 *
123 * \param connection Connection owning this channel, and specifying the
124 * service.
125 * \param objectPath The channel object path.
126 * \param immutableProperties The channel immutable properties.
127 * \return A TubeChannelPtr object pointing to the newly created
128 * TubeChannel object.
129 */
create(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties)130 TubeChannelPtr TubeChannel::create(const ConnectionPtr &connection,
131 const QString &objectPath, const QVariantMap &immutableProperties)
132 {
133 return TubeChannelPtr(new TubeChannel(connection, objectPath,
134 immutableProperties));
135 }
136
137 /**
138 * Construct a new TubeChannel object.
139 *
140 * \param connection Connection owning this channel, and specifying the
141 * service.
142 * \param objectPath The channel object path.
143 * \param immutableProperties The channel immutable properties.
144 * \param coreFeature The core feature of the channel type, if any. The corresponding introspectable should
145 * depend on TubeChannel::FeatureCore.
146 */
TubeChannel(const ConnectionPtr & connection,const QString & objectPath,const QVariantMap & immutableProperties,const Feature & coreFeature)147 TubeChannel::TubeChannel(const ConnectionPtr &connection,
148 const QString &objectPath,
149 const QVariantMap &immutableProperties,
150 const Feature &coreFeature)
151 : Channel(connection, objectPath, immutableProperties, coreFeature),
152 mPriv(new Private(this))
153 {
154 }
155
156 /**
157 * Class destructor.
158 */
~TubeChannel()159 TubeChannel::~TubeChannel()
160 {
161 delete mPriv;
162 }
163
164 /**
165 * Return the parameters associated with this tube, if any.
166 *
167 * The parameters are populated when an outgoing tube is offered, but they are most useful in the
168 * receiving end, where the parameters passed to the offer can be extracted for the tube's entire
169 * lifetime to bootstrap legacy protocols. All parameters are passed unchanged.
170 *
171 * This method requires TubeChannel::FeatureCore to be ready.
172 *
173 * \return The parameters as QVariantMap.
174 */
parameters() const175 QVariantMap TubeChannel::parameters() const
176 {
177 if (!isReady(FeatureCore)) {
178 warning() << "TubeChannel::parameters() used with FeatureCore not ready";
179 return QVariantMap();
180 }
181
182 return mPriv->parameters;
183 }
184
185 /**
186 * Return the state of this tube.
187 *
188 * Change notification is via the stateChanged() signal.
189 *
190 * This method requires TubeChannel::FeatureCore to be ready.
191 *
192 * \return The state as #TubeChannelState.
193 * \sa stateChanged()
194 */
state() const195 TubeChannelState TubeChannel::state() const
196 {
197 if (!isReady(FeatureCore)) {
198 warning() << "TubeChannel::state() used with FeatureCore not ready";
199 return TubeChannelStateNotOffered;
200 }
201
202 return mPriv->state;
203 }
204
setParameters(const QVariantMap & parameters)205 void TubeChannel::setParameters(const QVariantMap ¶meters)
206 {
207 mPriv->parameters = parameters;
208 }
209
onTubeChannelStateChanged(uint newState)210 void TubeChannel::onTubeChannelStateChanged(uint newState)
211 {
212 if (newState == mPriv->state) {
213 return;
214 }
215
216 uint oldState = mPriv->state;
217
218 debug() << "Tube state changed to" << newState;
219 mPriv->state = (Tp::TubeChannelState) newState;
220
221 /* only emit stateChanged if we already received the state from initial introspection */
222 if (oldState != (uint) -1) {
223 emit stateChanged((Tp::TubeChannelState) newState);
224 }
225 }
226
gotTubeProperties(PendingOperation * op)227 void TubeChannel::gotTubeProperties(PendingOperation *op)
228 {
229 if (!op->isError()) {
230 PendingVariantMap *pvm = qobject_cast<PendingVariantMap *>(op);
231
232 mPriv->extractTubeProperties(pvm->result());
233
234 debug() << "Got reply to Properties::GetAll(TubeChannel)";
235 mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, true);
236 } else {
237 warning().nospace() << "Properties::GetAll(TubeChannel) failed "
238 "with " << op->errorName() << ": " << op->errorMessage();
239 mPriv->readinessHelper->setIntrospectCompleted(TubeChannel::FeatureCore, false,
240 op->errorName(), op->errorMessage());
241 }
242 }
243
244 /**
245 * \fn void TubeChannel::stateChanged(Tp::TubeChannelState state)
246 *
247 * Emitted when the value of state() changes.
248 *
249 * \sa state The new state of this tube.
250 */
251
252 } // Tp
253