2
Copyright 2008 Will Stephenson <wstephenson@kde.org>
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License or (at your option) version 3 or any later version
8
accepted by the membership of KDE e.V. (or its successor approved
9
by the membership of KDE e.V.), which shall act as a proxy
10
defined in Section 14 of version 3 of the license.
12
This program 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
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program. If not, see <http://www.gnu.org/licenses/>.
21
#include "interfacegroup.h"
23
#include <NetworkManager.h>
24
#include <nm-setting-connection.h>
25
#include <nm-setting-wireless.h>
27
#include <QGraphicsLinearLayout>
29
#include <KNotification>
30
#include <KToolInvocation>
32
#include <solid/control/networkserialinterface.h>
33
#include <solid/control/wirednetworkinterface.h>
34
#include <solid/control/wirelessaccesspoint.h>
35
#include <solid/control/wirednetworkinterface.h>
36
#include <solid/control/wirelessnetworkinterface.h>
39
#include "interfaceitem.h"
40
#include "connectionitem.h"
41
#include "wirelessconnectionitem.h"
42
#include "connectioninspector.h"
43
#include "networkmanagersettings.h"
44
#include "remoteconnection.h"
45
#include "serialinterfaceitem.h"
46
#include "wiredinterfaceitem.h"
47
#include "wirelessinterfaceitem.h"
48
#include "wirelessenvironment.h"
49
#include "wirelessnetworkitem.h"
50
#include "mergedwireless.h"
52
QDebug operator<<(QDebug s, const AbstractWirelessNetwork*wl )
54
s.nospace() << "Wireless(" << qPrintable(wl->ssid() ) << "," << wl->strength() << ")";
58
bool wirelessNetworkGreaterThanStrength(AbstractWirelessNetwork* n1, AbstractWirelessNetwork * n2);
60
InterfaceGroup::InterfaceGroup(Solid::Control::NetworkInterface::Type type,
61
NetworkManagerSettings * userSettings,
62
NetworkManagerSettings * systemSettings,
63
QGraphicsWidget * parent)
64
: ConnectionList(userSettings, systemSettings, parent), m_type(type),
65
m_wirelessEnvironment(new WirelessEnvironmentMerged(this)),
66
m_interfaceLayout(new QGraphicsLinearLayout(Qt::Vertical)),
67
m_networkLayout(new QGraphicsLinearLayout(Qt::Vertical)),
70
if (m_type == Solid::Control::NetworkInterface::Ieee80211) {
71
m_enabled = Solid::Control::NetworkManager::isWirelessEnabled();
73
m_enabled = Solid::Control::NetworkManager::isNetworkingEnabled();
75
connect(m_wirelessEnvironment, SIGNAL(networkAppeared(const QString&)), SLOT(refreshConnectionsAndNetworks()));
76
connect(m_wirelessEnvironment, SIGNAL(networkDisappeared(const QString&)), SLOT(refreshConnectionsAndNetworks()));
77
connect(this, SIGNAL(connectionListUpdated()), SLOT(refreshConnectionsAndNetworks()));
79
m_layout->setSpacing(0);
80
m_interfaceLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
81
m_interfaceLayout->setSpacing(4);
82
m_networkLayout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
83
m_networkLayout->setSpacing(4);
84
kDebug() << "TYPE" << m_type;
86
if (m_type == Solid::Control::NetworkInterface::Gsm) {
87
setMinimumSize(QSize(285, 60)); // WTF?
91
InterfaceGroup::~InterfaceGroup()
93
qDeleteAll( m_interfaces );
96
void InterfaceGroup::setEnabled(bool enable)
99
foreach (InterfaceItem * item, m_interfaces) {
100
item->setEnabled(enable);
105
void InterfaceGroup::setupHeader()
107
m_layout->insertItem(0, m_interfaceLayout);
108
// create an interfaceItem for each interface of our type
109
foreach (Solid::Control::NetworkInterface * iface, Solid::Control::NetworkManager::networkInterfaces()) {
110
if (iface->type() == interfaceType()) {
111
addInterfaceInternal(iface);
112
//kDebug() << "Network Interface:" << iface->interfaceName() << iface->driver() << iface->designSpeed();
115
// hook up signals to allow us to change the connection list depending on APs present, etc
116
connect(Solid::Control::NetworkManager::notifier(), SIGNAL(networkInterfaceAdded(const QString&)),
117
SLOT(interfaceAdded(const QString&)));
118
connect(Solid::Control::NetworkManager::notifier(), SIGNAL(networkInterfaceRemoved(const QString&)),
119
SLOT(interfaceRemoved(const QString&)));
121
if (m_interfaces.count() == 0) {
127
void InterfaceGroup::setupFooter()
130
m_layout->addItem(m_networkLayout);
131
//kDebug() << m_interfaces.keys() << "Footer update";
132
//kDebug() << m_interfaces.keys() << m_networks.keys() << "Footer .. CONNECT";
133
connect(this, SIGNAL(connectionListUpdated()), SLOT(updateConnections()));
136
void InterfaceGroup::updateConnections()
139
if ( m_networkToConnect.isNull() )
142
ServiceConnectionHash::iterator i = m_connections.begin();
143
while (i != m_connections.end()) {
144
ConnectionItem * item = i.value();
145
QVariantMapMap settings = item->connection()->settings();
146
QString ssid = settings[ NM_SETTING_WIRELESS_SETTING_NAME ] [ NM_SETTING_WIRELESS_SSID ].toString();
147
if ( ssid == m_networkToConnect )
149
activateConnection( item );
156
void InterfaceGroup::updateNetworks()
160
foreach (WirelessNetworkItem * i, m_networks) {
161
m_networkLayout->removeItem(i);
167
//kDebug() << "INTERFACE IS ON ............................";
168
m_networkLayout->setSpacing(0);
169
foreach (AbstractWirelessNetwork * i, networksToShow()) {
170
addNetworkInternal(i->ssid());
172
//kDebug() << "Now ... " << m_networks.keys();
174
//kDebug() << "Interface disabled ................ :-(";
177
m_networkLayout->invalidate();
178
m_interfaceLayout->invalidate();
179
m_layout->invalidate();
181
m_networkLayout->updateGeometry();
182
m_interfaceLayout->updateGeometry();
183
m_layout->updateGeometry();
187
void InterfaceGroup::setNetworksLimit( int wlans )
189
int old = m_numberOfWlans;
190
m_numberOfWlans = wlans;
191
if (old != m_numberOfWlans) {
197
QList<AbstractWirelessNetwork*> InterfaceGroup::networksToShow()
199
QList<AbstractWirelessNetwork*> allNetworks;
200
QList<AbstractWirelessNetwork*> topNetworks;
202
kDebug() << "m_conn empty?" << m_connections.isEmpty() << "m_userSettings" << m_userSettings->isValid();
204
// check whether we have a connection for every ssid seen, if so, don't show it.
205
foreach (QString ssid, m_wirelessEnvironment->networks()) {
206
AbstractWirelessNetwork * net = m_wirelessEnvironment->findNetwork(ssid);
207
// trying out excluding networks based on any existing connection
208
bool connectionForNetworkExists = false;
209
foreach (ConnectionItem * connectionItem, m_connections) {
210
RemoteConnection * conn = connectionItem->connection();
211
QVariantMapMap settings = conn->settings();
213
QVariantMap connectionSetting = settings.value(QLatin1String(NM_SETTING_CONNECTION_SETTING_NAME));
214
if (connectionSetting.value(QLatin1String(NM_SETTING_CONNECTION_TYPE)).toString() == QLatin1String(NM_SETTING_WIRELESS_SETTING_NAME)) {
215
QVariantMap wirelessSetting = settings.value(QLatin1String(NM_SETTING_WIRELESS_SETTING_NAME));
216
// does this connection match the ssid?
217
QString connectionSsid = wirelessSetting.value(QLatin1String(NM_SETTING_WIRELESS_SSID)).toString();
218
connectionForNetworkExists |= (connectionSsid == ssid);
221
if (!connectionForNetworkExists) {
222
allNetworks.append(net);
227
qSort(allNetworks.begin(), allNetworks.end(), wirelessNetworkGreaterThanStrength);
229
//return the configured number of networks to show
230
topNetworks = allNetworks.mid(0, m_numberOfWlans);
234
void InterfaceGroup::addInterfaceInternal(Solid::Control::NetworkInterface* iface)
237
if (!m_interfaces.contains(iface->uni())) {
238
InterfaceItem * interface = 0;
239
WiredInterfaceItem * wiredinterface = 0;
240
WirelessInterfaceItem * wirelessinterface = 0;
241
SerialInterfaceItem * serialinterface = 0;
242
ConnectionInspector * inspector = 0;
243
if (iface->type() != m_type) {
246
switch (iface->type()) {
247
case Solid::Control::NetworkInterface::Ieee80211:
248
wirelessinterface = new WirelessInterfaceItem(static_cast<Solid::Control::WirelessNetworkInterface *>(iface), m_userSettings, m_systemSettings, InterfaceItem::InterfaceName, this);
249
connect(wirelessinterface, SIGNAL(stateChanged()), this, SLOT(updateNetworks()));
250
wirelessinterface->setEnabled(Solid::Control::NetworkManager::isWirelessEnabled());
252
// keep track of rf kill changes
253
QObject::disconnect(Solid::Control::NetworkManager::notifier(), SIGNAL(wirelessEnabledChanged(bool)), this, 0 );
254
QObject::disconnect(Solid::Control::NetworkManager::notifier(), SIGNAL(wirelessHardwareEnabledChanged(bool)), this, 0 );
255
QObject::connect(Solid::Control::NetworkManager::notifier(), SIGNAL(wirelessEnabledChanged(bool)),
256
this, SLOT(setEnabled(bool)));
257
QObject::connect(Solid::Control::NetworkManager::notifier(), SIGNAL(wirelessHardwareEnabledChanged(bool)),
258
this, SLOT(setEnabled(bool)));
260
m_wirelessEnvironment->addWirelessEnvironment(wirelessinterface->wirelessEnvironment());
261
interface = wirelessinterface;
262
inspector = new WirelessConnectionInspector(static_cast<Solid::Control::WirelessNetworkInterface*>(iface), wirelessinterface->wirelessEnvironment());
263
kDebug() << "WiFi added";
265
case Solid::Control::NetworkInterface::Serial:
266
interface = serialinterface = new SerialInterfaceItem(static_cast<Solid::Control::SerialNetworkInterface *>(iface),
267
m_userSettings, m_systemSettings, InterfaceItem::InterfaceName, this);
268
inspector = new PppoeConnectionInspector;
270
case Solid::Control::NetworkInterface::Gsm:
271
interface = serialinterface = new SerialInterfaceItem(static_cast<Solid::Control::SerialNetworkInterface *>(iface),
272
m_userSettings, m_systemSettings, InterfaceItem::InterfaceName, this);
273
// TODO: When ModemManager support is added, connect signals from the SII to
274
// reassesConnectionList
275
inspector = new GsmConnectionInspector;
277
case Solid::Control::NetworkInterface::Cdma:
278
interface = serialinterface = new SerialInterfaceItem(static_cast<Solid::Control::SerialNetworkInterface *>(iface),
279
m_userSettings, m_systemSettings, InterfaceItem::InterfaceName, this);
280
inspector = new CdmaConnectionInspector;
281
// TODO: When ModemManager support is added, connect signals from the SII to
282
// reassesConnectionList
285
case Solid::Control::NetworkInterface::Ieee8023:
286
interface = wiredinterface = new WiredInterfaceItem(static_cast<Solid::Control::WiredNetworkInterface *>(iface),
287
m_userSettings, m_systemSettings, InterfaceItem::InterfaceName, this);
288
inspector = new WiredConnectionInspector(static_cast<Solid::Control::WiredNetworkInterface*>(iface));
291
interface->setConnectionInspector(inspector);
292
interface->setEnabled(m_enabled);
293
m_interfaceLayout->addItem(interface);
294
m_interfaces.insert(iface->uni(), interface);
295
//m_interfaceLayout->invalidate();
296
m_interfaceLayout->updateGeometry();
304
void InterfaceGroup::addNetworkInternal(const QString & ssid)
306
//kDebug() << "Adding network:" << ssid << m_networks.keys();
307
if (!m_networks.contains(ssid)) {
308
AbstractWirelessNetwork * net = m_wirelessEnvironment->findNetwork(ssid);
309
WirelessNetworkItem * netItem = new WirelessNetworkItem(net, this);
310
netItem->setupItem();
311
m_networkLayout->addItem(netItem);
312
m_networks.insert(ssid, netItem);
313
connect(netItem, SIGNAL(clicked(AbstractConnectableItem*)),
314
SLOT(connectToWirelessNetwork(AbstractConnectableItem*)));
318
bool InterfaceGroup::accept(RemoteConnection * conn) const
320
// there was some code I don't remember the purpose of in addConnectionInternal before it was refactored here
321
// that cast to WirelessConnectionItem, then did the same interface accept() loop. ...?
322
bool accepted = false;
323
foreach (InterfaceItem * iface, m_interfaces) {
324
//kDebug() << conn << iface->connectionInspector()->accept(conn);
325
if (iface->connectionInspector()->accept(conn)) {
333
ConnectionItem * InterfaceGroup::createItem(RemoteConnection* connection)
335
ConnectionItem * ci = 0;
336
if (m_type == Solid::Control::NetworkInterface::Ieee80211) {
337
// get connection ssid. In theory we know that the connection _has_ an ssid because the
338
// WirelessConnectionInspector accepted it.
339
QVariantMapMap settings = connection->settings();
340
if ( settings.contains(QLatin1String(NM_SETTING_WIRELESS_SETTING_NAME))) {
341
QVariantMap connectionSetting = settings.value(QLatin1String(NM_SETTING_WIRELESS_SETTING_NAME));
342
if (connectionSetting.contains(QLatin1String(NM_SETTING_WIRELESS_SSID))) {
343
QString ssid = connectionSetting.value(QLatin1String(NM_SETTING_WIRELESS_SSID)).toString();
344
WirelessConnectionItem * wi = new WirelessConnectionItem(connection, this);
346
wi->setNetwork(m_wirelessEnvironment->findNetwork(ssid));
350
ci = new ConnectionItem(connection, this);
358
Solid::Control::NetworkInterface::Type InterfaceGroup::interfaceType() const
363
void InterfaceGroup::interfaceAdded(const QString& uni)
365
if (m_interfaces.keys().contains(uni)) {
368
kDebug() << "Interface Added.";
369
Solid::Control::NetworkInterface * iface = Solid::Control::NetworkManager::findNetworkInterface(uni);
370
addInterfaceInternal(iface);
371
KNotification::event(Event::HwAdded, i18nc("Notification for hardware added", "Network interface %1 attached", iface->interfaceName()), QPixmap(), 0, KNotification::CloseOnTimeout, KComponentData("networkmanagement", "networkmanagement", KComponentData::SkipMainComponentRegistration));
376
void InterfaceGroup::interfaceRemoved(const QString& uni)
378
if (m_interfaces.contains(uni)) {
379
InterfaceItem * item = m_interfaces.take(uni);
380
m_interfaceLayout->removeItem(item);
381
KNotification::event(Event::HwRemoved, i18nc("Notification for hardware removed", "Network interface removed"), QPixmap(), 0, KNotification::CloseOnTimeout, KComponentData("networkmanagement", "networkmanagement", KComponentData::SkipMainComponentRegistration));
388
void InterfaceGroup::refreshConnectionsAndNetworks()
390
//kDebug() << "Refreshing";
395
void InterfaceGroup::activateConnection(AbstractConnectableItem* item)
397
m_networkToConnect.truncate( 0 );
398
// tell the manager to activate the connection
400
// HACK - take the first one
401
ConnectionItem * ci = qobject_cast<ConnectionItem*>(item);
402
QHash<QString, InterfaceItem *>::const_iterator i = m_interfaces.constBegin();
403
if ( i != m_interfaces.constEnd()) {
404
QString firstDeviceUni = i.key();
405
Solid::Control::NetworkManager::activateConnection(firstDeviceUni, ci->connection()->service() + " " + ci->connection()->path(), QVariantMap());
406
KNotification::event(Event::Connecting, i18nc("Notification text when activating a connection","Connecting %1", ci->connection()->id()), QPixmap(), 0, KNotification::CloseOnTimeout, KComponentData("networkmanagement", "networkmanagement", KComponentData::SkipMainComponentRegistration));
408
// if the manager updates the interface's state, we should then refresh the list of
409
// connections(remove any active connections from the list
410
// What about a connection that could be activated on 2 devices?
411
// Ideally we should keep them around
415
void InterfaceGroup::connectToWirelessNetwork(AbstractConnectableItem* item)
417
WirelessNetworkItem * wni = qobject_cast<WirelessNetworkItem*>(item);
419
//kDebug() << wni->net()->referenceAccessPoint()->hardwareAddress();
420
QDBusInterface kcm(QLatin1String("org.kde.NetworkManager.KCModule"), QLatin1String("/default"), QLatin1String("org.kde.kcmshell.ConnectionEditor"));
422
kDebug() << "opening connection management dialog from running KCM";
424
args << wni->net()->ssid()
425
<< (quint32)wni->net()->referenceAccessPoint()->capabilities()
426
<< (quint32)wni->net()->referenceAccessPoint()->wpaFlags()
427
<< (quint32)wni->net()->referenceAccessPoint()->rsnFlags();
428
m_networkToConnect = wni->net()->ssid();
429
kcm.call(QDBus::NoBlock, "createConnection", "802-11-wireless", QVariant::fromValue(args));
431
kDebug() << "opening connection management dialog using networkmanagement_configshell";
434
QString::fromLatin1("'%1' %2 %3 %4")
435
.arg(wni->net()->ssid().replace('\'', "\\'"))
436
.arg(wni->net()->referenceAccessPoint()->capabilities())
437
.arg(wni->net()->referenceAccessPoint()->wpaFlags())
438
.arg(wni->net()->referenceAccessPoint()->rsnFlags());
440
args << QLatin1String("--type") << QLatin1String("802-11-wireless") << QLatin1String("--specific-args") << moduleArgs << QLatin1String("create");
441
m_networkToConnect = wni->net()->ssid();
442
int ret = KToolInvocation::kdeinitExec("networkmanagement_configshell", args);
443
kDebug() << ret << args;
448
bool wirelessNetworkGreaterThanStrength(AbstractWirelessNetwork* n1, AbstractWirelessNetwork * n2)
450
return n1->strength() > n2->strength();
453
// vim: sw=4 sts=4 et tw=100