2
Copyright 2008,2009 Will Stephenson <wstephenson@kde.org>
3
Copyright 2008, 2009 Sebastian Kügler <sebas@kde.org>
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License as
7
published by the Free Software Foundation; either version 2 of
8
the License or (at your option) version 3 or any later version
9
accepted by the membership of KDE e.V. (or its successor approved
10
by the membership of KDE e.V.), which shall act as a proxy
11
defined in Section 14 of version 3 of the license.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "interfaceitem.h"
24
#include "remoteinterfaceconnection.h"
25
#include "remoteactivatablelist.h"
26
#include "remoteinterfaceconnection.h"
28
#include <arpa/inet.h>
30
#include <QGraphicsGridLayout>
35
#include <KGlobalSettings>
36
#include <KIconLoader>
38
#include <kdeversion.h>
40
#include <Plasma/Animation>
41
#include <Plasma/Animator>
43
#include <Plasma/IconWidget>
44
#include <Plasma/Label>
45
#include <Plasma/Meter>
47
#include <Solid/Device>
48
#include <Solid/NetworkInterface>
49
#include <solid/control/networkinterface.h>
50
#include <solid/control/wirednetworkinterface.h>
51
#include <solid/control/networkipv4confignm09.h>
52
#include <solid/control/networkmanager.h>
54
#include "knmserviceprefs.h"
55
#include "nm-device-interface.cpp"
56
#include "nm-ip4-config-interface.cpp"
59
InterfaceItem::InterfaceItem(Solid::Control::NetworkInterfaceNm09 * iface, RemoteActivatableList* activatables, NameDisplayMode mode, QGraphicsWidget * parent) : Plasma::IconWidget(parent),
60
m_currentConnection(0),
62
m_activatables(activatables),
64
m_connectionNameLabel(0),
67
m_hasDefaultRoute(false),
70
connect(m_activatables, SIGNAL(disappeared()), this, SLOT(serviceDisappeared()));
71
connect(m_activatables, SIGNAL(activatableAdded(RemoteActivatable*, int)), SLOT(activatableAdded(RemoteActivatable*)));
72
connect(m_activatables, SIGNAL(activatableRemoved(RemoteActivatable*)), SLOT(activatableRemoved(RemoteActivatable*)));
73
setDrawBackground(true);
74
setTextBackgroundColor(QColor(Qt::transparent));
75
QString tt = i18nc("tooltip on the LHS widgets", "Click here for interface details");
77
m_pixmapSize = QSize(48, 48);
78
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
80
m_layout = new QGraphicsGridLayout(this);
81
m_layout->setVerticalSpacing(0);
82
m_layout->setColumnSpacing(0, 8);
83
m_layout->setColumnSpacing(1, 4);
84
m_layout->setColumnSpacing(2, 6);
85
m_layout->setRowSpacing(0, 6);
86
m_layout->setRowSpacing(1, 6);
87
m_layout->setPreferredWidth(240);
88
m_layout->setColumnFixedWidth(0, m_pixmapSize.width());
89
m_layout->setColumnFixedWidth(2, 16); // FIXME: spacing?
91
m_icon = new Plasma::Label(this);
92
m_icon->setToolTip(tt);
93
m_icon->setMinimumHeight(m_pixmapSize.height());
94
m_icon->setMaximumHeight(m_pixmapSize.height());
96
setMinimumHeight(m_pixmapSize.height()+6);
97
m_layout->addItem(m_icon, 0, 0, 2, 1);
98
m_icon->nativeWidget()->setPixmap(interfacePixmap());
101
m_ifaceNameLabel = new Plasma::Label(this);
102
m_ifaceNameLabel->setToolTip(tt);
103
m_ifaceNameLabel->nativeWidget()->setWordWrap(true);
104
m_ifaceNameLabel->setMaximumHeight(QFontMetrics(KGlobalSettings::generalFont()).height());
105
m_ifaceNameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
106
m_layout->addItem(m_ifaceNameLabel, 0, 1, 1, 1);
108
m_disconnectButton = new Plasma::PushButton(this);
109
m_disconnectButton->setMaximumHeight(16);
110
m_disconnectButton->setMaximumWidth(16);
111
m_disconnectButton->setIcon(KIcon("dialog-close"));
112
m_disconnectButton->setToolTip(i18nc("tooltip on disconnect icon", "Disconnect"));
113
m_disconnectButton->hide();
114
m_disconnect = false;
115
// forward disconnect signal
116
connect(m_disconnectButton, SIGNAL(clicked()), this, SLOT(emitDisconnectInterfaceRequest()));
118
m_layout->addItem(m_disconnectButton, 0, 2, 1, 1, Qt::AlignRight);
120
// active connection name
121
m_connectionNameLabel = new Plasma::Label(this);
122
m_connectionNameLabel->setToolTip(tt);
123
m_connectionNameLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
124
m_connectionNameLabel->nativeWidget()->setFont(KGlobalSettings::smallestReadableFont());
125
m_connectionNameLabel->nativeWidget()->setWordWrap(false);
126
m_connectionNameLabel->nativeWidget()->setMaximumWidth(210);
127
m_layout->addItem(m_connectionNameLabel, 1, 1, 1, 1);
130
m_connectionInfoIcon = new Plasma::Label(this);
131
m_connectionInfoIcon->setMinimumHeight(16);
132
m_connectionInfoIcon->setMinimumWidth(16);
133
m_connectionInfoIcon->setMaximumHeight(16);
134
m_connectionInfoIcon->nativeWidget()->setPixmap(KIcon("security-low").pixmap(16, 16));
135
m_connectionInfoIcon->hide(); // hide by default, we'll enable it later
137
m_layout->addItem(m_connectionInfoIcon, 1, 2, 1, 1, Qt::AlignRight); // check...
140
connect(m_iface.data(), SIGNAL(connectionStateChanged(int,int,int)),
141
this, SLOT(handleConnectionStateChange(int,int,int)));
142
connect(m_iface.data(), SIGNAL(linkUpChanged(bool)), this, SLOT(setActive(bool)));
144
setNameDisplayMode(mode);
147
if (m_iface.data()->type() == Solid::Control::NetworkInterfaceNm09::Ethernet) {
148
Solid::Control::WiredNetworkInterfaceNm09* wirediface =
149
static_cast<Solid::Control::WiredNetworkInterfaceNm09*>(m_iface.data());
150
connect(wirediface, SIGNAL(carrierChanged(bool)), this, SLOT(setActive(bool)));
152
m_state = Solid::Control::NetworkInterfaceNm09::UnknownState;
153
connectionStateChanged(static_cast<Solid::Control::NetworkInterfaceNm09::ConnectionState>(m_iface.data()->connectionState()));
156
m_layout->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
159
connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
161
qreal targetOpacity = m_enabled ? 1.0 : 0.7;
162
// Fade in when this widget appears
163
Plasma::Animation* fadeAnimation = Plasma::Animator::create(Plasma::Animator::FadeAnimation);
164
fadeAnimation->setTargetWidget(this);
165
fadeAnimation->setProperty("startOpacity", 0.0);
166
fadeAnimation->setProperty("targetOpacity", targetOpacity);
167
fadeAnimation->start();
171
InterfaceItem::~InterfaceItem()
175
void InterfaceItem::disappear()
177
Plasma::Animation* fadeAnimation = Plasma::Animator::create(Plasma::Animator::FadeAnimation);
178
fadeAnimation->setTargetWidget(this);
179
fadeAnimation->setProperty("startOpacity", 1.0);
180
fadeAnimation->setProperty("targetOpacity", 0.0);
181
fadeAnimation->start();
182
connect(fadeAnimation, SIGNAL(finished()), this, SIGNAL(disappearAnimationFinished()));
185
void InterfaceItem::showItem(QGraphicsWidget* widget, bool show)
187
Plasma::Animation* fadeAnimation = Plasma::Animator::create(Plasma::Animator::FadeAnimation);
188
fadeAnimation->setTargetWidget(widget);
191
fadeAnimation->setProperty("startOpacity", 0.0);
192
fadeAnimation->setProperty("targetOpacity", 1.0);
194
fadeAnimation->setProperty("startOpacity", 1.0);
195
fadeAnimation->setProperty("targetOpacity", 0.0);
197
fadeAnimation->start();
200
QString InterfaceItem::label()
202
return m_ifaceNameLabel->text();
205
Solid::Control::NetworkInterfaceNm09* InterfaceItem::interface()
207
return m_iface.data();
210
void InterfaceItem::setActive(bool active)
214
connectionStateChanged(static_cast<Solid::Control::NetworkInterfaceNm09::ConnectionState>(m_iface.data()->connectionState()));
218
void InterfaceItem::setEnabled(bool enable)
221
Plasma::Animation* fadeAnimation = Plasma::Animator::create(Plasma::Animator::FadeAnimation);
222
fadeAnimation->setTargetWidget(this);
224
showItem(m_connectionInfoIcon, false);
225
fadeAnimation->setProperty("startOpacity", 0.7);
226
fadeAnimation->setProperty("targetOpacity", 1.0);
228
fadeAnimation->setProperty("startOpacity", 1.0);
229
fadeAnimation->setProperty("targetOpacity", 0.7);
232
// we only animate when setEnabled is not called during initialization,
233
// as that would conflict with the appear animation
234
fadeAnimation->start();
238
void InterfaceItem::setNameDisplayMode(NameDisplayMode mode)
242
m_interfaceName = UiUtils::interfaceNameLabel(m_iface.data()->uni());
244
if (m_nameMode == InterfaceName) {
245
m_ifaceNameLabel->setText(QString("<b>%1</b>").arg(m_interfaceName));
246
} else if (m_nameMode == HardwareName) {
248
m_ifaceNameLabel->setText(QString("<b>%1</b>").arg(m_iface.data()->interfaceName()));
250
m_ifaceNameLabel->setText(i18nc("generic label for an interface", "<b>Network Interface</b>"));
254
m_ifaceNameLabel->setText(i18nc("network interface name unknown", "<b>Unknown Network Interface</b>"));
258
InterfaceItem::NameDisplayMode InterfaceItem::nameDisplayMode() const
263
QString InterfaceItem::connectionName()
265
// Default active connection's name is empty, room for improvement?
266
if (m_currentConnection) {
267
return m_currentConnection->connectionName();
272
void InterfaceItem::setConnectionInfo()
275
currentConnectionChanged();
276
connectionStateChanged(static_cast<Solid::Control::NetworkInterfaceNm09::ConnectionState>(m_iface.data()->connectionState()));
280
QString InterfaceItem::currentIpAddress()
285
if (static_cast<Solid::Control::NetworkInterfaceNm09::ConnectionState>(m_iface.data()->connectionState()) != Solid::Control::NetworkInterfaceNm09::Activated) {
286
return i18nc("label of the network interface", "No IP address.");
291
OrgFreedesktopNetworkManagerDeviceInterface devIface(NM_DBUS_SERVICE, m_iface.data()->uni(), QDBusConnection::systemBus());
292
if (devIface.isValid()) {
293
addr.setAddress(ntohl(devIface.ip4Address()));
297
return i18nc("label of the network interface", "IP display error.");
299
return addr.toString();
303
RemoteInterfaceConnection* InterfaceItem::currentConnection()
305
return m_currentConnection;
308
void InterfaceItem::setActivatableList(RemoteActivatableList* activatables)
310
m_activatables = activatables;
313
void InterfaceItem::currentConnectionChanged()
315
updateCurrentConnection(m_activatables->connectionForInterface(m_iface.data()));
318
void InterfaceItem::updateCurrentConnection(RemoteInterfaceConnection * ic)
321
if (m_currentConnection) {
322
QObject::disconnect(m_currentConnection, 0, this, 0);
324
m_currentConnection = ic;
326
connect(m_currentConnection, SIGNAL(hasDefaultRouteChanged(bool)),
327
SLOT(handleHasDefaultRouteChanged(bool)));
328
handleHasDefaultRouteChanged(m_currentConnection->hasDefaultRoute());
331
handleHasDefaultRouteChanged(false);
332
m_currentConnection = 0;
336
void InterfaceItem::handleHasDefaultRouteChanged(bool changed)
338
m_hasDefaultRoute = changed;
339
//kDebug() << "Default Route changed!!" << changed;
340
m_icon->nativeWidget()->setPixmap(interfacePixmap());
344
void InterfaceItem::pppStats(uint in, uint out)
346
kDebug() << "PPP Stats. in:" << in << "out:" << out;
349
void InterfaceItem::activeConnectionsChanged()
354
void InterfaceItem::slotClicked()
356
emit clicked(m_iface.data());
359
void InterfaceItem::handleConnectionStateChange(int new_state, int old_state, int reason)
363
connectionStateChanged((Solid::Control::NetworkInterfaceNm09::ConnectionState)new_state);
366
void InterfaceItem::handleConnectionStateChange(int new_state)
368
connectionStateChanged((Solid::Control::NetworkInterfaceNm09::ConnectionState)new_state);
371
void InterfaceItem::connectionStateChanged(Solid::Control::NetworkInterfaceNm09::ConnectionState state, bool updateConnection)
373
if (m_state == state) {
378
// get the active connections
379
// check if any of them affect our interface
380
// setActiveConnection on ourself
381
// button to connect, disconnect
382
bool old_disco = m_disconnect;
384
m_disconnect = false;
385
// Name and info labels
387
if (updateConnection) {
388
currentConnectionChanged();
390
if (m_currentConnection) {
391
lname = UiUtils::connectionStateToString(state, m_currentConnection->connectionName());
393
lname = UiUtils::connectionStateToString(state, QString());
394
// to allow updating connection's name in the next call of connectionStateChanged()
395
// even if the state has not changed.
396
m_state = Solid::Control::NetworkInterfaceNm09::UnknownState;
400
case Solid::Control::NetworkInterfaceNm09::Unavailable:
401
if (m_iface.data()->type() == Solid::Control::NetworkInterfaceNm09::Ethernet) {
402
lname = i18nc("wired interface network cable unplugged", "Cable Unplugged");
404
setEnabled(false); // FIXME: tone down colors using an animation
406
case Solid::Control::NetworkInterfaceNm09::Disconnected:
407
case Solid::Control::NetworkInterfaceNm09::Deactivating:
410
case Solid::Control::NetworkInterfaceNm09::Preparing:
411
case Solid::Control::NetworkInterfaceNm09::Configuring:
412
case Solid::Control::NetworkInterfaceNm09::NeedAuth:
413
case Solid::Control::NetworkInterfaceNm09::IPConfig:
414
case Solid::Control::NetworkInterfaceNm09::IPCheck:
415
case Solid::Control::NetworkInterfaceNm09::Secondaries:
416
case Solid::Control::NetworkInterfaceNm09::Activated:
420
case Solid::Control::NetworkInterfaceNm09::Unmanaged:
421
case Solid::Control::NetworkInterfaceNm09::Failed:
422
case Solid::Control::NetworkInterfaceNm09::UnknownState:
427
// Update connect button
428
if (old_disco != m_disconnect) {
429
showItem(m_disconnectButton, m_disconnect);
431
m_connectionNameLabel->setText(lname);
432
m_icon->nativeWidget()->setPixmap(interfacePixmap());
434
//kDebug() << "State changed" << lname;
438
QPixmap InterfaceItem::interfacePixmap(const QString &icon) {
439
// Which pixmap should we display with the notification?
440
QString overlayIcon = icon;
441
if (overlayIcon.isEmpty()) {
442
overlayIcon = "network-defaultroute";
444
//kDebug() << "painting icon" << overlayIcon;
445
QPixmap pmap = KIcon(UiUtils::iconName(m_iface.data())).pixmap(m_pixmapSize);
446
//QPixmap pmap = KIcon(icon).pixmap(QSize(KIconLoader::SizeMedium, KIconLoader::SizeMedium));
447
if (m_hasDefaultRoute && !pmap.isNull()) {
449
p.drawPixmap(QRect(2,2,18,18), KIcon(overlayIcon).pixmap(QSize(18,18)));
454
void InterfaceItem::emitDisconnectInterfaceRequest()
457
//kDebug() << m_iface->uni();
458
emit disconnectInterfaceRequested(m_iface.data()->uni());
462
void InterfaceItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
465
emit hoverEnter(m_iface.data()->uni());
467
IconWidget::hoverEnterEvent(event);
470
void InterfaceItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
473
emit hoverLeave(m_iface.data()->uni());
475
IconWidget::hoverLeaveEvent(event);
478
void InterfaceItem::serviceDisappeared()
480
m_currentConnection = 0;
483
void InterfaceItem::activatableAdded(RemoteActivatable * activatable)
485
if (m_iface && RemoteActivatableList::isConnectionForInterface(activatable, m_iface.data())) {
486
updateCurrentConnection(qobject_cast<RemoteInterfaceConnection*>(activatable));
488
/* Sometimes the activatableAdded signal arrives after the connectionStateChanged
489
signal, so update the interface state here but do not search for current connection
490
since it is already known. */
491
connectionStateChanged(m_iface.data()->connectionState(), false);
495
void InterfaceItem::activatableRemoved(RemoteActivatable * activatable)
497
if (activatable == m_currentConnection) {
498
m_currentConnection = 0;
501
// vim: sw=4 sts=4 et tw=100