Initial Import
[profile/ivi/connman-qt.git] / libconnman-qt / networkitem.cpp
1 /*   -*- Mode: C++ -*-
2  * meegotouchcp-connman - connectivity plugin for duicontrolpanel
3  * Copyright © 2010, Intel Corporation.
4  *
5  * This program is licensed under the terms and conditions of the
6  * Apache License, version 2.0.  The full text of the Apache License is at
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  */
10 #include "networkitem.h"
11 #include "debug.h"
12 #include "commondbustypes.h"
13
14 #include <QVariant>
15
16 //FIXME: could reuse these static strings for getProperties and popertyChanged
17 const char* const NetworkItemModel::Name = "Name";
18 const char* const NetworkItemModel::Security = "Security";
19 const char* const NetworkItemModel::Strength = "Strength";
20 const char* const NetworkItemModel::State = "State";
21 const char* const NetworkItemModel::Type = "Type";
22 const char* const NetworkItemModel::PassphraseRequired = "PassphraseRequired";
23 const char* const NetworkItemModel::Passphrase = "Passphrase";
24 const char* const NetworkItemModel::IPv4 = "IPv4.Configuration";
25 const char* const NetworkItemModel::IPv4Normal = "IPv4";
26 const char* const NetworkItemModel::Nameservers = "Nameservers";
27 const char* const NetworkItemModel::DeviceAddress = "DeviceAddress";
28 const char* const NetworkItemModel::Mode = "Mode";
29 const char* const NetworkItemModel::APN = "APN";
30 const char* const NetworkItemModel::SetupRequired = "SetupRequired";
31 ///todo: not hooked up:
32 const char* const NetworkItemModel::LoginRequired = "LoginRequired";
33
34 int NetworkItemModel::instances = 0;
35 int NetworkItemModel::idCounter = 0;
36
37 NetworkItemModel::NetworkItemModel(const QString &path, QObject *parent) :
38   id(idCounter),
39   m_service(NULL),
40   m_getPropertiesWatcher(NULL),
41   m_setPropertyWatcher(NULL),
42   m_disconnectWatcher(NULL),
43   m_connectWatcher(NULL),
44   m_state(StateNone),
45   m_strength(0),
46   m_passphraseRequired(false)
47 {
48   registerCommonDataTypes();
49
50   setParent(parent);
51   instances++;
52   idCounter++;
53   m_servicePath = path;
54   if (!path.isEmpty()) {
55     m_service = new Service("net.connman", path,
56                             QDBusConnection::systemBus(),
57                             this);
58     if (!m_service->isValid()) {
59           qDebug("service %s is invalid!", STR(path));
60       throw -1; //FIXME
61     }
62     QDBusPendingReply<QVariantMap> reply = m_service->GetProperties();
63     m_getPropertiesWatcher = new QDBusPendingCallWatcher(reply, this);
64     connect(m_getPropertiesWatcher,
65             SIGNAL(finished(QDBusPendingCallWatcher*)),
66             this,
67             SLOT(getPropertiesReply(QDBusPendingCallWatcher*)));
68
69         connect(m_service,
70                 SIGNAL(PropertyChanged(const QString&,
71                                    const QDBusVariant &)),
72                 this,
73                 SLOT(propertyChanged(const QString&,
74                                          const QDBusVariant &)));
75
76   }
77
78
79   //this is an attempt to avoid having lots of networks show in the
80   //list with no type.  The thought process is that the filter is
81   //matching on empty strings.  It doesn't appear to work in the
82   //nothing in the list except one thing problem.  But other problems
83   //haven't been tried
84   m_type = "????";
85 }
86
87 NetworkItemModel::~NetworkItemModel()
88 {
89   instances--;
90   qDebug("destructing instance %d.  There are %d models around", id, instances);
91 }
92
93
94 void NetworkItemModel::connectService()
95 {
96 #ifdef PRETEND
97   qDebug("connectService pretending");
98 #else
99   qDebug("connectService FOR REAL");
100   m_service->Connect();
101 #endif
102 }
103
104 void NetworkItemModel::disconnectService()
105 {
106 #ifdef PRETEND
107   qDebug("disconnectService pretending");
108 #else
109   qDebug("disconnectService FOR REAL");
110   m_service->Disconnect();
111 #endif
112 }
113
114 void NetworkItemModel::removeService()
115 {
116 #ifdef PRETEND
117   qDebug("removeService pretending");
118 #else
119   qDebug("removeService FOR REAL");
120   m_service->Remove();
121 #endif
122 }
123
124 void NetworkItemModel::moveBefore(NetworkItemModel *other)
125 {
126     m_service->MoveBefore(QDBusObjectPath(other->servicePath()));
127 }
128
129 void NetworkItemModel::moveAfter(NetworkItemModel *other)
130 {
131     m_service->MoveAfter(QDBusObjectPath(other->servicePath()));
132 }
133
134 const QString& NetworkItemModel::name() const
135 {
136   return m_name;
137 }
138
139 const QString& NetworkItemModel::security() const
140 {
141   return m_security;
142 }
143
144 const NetworkItemModel::StateType& NetworkItemModel::state() const
145 {
146   return m_state;
147 }
148
149 const int& NetworkItemModel::strength() const
150 {
151   return m_strength;
152 }
153
154 const QString& NetworkItemModel::type() const
155 {
156   return m_type;
157 }
158
159 const bool& NetworkItemModel::passphraseRequired() const
160 {
161   return m_passphraseRequired;
162 }
163
164 const QString& NetworkItemModel::passphrase() const
165 {
166   return m_passphrase;
167 }
168
169 const NetworkItemModel::IPv4Type& NetworkItemModel::ipv4() const
170 {
171   return m_ipv4;
172 }
173
174 const QString& NetworkItemModel::mode() const
175 {
176   return m_mode;
177 }
178
179 const QString NetworkItemModel::ipv4address() const
180 {
181         return ipv4().Address;
182 }
183
184 const QString NetworkItemModel::ipv4netmask() const
185 {
186         return ipv4().Netmask;
187 }
188
189 const QString NetworkItemModel::ipv4gateway() const
190 {
191         return ipv4().Gateway;
192 }
193
194 const QString NetworkItemModel::ipv4method() const
195 {
196         return ipv4().Method;
197 }
198
199 const bool& NetworkItemModel::setupRequired() const
200 {
201         return m_setupRequired;
202 }
203
204 const QString NetworkItemModel::apn() const
205 {
206         return m_apn;
207 }
208
209 const QString NetworkItemModel::error() const
210 {
211         return m_error;
212 }
213
214 void NetworkItemModel::setPassphrase(const QString &passphrase)
215 {
216   Q_ASSERT(m_service);
217   QDBusPendingReply<void> reply =
218     m_service->SetProperty("Passphrase", QDBusVariant(QVariant(passphrase)));
219   reply.waitForFinished(); //FIXME: BAD
220   if (reply.isError()) {
221     qDebug()<<"got error from setProperty: "<<reply.error().message();
222     //throw -1; //FIXME: don't throw
223   }
224
225 }
226
227 void NetworkItemModel::setIpv4(const IPv4Type &ipv4)
228 {
229   Q_ASSERT(m_service);
230
231
232   StringMap dict;
233   Q_ASSERT(!ipv4.Method.isEmpty());
234   dict.insert("Method", ipv4.Method);
235   if (ipv4.Method != "dhcp") {
236     //FIXME: what do to if address and such are empty!?!
237     dict.insert("Address", ipv4.Address);
238     dict.insert("Netmask", ipv4.Netmask);
239     dict.insert("Gateway", ipv4.Gateway);
240   }
241   QVariant variant = qVariantFromValue(dict);
242   QDBusPendingReply<void> reply =
243     m_service->SetProperty(QString(IPv4), QDBusVariant(variant));
244   if (m_setPropertyWatcher) {
245     delete m_setPropertyWatcher;
246   }
247   m_setPropertyWatcher = new QDBusPendingCallWatcher(reply, this);
248   connect(m_setPropertyWatcher,
249           SIGNAL(finished(QDBusPendingCallWatcher*)),
250           this,
251           SLOT(setPropertyFinished(QDBusPendingCallWatcher*)));
252 }
253
254 void NetworkItemModel::setApn(QString value)
255 {
256         Q_ASSERT(m_service);
257
258         m_service->SetProperty(APN, QDBusVariant(QVariant(value)));
259 }
260
261 const QString& NetworkItemModel::servicePath() const
262 {
263   return m_servicePath;
264 }
265
266 const QStringList& NetworkItemModel::nameservers() const
267 {
268   return m_nameservers;
269 }
270
271 const QString& NetworkItemModel::deviceAddress() const
272 {
273   return m_deviceAddress;
274 }
275
276 void NetworkItemModel::setNameservers(const QStringList &nameservers)
277 {
278   Q_ASSERT(m_service);
279
280   if (!isListEqual(m_nameservers, nameservers)) {
281     QVariant variant = qVariantFromValue(nameservers);
282     QDBusPendingReply<void> reply =
283       m_service->SetProperty(Nameservers, QDBusVariant(variant));
284       //I hate to wait here, but I'm not sure what else to do
285       reply.waitForFinished();
286       if (reply.isError()) {
287         qDebug("got error from setProperty");
288         throw -1; //FIXME: don't throw
289       }
290   }
291 }
292
293 void NetworkItemModel::setIpv4Address(QString v)
294 {
295         m_ipv4.Address = v;
296         setIpv4(m_ipv4);
297 }
298
299 void NetworkItemModel::setIpv4Netmask(QString v )
300 {
301         m_ipv4.Netmask = v;
302         setIpv4(m_ipv4);
303 }
304
305 void NetworkItemModel::setIpv4Gateway(QString v)
306 {
307         m_ipv4.Gateway = v;
308         setIpv4(m_ipv4);
309 }
310
311 void NetworkItemModel::setIpv4Method(QString v)
312 {
313         m_ipv4.Method = v;
314         setIpv4(m_ipv4);
315 }
316
317 NetworkItemModel::StateType NetworkItemModel::state(const QString &state)
318 {
319   NetworkItemModel::StateType _state;
320   if (state == "idle") {
321         _state = StateIdle;
322   } else if (state == "failure") {
323         _state = StateFailure;
324   } else if (state == "association") {
325         _state = StateAssociation;
326   } else if (state == "configuration") {
327         _state = StateConfiguration;
328   } else if (state == "ready") {
329         _state = StateReady;
330   } else if (state == "online") {
331         _state = StateOnline;
332   } else {
333         _state = StateNone;
334         qDebug("setting to to STATE_NONE because of unknown state returned: \"%s\"", STR(state));
335   }
336
337   return _state;
338 }
339
340 //This sets the m_ipv4 with data.  It does not set the data on the
341 //Service object
342 void NetworkItemModel::_setIpv4(const QVariantMap &ipv4)
343 {
344   bool modified = false;
345   QString string;
346
347   string = ipv4["Method"].toString();
348  // qDebug("Method: %s", STR(string));
349   if (m_ipv4.Method != string) {
350     m_ipv4.Method = string;
351     modified = true;
352     methodChanged();
353   }
354   string = ipv4["Address"].toString();
355   //qDebug("Address: %s", STR(string));
356   if (m_ipv4.Address != string) {
357     m_ipv4.Address = string;
358     modified = true;
359     addressChanged();
360   }
361   string =  ipv4["Netmask"].toString();
362   //qDebug("Netmask: %s", STR(string));
363   if (m_ipv4.Netmask != string) {
364     m_ipv4.Netmask = string;
365     modified = true;
366     netmaskChanged();
367   }
368   string = ipv4["Gateway"].toString();
369  // qDebug("Gateway: %s", STR(string));
370   if (m_ipv4.Gateway != string) {
371     m_ipv4.Gateway = string;
372     modified = true;
373     gatewayChanged();
374   }
375 }
376
377 bool NetworkItemModel::isListEqual(const QStringList &a, const QStringList &b) const
378 {
379   if (a.count() != b.count()) {
380     return false;
381   }
382   for (int i=0; i < a.count(); i++) {
383     if (a.at(i) != b.at(i)) {
384       return false;
385     }
386   }
387   return true;
388 }
389
390
391
392 void NetworkItemModel::getPropertiesReply(QDBusPendingCallWatcher *call)
393 {
394   QDBusPendingReply<QVariantMap> reply = *call;
395   if (reply.isError()) {
396         qDebug("getPropertiesReply is error!");
397     QDBusError error = reply.error();
398         qDebug("service: %s", STR(servicePath()));
399         qDebug()<<QString("type: %1 name: %2 message: %3").
400                  arg(QDBusError::errorString(error.type()))
401                  .arg(error.name())
402                  .arg(error.message());
403         return;
404   }
405   qDebug()<<"getPropertiesReply";
406   QVariantMap properties = reply.value();
407   //although it seems dangerous as some of these properties are not
408   //present, grabbing them is not, because QMap will insert the
409   //default value into the map if it isn't present.  That's "" for
410   //strings and 0 for ints/bools
411
412   m_name = qdbus_cast<QString>(properties[Name]);
413   nameChanged(m_name);
414   m_type = qdbus_cast<QString>(properties[Type]);
415   typeChanged(m_type);
416   m_mode= qdbus_cast<QString>(properties[Mode]);
417
418   QStringList sec = qdbus_cast<QStringList>(properties[Security]);
419
420   if(sec.count() > 0)
421   {
422       m_security = sec.at(0);
423       securityChanged(m_security);
424   }
425
426   m_passphraseRequired = qdbus_cast<bool>(properties[PassphraseRequired]);
427   m_passphrase = qdbus_cast<QString>(properties[Passphrase]);
428   passphraseChanged(m_passphrase);
429   m_strength = qdbus_cast<int>(properties[Strength]);
430   strengthChanged(m_strength);
431   m_state = state(qdbus_cast<QString>(properties[State]));
432   _setIpv4(qdbus_cast<QVariantMap>(properties[IPv4Normal]));
433   m_nameservers = qdbus_cast<QStringList>(properties[Nameservers]);
434   m_deviceAddress = qdbus_cast<QVariantMap>(properties["Ethernet"])["Address"].toString();
435   m_apn = qdbus_cast<QString>(properties[APN]);
436   m_error = qdbus_cast<QString>(properties["Error"]);
437   errorChanged();
438   m_setupRequired = qdbus_cast<bool>(properties[SetupRequired]);
439   emit propertyChanged("","");
440 }
441
442 void NetworkItemModel::propertyChanged(const QString &name,
443                                        const QDBusVariant &value)
444 {
445   qDebug()<<"NetworkItemModel: property "<<STR(name)<<" changed: "<<value.variant();
446     if (name == State) {
447           m_state = state(value.variant().toString());
448           stateChanged(m_state);
449     } else if (name == Name) {
450                 m_name = (value.variant().toString());
451                 nameChanged(m_name);
452     } else if (name == Type) {
453           m_type = (value.variant().toString());
454           typeChanged(m_type);
455     } else if (name == Mode) {
456           m_mode = (value.variant().toString());
457         } else if (name == Security) {
458                 QStringList sec = qdbus_cast<QStringList>(value.variant());
459
460                 if(sec.count() > 0)
461                 {
462                         m_security = sec.at(0);
463                         securityChanged(m_security);
464                 }
465     } else if (name == PassphraseRequired) {
466           m_passphraseRequired = (value.variant().toBool());
467     } else if (name == Passphrase) {
468           m_passphrase = (value.variant().toString());
469           passphraseChanged(m_passphrase);
470     } else if (name == Strength) {
471           m_strength = (value.variant().toInt());
472           strengthChanged(m_strength);
473         } else if (name == IPv4 || name == IPv4Normal) {
474           _setIpv4(qdbus_cast<QVariantMap>(value.variant()));
475     } else if (name == Nameservers) {
476           m_nameservers = (value.variant().toStringList());
477     } else if (name == "Ethernet") {
478           m_deviceAddress = (qdbus_cast<QVariantMap>(value.variant())["Address"].toString());
479         } else if (name == SetupRequired) {
480            m_setupRequired = value.variant().toBool();
481            setupRequiredChanged(m_setupRequired);
482         } else if (name == APN) {
483                 m_apn = value.variant().toString();
484         } else if (name == "Error") {
485                 m_error = value.variant().toString();
486                 errorChanged();
487         } else {
488           qDebug("We don't do anything with property: %s", STR(name));
489     }
490
491         emit propertyChanged(name,value.variant());
492 }
493
494 void NetworkItemModel::setPropertyFinished(QDBusPendingCallWatcher *call)
495 {
496   QDBusPendingReply<void> reply = *call;
497   if (reply.isError()) {
498         qDebug()<<"not continuing because of error in setProperty!"<<reply.error().message();
499         m_error = reply.error().message();
500         errorChanged();
501   } else {
502     QDBusPendingReply<void> nextReply = m_service->Disconnect();
503     if (m_setPropertyWatcher) {
504       delete m_setPropertyWatcher;
505     }
506     m_setPropertyWatcher = new QDBusPendingCallWatcher(nextReply, this);
507     connect(m_setPropertyWatcher,
508             SIGNAL(finished(QDBusPendingCallWatcher*)),
509             this,
510             SLOT(disconnectFinished(QDBusPendingCallWatcher*)));
511   }
512 }
513
514 void NetworkItemModel::disconnectFinished(QDBusPendingCallWatcher *call)
515 {
516   QDBusPendingReply<void> reply = *call;
517   if (reply.isError()) {
518         qDebug("not continuing because of error in disconnect!");
519   } else {
520     QDBusPendingReply<void> nextReply = m_service->Connect();
521     if (m_setPropertyWatcher) {
522       delete m_setPropertyWatcher;
523     }
524     m_disconnectWatcher = new QDBusPendingCallWatcher(nextReply, this);
525     connect(m_disconnectWatcher,
526             SIGNAL(finished(QDBusPendingCallWatcher*)),
527             this,
528             SLOT(connectFinished(QDBusPendingCallWatcher*)));
529   }
530 }
531
532 void NetworkItemModel::connectFinished(QDBusPendingCallWatcher *call)
533 {
534   QDBusPendingReply<void> reply = *call;
535   if (reply.isError()) {
536         qDebug("error calling connect!");
537   } else {
538         qDebug("connect finished without error");
539   }
540 }
541