You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetworkmanager/tdenetworkmanager/src/knetworkmanager-tray.cpp

1128 lines
35 KiB

/***************************************************************************
*
* knetworkmanager-tray.cpp - A NetworkManager frontend for KDE
*
* Copyright (C) 2005, 2006 Novell, Inc.
*
* Author: Timo Hoenig <thoenig@suse.de>, <thoenig@nouse.net>
* Will Stephenson <wstephenson@suse.de>, <wstephenson@kde.org>
* Valentine Sinitsyn <e_val@inbox.ru>
* Helmut Schaa <hschaa@suse.de>, <helmut.schaa@gmx.de>
* Alexander Naumov <anaumov@suse.de>, <posix.ru@gmail.com>
* Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
class WirelessDialog;
#include <tqsignalmapper.h>
#include <tqevent.h>
#include <tqvbox.h>
#include <tqlayout.h>
#include <tqpushbutton.h>
#include <tqpixmap.h>
#include <tqpixmapcache.h>
#include <tqpainter.h>
#include <tqstyle.h>
#include <tqvaluelist.h>
#include <dcopclient.h>
#include <tqdbusobjectpath.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <knotifyclient.h>
#include <knotifydialog.h>
#include <klocale.h>
#include <kstdguiitem.h>
#include <khelpmenu.h>
#include <kprocess.h>
#include <kiconloader.h>
#include <kconfig.h>
#include <kmessagebox.h>
#include <tqpushbutton.h>
#include <tqlayout.h>
#include <tqlabel.h>
#include <tqapplication.h>
#include <tqdialog.h>
#include <NetworkManager.h>
#include <NetworkManagerVPN.h>
#include <tqdbuserror.h>
#include "xmlmarshaller.h"
#include "vpn_tray_component.h"
#include "devicetraycomponent.h"
#include "knetworkmanager-cellular_device_tray.h"
#include "knetworkmanager-cellular_device.h"
#include "knetworkmanager-device.h"
#include "knetworkmanager-devicestore.h"
#include "knetworkmanager-tray.h"
#include "knetworkmanager-menu_subhead.h"
#include "knetworkmanager-nm_proxy.h"
#include "knetworkmanager-connection.h"
#include "knetworkmanager-connection_setting_info.h"
#include "knetworkmanager-connection_settings_dialog.h"
#include "knetworkmanager-connection_store.h"
#include "knetworkmanager-vpn_connection.h"
#include "knetworkmanager-connection.h"
#include "knetworkmanager-storage.h"
#include "knetworkmanager-connection_editor.h"
#include "knetworkmanager-vpnauthenticationdialog.h"
#include "knetworkmanager-wired_device.h"
#include "knetworkmanager-wired_device_tray.h"
#include "knetworkmanager-wireless_device_tray.h"
#include "knetworkmanager-wireless_device.h"
#include <stdio.h>
#define KDED_NETWORK_NAME "NMNetwork"
#if !defined(NM_CHECK_VERSION)
#define NM_CHECK_VERSION(x,y,z) 0
#endif
extern unsigned int current_vpn_state;
NMDeviceState nm_device_state_global;
extern unsigned char vpn_new_credentials_needed;
NewSecretsDialog::NewSecretsDialog(ConnectionSettings::Connection *connection, TQWidget * parent, const char * name, bool modal, TQt::WFlags f)
: TQDialog(parent, name, modal, f)
{
_connection = connection;
init();
}
NewSecretsDialog::~NewSecretsDialog ()
{
}
void NewSecretsDialog::slotDialogEdit()
{
ConnectionSettingsDialogImpl* dlg = new ConnectionSettingsDialogImpl(_connection, false, NULL, Tray::getInstance(), "Edit connection");
dlg->show();
close();
}
void NewSecretsDialog::reject()
{
_connection->slotSecretsError();
TQDialog::reject();
}
void NewSecretsDialog::init()
{
ConnectionSettings::GenericConnection* conn = dynamic_cast<ConnectionSettings::GenericConnection*>(_connection);
// if we do not have a connection bail out
if (!conn)
{
reject();
return;
}
// show a message to the user that the connection failed
// and allow edit or cancel
TQLabel* label = new TQLabel(tqtr(" The connection %1 could not be established ").arg(conn->getInfoSetting()->getName()), this);
TQPushButton* buttonEdit = new TQPushButton(tr("&Edit"), this);
TQPushButton* buttonCancel = new TQPushButton(tr("&Cancel"), this);
TQHBoxLayout *topLeftLayout = new TQHBoxLayout();
topLeftLayout->addWidget(buttonEdit);
topLeftLayout->addWidget(buttonCancel);
TQVBoxLayout *mainLayout = new TQVBoxLayout(this);
mainLayout->setMargin(15);
mainLayout->setSpacing(10);
mainLayout->addWidget(label);
mainLayout->addLayout(topLeftLayout);
connect(buttonEdit, TQT_SIGNAL(clicked()), TQT_SLOT(slotDialogEdit()));
connect(buttonCancel, TQT_SIGNAL(clicked()), this, TQT_SLOT(close()));
}
class TrayPrivate
{
public:
TrayPrivate(TQObject* parent)
: foregroundTrayComponent(0)
, signalMapper(parent, "signal_mapper")
, current_idx(0)
{}
~TrayPrivate() {}
static Tray* tray;
TQValueList<TrayComponent*> trayComponents;
DeviceTrayComponent * foregroundTrayComponent;
TQSignalMapper signalMapper;
TQMap<int, TQPair<ConnectionSettings::Connection*, Device*> > act_conn_map;
int current_idx;
};
Tray* TrayPrivate::tray = NULL;
Tray* Tray::getInstance()
{
if (TrayPrivate::tray)
return TrayPrivate::tray;
else return (TrayPrivate::tray = new Tray());
}
void Tray::slotEditConnections()
{
ConnectionEditorImpl* dlg = new ConnectionEditorImpl(this);
dlg->show();
}
void Tray::slotEnableWireless()
{
NMProxy* nm = NMProxy::getInstance();
TQT_DBusError err;
if (!nm) return;
nm->setWirelessEnabled(true, err);
}
void Tray::slotDisableWireless()
{
NMProxy* nm = NMProxy::getInstance();
TQT_DBusError err;
if (!nm) return;
nm->setWirelessEnabled(false, err);
}
void Tray::slotOfflineMode()
{
NMProxy* nm = NMProxy::getInstance();
TQT_DBusError err;
if (!nm) return;
nm->Sleep(true, err);
}
void Tray::slotOnlineMode()
{
NMProxy* nm = NMProxy::getInstance();
TQT_DBusError err;
if (!nm) return;
nm->Sleep(false, err);
}
void Tray::slotNewVPNConnection()
{
printf("Creating new VPN connection\n\r");
// create a new VPN connection
Connection* conn = new VPNConnection();
// edit the new connection
ConnectionSettingsDialogImpl* dlg = new ConnectionSettingsDialogImpl(conn, true, NULL, this, "connect_something", false, TQt::WDestructiveClose);
dlg->show();
}
void Tray::contextMenuAboutToShow (KPopupMenu* menu)
{
TQT_DBusError err;
NMProxy* nm = NMProxy::getInstance();
// clear menu
menu->clear();
if (nm->isNMRunning())
{
// actions for each Device
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin();
it != d->trayComponents.end();
++it)
{
(*it)->addMenuItems(menu);
}
// Submenu title
Subhead* subhead = new Subhead (menu, "subhead", TQString("Connection Management"), SmallIcon("knetworkmanager_disabled", TQIconSet::Automatic));
menu->insertItem (subhead, -1, -1);
// New connection
KAction * newConnAction = 0;
int devices = d->trayComponents.count();
if ( devices > 1 ) {
newConnAction = actionCollection ()->action ("new_connection_menu");
KActionMenu* newConnActionMenu = static_cast<KActionMenu*>(newConnAction);
newConnActionMenu->popupMenu()->clear();
TQValueList<TrayComponent*>::Iterator it;
for (it = d->trayComponents.begin();
it != d->trayComponents.end();
++it)
{
DeviceTrayComponent* dev_comp = dynamic_cast<DeviceTrayComponent*> (*it);
KAction * deviceNewConnAction = 0;
if (dev_comp)
{
TQString actionName = TQString("new_connection_%1").arg(dev_comp->device()->getInterface());
TQString menuCaption = TQString("%1").arg(dev_comp->device()->getInterface());
if (menuCaption.contains("eth", FALSE) > 0) {
menuCaption = menuCaption.insert(0, "Wired Connection (");
}
else if (menuCaption.contains("wlan", FALSE) > 0) {
menuCaption = menuCaption.insert(0, "Wireless Connection (");
}
else if (menuCaption.contains("pan", FALSE) > 0) {
menuCaption = menuCaption.insert(0, "Private Area Connection (");
}
else {
menuCaption = menuCaption.insert(0, "Unknown Connection (");
}
menuCaption = menuCaption.append(")");
deviceNewConnAction = actionCollection ()->action (actionName);
if (!deviceNewConnAction) {
deviceNewConnAction = new KAction (menuCaption, 0, (*it), TQT_SLOT(newConnection()), actionCollection(), actionName);
}
newConnActionMenu->insert(deviceNewConnAction);
}
}
// New VPN connection option
++it;
KAction * deviceNewConnAction = 0;
TQString menuCaption = "VPN Connection";
TQString actionName = TQString("new_connection_%1").arg("vpn");
deviceNewConnAction = new KAction (menuCaption, 0, TQT_TQOBJECT(this), TQT_SLOT(slotNewVPNConnection()), actionCollection(), actionName);
newConnActionMenu->insert(deviceNewConnAction);
} else if ( devices == 1 ) {
newConnAction = actionCollection ()->action ("new_connection");
TQT_BASE_OBJECT_NAME::disconnect( newConnAction, TQT_SIGNAL(activated()) );
TQT_BASE_OBJECT_NAME::connect( newConnAction, TQT_SIGNAL(activated()), d->trayComponents[0], TQT_SLOT(newConnection()));
}
if (newConnAction) {
newConnAction->plug(menu);
}
// turn things off
if (nm)
{
KActionMenu* disableStuffActionMenu = static_cast<KActionMenu*>(actionCollection ()->action ("deactivate_menu") );
disableStuffActionMenu->popupMenu()->clear();
TQValueList<TQPair<ConnectionSettings::Connection*, Device*> > map = nm->getActiveConnectionsMap();
d->act_conn_map.clear();
for (TQValueList<TQPair<ConnectionSettings::Connection*, Device*> >::Iterator it = map.begin(); it != map.end(); ++it)
{
ConnectionSettings::GenericConnection* conn = dynamic_cast<ConnectionSettings::GenericConnection*>((*it).first);
Device* dev = (*it).second;
if (!conn)
continue;
TQString actionName = TQString("disable_connection_%1_%2").arg(conn->getID()).arg(dev ? dev->getInterface() : "");
KAction * deviceNewConnAction = actionCollection ()->action (actionName);
TQString actionText = conn->getInfoSetting()->getName();
if (dev)
actionText += TQString(" (%1)").arg(dev->getInterface());
if (!deviceNewConnAction) {
deviceNewConnAction = new KAction (actionText, 0, &d->signalMapper, TQT_SLOT(map()), actionCollection(), actionName);
}
d->signalMapper.setMapping(deviceNewConnAction, d->current_idx);
d->act_conn_map.insert(d->current_idx, TQPair<ConnectionSettings::Connection*, Device*> (conn, dev));
d->current_idx++;
disableStuffActionMenu->insert(deviceNewConnAction);
}
// disable wireless
if (nm->getWirelessHardwareEnabled(err))
{
KAction* wireless = NULL;
if (nm->getWirelessEnabled(err)) {
wireless = actionCollection ()->action ("disable_wireless");
} else {
wireless = actionCollection ()->action ("enable_wireless");
}
disableStuffActionMenu->insert(wireless);
}
// offline vs. online mode
KAction* switch_mode = NULL;
if (nm->getState(err) != NM_STATE_ASLEEP) {
switch_mode = actionCollection ()->action ("offline_mode");
}
else {
switch_mode = actionCollection ()->action ("online_mode");
}
disableStuffActionMenu->insert(switch_mode);
disableStuffActionMenu->plug(menu);
}
}
else
{
Subhead* subhead = new Subhead (menu, "subhead", i18n("NetworkManager is not running"), SmallIcon("stop", TQIconSet::Automatic));
menu->insertItem (subhead, -1, -1);
}
// Notifications
KAction* notif = actionCollection()->action("configure_notifications");
notif->plug(menu);
// Connection Editor
KAction* edit = actionCollection ()->action ("edit_connections");
edit->plug(menu);
// quit
menu->insertSeparator ();
KAction* quitAction = actionCollection ()->action (KStdAction::name (KStdAction::Quit));
if (quitAction)
quitAction->plug (menu);
}
void
Tray::slotStateChanged(TQ_UINT32 state)
{
NMState nm_state = (NMState) state;
// change tray icon according to NM's state
switch(nm_state)
{
case NM_STATE_UNKNOWN:
case NM_STATE_ASLEEP:
case NM_STATE_CONNECTING:
case NM_STATE_DISCONNECTED:
setPixmap (loadIcon ("knetworkmanager_disabled"));
break;
case NM_STATE_CONNECTED:
setPixmap (loadIcon ("knetworkmanager"));
break;
}
printf("NM state: %d\n\r", nm_state);
}
void
Tray::enterEvent (TQEvent* /*e*/)
{
// show tooltip
TQToolTip::remove (this);
TQString tooltip = "";
// build up the tooltip from all tray components
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin(); it != d->trayComponents.end(); ++it)
{
TrayComponent* comp = *it;
if (comp->getToolTipText().isEmpty())
continue;
if (!tooltip.isEmpty())
tooltip += "\n\n";
tooltip += comp->getToolTipText().join("\n");
}
if (!tooltip.isEmpty())
TQToolTip::add (this, tooltip);
}
void
Tray::slotVPNSecretsNeeded(ConnectionSettings::Connection* connection, ConnectionSettings::ConnectionSetting* setting, const TQStringList& hints, bool request_new)
{
#warning Implement Tray::slotVPNSecretsNeeded to handle parms properly
Q_UNUSED(hints);
Storage* storage = Storage::getInstance();
bool hasSecretsStored = storage->hasSecretsStored(connection, setting);
printf("Tray::slotVPNSecretsNeeded\n\r");
kdDebug() << "Tray::slotVPNSecretsNeeded" << endl;
// default secrets handling for all other connection types
// 1) if we have secrets stored, restore them and send them back to NM
// 2) if NM requests new secrets we should allow the user to retry the
// connection or to edit it
//if (hasSecretsStored && (!request_new))
if (hasSecretsStored)
{
printf("Tray::slotVPNSecretsNeeded: Restoring saved secrets\n\r");
// We have secrets stored, restore them
// if (storage->restoreVPNSecrets(connection, setting))
// {
int number_of_secrets_found = 0;
ConnectionSettings::VPNConnection* conn = dynamic_cast<ConnectionSettings::VPNConnection*>(connection);
TQString id = connection->getID();
TQString type = setting->getType();
printf("restoreVPNSecrets\n\r");
// ID is necessary
if (id.isEmpty()) {
printf("VPN connection ID is empty!\n\r");
}
else {
// Get a group for this setting
TQString setting_grp = TQString("ConnectionSecrets_%1_%2").arg(id).arg(type);
// Restore the settings
printf("Restoring VPN secret: %s\n\r", setting_grp.ascii());
KConfigGroup secrets_grp(KGlobal::config(), setting_grp);
TQMap<TQString, TQString> config_map = KGlobal::config()->entryMap(setting_grp);
TQString typetwo = secrets_grp.readEntry("Type");
// // get the appropriate setting from the connection
// ConnectionSetting* setting = conn->getSetting(typetwo);
// if (!setting)
// {
// printf("Secrets cannot be restored!\n\r");
// }
// Read the SettingsMap from kconfig
// This loop reads the secrets information map only
TQMap<TQString, TQString> map;
for(TQMap<TQString, TQString>::ConstIterator it = config_map.begin(); it != config_map.end(); ++it)
{
if (!it.key().startsWith("Value_"))
continue;
TQString key = it.key();
// Get the original key name
key.replace("Value_", "");
TQString xmldata = it.data();
// Remove the annoying XML <string> stuff
xmldata.replace("<string>", "");
xmldata.replace("</string>", "");
//printf("Got %s with value %s\n\r", key.ascii(), xmldata.ascii());
map.insert(key, xmldata);
number_of_secrets_found++;
}
if (number_of_secrets_found > 0) {
printf("Got secrets from file, continuing...\n\r");
// Good, we have new secrets now, update the settings
//map = _vpnAuthWidget->getPasswords();
ConnectionSetting* propcore = conn->getVPNSettingConnectionCore();
SettingsMap othersettingsmap = propcore->toMap();
// Pull the username and gateway out of map to stuff in the NM standard settings matrix
othersettingsmap.insert("user", TQT_DBusData::fromString(map["user"]));
map.erase("user");
othersettingsmap.insert("domain", TQT_DBusData::fromString(map["domain"]));
map.erase("domain");
if (!request_new) {
propcore->fromMap(othersettingsmap);
VPN* prop = dynamic_cast<VPN*>(propcore);
prop->setSecrets(map);
conn->slotSecretsProvided(prop);
}
else {
printf("Tray::slotVPNSecretsNeeded: New secrets requested\n\r");
// OK, NM requests new secrets...do something!
ConnectionSettings::VPNConnection* conn = dynamic_cast<ConnectionSettings::VPNConnection*>(connection);
VPNAuthenticationDialog* auth = new VPNAuthenticationDialog(conn, this, "vpnauth");
// Prefill the password dialog with cached credentials
TQString passdata;
for(TQMap<TQString, TQString>::ConstIterator it = map.begin(); it != map.end(); ++it)
{
passdata = it.data();
// Remove any non-typable characters from the string!
passdata.remove("\r");
passdata.remove("\n");
passdata.remove("\t");
//printf("Trying to set %s to value %s\n\r", it.key().ascii(), passdata.ascii());
auth->setPasswords(it.key(), passdata);
}
auth->show();
}
//connection->slotSecretsProvided(setting);
}
else {
printf("Tray::slotVPNSecretsNeeded: New secrets needed\n\r");
// OK, NM needs new secrets...do something!
ConnectionSettings::VPNConnection* conn = dynamic_cast<ConnectionSettings::VPNConnection*>(connection);
VPNAuthenticationDialog* auth = new VPNAuthenticationDialog(conn, this, "vpnauth");
auth->show();
}
}
// }
}
else
{
printf("Tray::slotVPNSecretsNeeded: New secrets needed\n\r");
// OK, NM needs new secrets...do something!
ConnectionSettings::VPNConnection* conn = dynamic_cast<ConnectionSettings::VPNConnection*>(connection);
VPNAuthenticationDialog* auth = new VPNAuthenticationDialog(conn, this, "vpnauth");
auth->show();
}
}
void
Tray::slotSecretsNeeded(ConnectionSettings::Connection* connection, ConnectionSettings::ConnectionSetting* setting, const TQStringList& hints, bool request_new)
{
Storage* storage = Storage::getInstance();
bool hasSecretsStored = storage->hasSecretsStored(connection, setting);
// FIXME ugly secrets handling for VPN
if (connection->getType() == NM_SETTING_VPN_SETTING_NAME)
{
if (vpn_new_credentials_needed == 1) {
printf("VPN connection failed with bad credentials\n\r");
vpn_new_credentials_needed = 0;
request_new = 1;
}
slotVPNSecretsNeeded(connection, setting, hints, request_new);
return;
}
// default secrets handling for all other connection types
// 1) if we have secrets stored, restore them and send them back to NM
// 2) if NM requests new secrets we should allow the user to retry the
// connection or to edit it
if (hasSecretsStored && !request_new)
{
// We have secrets stored, restore them
if (storage->restoreSecrets(connection, setting))
{
connection->slotSecretsProvided(setting);
}
}
else
{
// ok, NM requests new secrets, let's ask the user if he wants to retry
// or edit the connection
NewSecretsDialog* dlg = new NewSecretsDialog(connection, this, "knetworkmanager");
dlg->show();
}
}
void Tray::slotAddDeviceTrayComponent(Device* dev)
{
if (dev)
createDeviceTrayComponent(dev);
}
void Tray::slotRemoveDeviceTrayComponent(Device* dev)
{
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin(); it != d->trayComponents.end(); ++it)
{
DeviceTrayComponent* dev_comp = dynamic_cast<DeviceTrayComponent*>(*it);
if (!dev_comp)
continue;
if (dev_comp->device() == dev)
{
if (d->foregroundTrayComponent && dev_comp->device() == d->foregroundTrayComponent->device() ) {
d->foregroundTrayComponent = 0;
}
// remove the appropriate action
TQString actionName = TQString("new_connection_%1").arg(dev_comp->device()->getInterface());
KAction * deviceNewConnAction = actionCollection ()->action (actionName);
if (!deviceNewConnAction)
{
delete deviceNewConnAction;
deviceNewConnAction = NULL;
}
// remove device_tray and delete it
d->trayComponents.remove(it);
delete dev_comp;
if (contextMenu()->isVisible()) {
contextMenu()->hide();
}
break;
}
}
}
void Tray::createDeviceTrayComponent(Device* dev)
{
bool trayExists = false;
if (!dev) return;
// check if we have already a trayicon for this device
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin(); it != d->trayComponents.end(); ++it)
{
DeviceTrayComponent* dev_comp = dynamic_cast<DeviceTrayComponent*> (*it);
if (dev_comp)
if (dev_comp->device() == dev)
{
trayExists = true;
break;
}
}
// create the appropriate device tray icon
if (!trayExists)
{
DeviceTrayComponent* devTray = 0;
// different tray icons for different device types!
switch (dev->getDeviceType())
{
#if NM_CHECK_VERSION(0,8,992)
case NM_DEVICE_TYPE_ETHERNET:
#else
case DEVICE_TYPE_802_3_ETHERNET:
#endif
devTray = new WiredDeviceTray(dynamic_cast<WiredDevice*>(dev), this, "wired_device_tray");
break;
#if NM_CHECK_VERSION(0,8,992)
case NM_DEVICE_TYPE_WIFI:
#else
case DEVICE_TYPE_802_11_WIRELESS:
#endif
devTray = new WirelessDeviceTray(static_cast<WirelessDevice*>(dev), this, "wireless_device_tray");
break;
#if NM_CHECK_VERSION(0,8,992)
case NM_DEVICE_TYPE_MODEM:
#else
case DEVICE_TYPE_GSM:
case DEVICE_TYPE_CDMA:
#endif
devTray = new CellularDeviceTray(static_cast<CellularDevice*>(dev), this, "cellular_device_tray");
break;
default:
kdWarning() << k_funcinfo << "UDI: " << dev->getUdi() << " has unknown devicetype: " << dev->getDeviceType() << endl;
}
if(devTray)
{
connect( devTray, TQT_SIGNAL(needsCenterStage(TrayComponent*,bool)),
TQT_SLOT(trayComponentNeedsCenterStage(TrayComponent*,bool)));
connect( devTray, TQT_SIGNAL(uiUpdated()), TQT_SLOT(trayUiChanged()));
d->trayComponents.append(devTray);
//WILLTODO: sort
}
}
}
void Tray::createVPNTrayComponent()
{
bool trayExists = false;
// check if we have already a trayicon for this device
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin(); it != d->trayComponents.end(); ++it)
{
VPNTrayComponent* vpn_comp = dynamic_cast<VPNTrayComponent*> (*it);
if (vpn_comp)
{
trayExists = true;
break;
}
}
// create the appropriate device tray icon
if (!trayExists)
{
TrayComponent* devTray = new VPNTrayComponent(this, "vpn_device_tray");
if(devTray)
{
d->trayComponents.append(devTray);
//WILLTODO: sort
}
}
}
void Tray::updateDeviceTrays()
{
// create one tray-icon for each device
DeviceStore* store = DeviceStore::getInstance();
TQValueList<Device*> devices = store->getDevices();
// check for newly added devices
for (TQValueList<Device*>::iterator it = devices.begin(); it != devices.end(); ++it)
{
Device* dev = (*it);
if (dev)
createDeviceTrayComponent(dev);
else
kdWarning() << k_funcinfo << "got a NULL-Device" << endl;
}
// add the VPN componenet as it is not associated with a device
createVPNTrayComponent();
}
void Tray::mousePressEvent( TQMouseEvent *e )
{
if ( !TQT_TQRECT_OBJECT(rect()).contains( e->pos() ) ) {
return;
}
switch ( e->button() ) {
case Qt::LeftButton:
contextMenuAboutToShow(contextMenu());
contextMenu()->popup(e->globalPos());
break;
default:
KSystemTray::mousePressEvent( e );
break;
}
}
void Tray::slotDeactivateConnection(int index)
{
ConnectionSettings::Connection* conn = d->act_conn_map[index].first;
Device* dev = d->act_conn_map[index].second;
NMProxy* nm = NMProxy::getInstance();
if (conn) {
TQString actionText = conn->getObjectPath().data();
nm->deactivateConnection(conn, dev);
}
}
void Tray::trayComponentNeedsCenterStage(TrayComponent *component, bool needsIt)
{
DeviceTrayComponent * dtc = dynamic_cast<DeviceTrayComponent*>(component);
if (dtc) {
kdDebug() << k_funcinfo << dtc->device()->getInterface() << " : " << needsIt << endl;
Device * device = dtc->device();
if (needsIt) {
if (d->foregroundTrayComponent) {
disconnect(d->foregroundTrayComponent->device(), TQT_SIGNAL(StateChanged(NMDeviceState)), this, 0 );
}
d->foregroundTrayComponent = dtc;
connect(device, TQT_SIGNAL(StateChanged(NMDeviceState)),
TQT_SLOT(slotUpdateDeviceState(NMDeviceState)));
} else {
disconnect(device, TQT_SIGNAL(StateChanged(NMDeviceState)), this, 0 );
//use active default
NMProxy* nm = NMProxy::getInstance();
device = nm->getDefaultDevice();
if ( device ) {
// identify the new foreground
for (TQValueList<TrayComponent*>::Iterator it = d->trayComponents.begin(); it != d->trayComponents.end(); ++it)
{
DeviceTrayComponent* newDtc = dynamic_cast<DeviceTrayComponent*> (*it);
if ( newDtc && newDtc->device() == device ) {
d->foregroundTrayComponent = newDtc;
break;
}
}
kdDebug() << " Device " << dtc->device()->getInterface() << " background, new foreground device: " << device->getInterface() << endl;
connect(device, TQT_SIGNAL(StateChanged(NMDeviceState)),
TQT_SLOT(slotUpdateDeviceState(NMDeviceState)));
slotUpdateDeviceState(device->getState());
}
}
}
}
void Tray::slotUpdateDeviceState()
{
// FIXME
}
void Tray::slotUpdateDeviceState(NMDeviceState state)
{
updateTrayIcon(state);
updateActiveConnection(state);
}
void Tray::trayUiChanged()
{
DeviceTrayComponent * dtc = d->foregroundTrayComponent;
if (dtc) {
updateTrayIcon(dtc->device()->getState());
}
}
void Tray::updateTrayIcon(NMDeviceState state)
{
// Get all active connections
char active_vpn=0;
char found_any_active_connection=0;
ConnectionStore* connectionStore = ConnectionStore::getInstance();
NMProxy* nm = NMProxy::getInstance();
TQValueList<TQPair<ConnectionSettings::Connection*, Device*> > map = nm->getActiveConnectionsMap();
// get all available VPN Connections
TQValueList<Connection*> connections = connectionStore->getConnections(NM_SETTING_VPN_SETTING_NAME);
if (!connections.empty())
{
for (TQValueList<Connection*>::iterator it = connections.begin(); it != connections.end(); ++it)
{
VPNConnection* vpnconn = dynamic_cast<VPNConnection*>(*it);
if (vpnconn)
{
// VPN connection found :)
Info* info = vpnconn->getInfoSetting();
// lets create a nice name for this connection
if (info)
{
TQString title = info->getName();
for (TQValueList<TQPair<ConnectionSettings::Connection*, Device*> >::Iterator it = map.begin(); it != map.end(); ++it)
{
ConnectionSettings::GenericConnection* conn = dynamic_cast<ConnectionSettings::GenericConnection*>((*it).first);
if (conn) {
if (strcmp(info->getName(), conn->getInfoSetting()->getName()) == 0) {
active_vpn = 1;
}
}
}
}
}
}
}
found_any_active_connection = 0;
// Get all active connections
TQValueList<TQPair<ConnectionSettings::Connection*, Device*> > allconnmap = nm->getActiveConnectionsMap();
for (TQValueList<TQPair<ConnectionSettings::Connection*, Device*> >::Iterator it = allconnmap.begin(); it != allconnmap.end(); ++it)
{
ConnectionSettings::GenericConnection* conn = dynamic_cast<ConnectionSettings::GenericConnection*>((*it).first);
if (!conn)
continue;
// Found an active connection
found_any_active_connection = 1;
}
// if (found_any_active_connection == 1) {
// printf("Active connection found\n\r");
// }
if ((current_vpn_state == NM_VPN_CONNECTION_STATE_FAILED) || (current_vpn_state == NM_VPN_CONNECTION_STATE_DISCONNECTED)) {
active_vpn = 0;
}
if (active_vpn == 0) {
// stop the old movie to avoid unnecessary wakups
DeviceTrayComponent * dtc = d->foregroundTrayComponent;
if (movie())
movie()->pause();
if ((dtc) && (found_any_active_connection == 1)) {
if (!dtc->movieForState(state).isNull())
{
// animation desired
int frame = -1;
if (movie())
frame = movie()->frameNumber();
// set the movie
setMovie(dtc->movieForState(state));
// start at the same frame as the movie before
if (frame > 0)
movie()->step(frame);
// start the animation
movie()->unpause();
}
else if (!dtc->pixmapForState(state).isNull())
setPixmap(dtc->pixmapForState(state));
else
setPixmap(loadIcon("knetworkmanager"));
}
else {
setPixmap(loadIcon("knetworkmanager"));
}
}
else {
printf("VPN state: %d\n\r", current_vpn_state);
//printf("Activated is: %d\n\r", NM_VPN_CONNECTION_STATE_ACTIVATED);
// stop the old movie to avoid unnecessary wakups
DeviceTrayComponent * dtc = d->foregroundTrayComponent;
if (movie())
movie()->pause();
if (dtc) {
if (current_vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED) {
setPixmap(loadIcon("nm_device_vpn"));
}
if ((current_vpn_state == NM_VPN_CONNECTION_STATE_PREPARE) || (current_vpn_state == NM_VPN_CONNECTION_STATE_NEED_AUTH) || (current_vpn_state == NM_VPN_CONNECTION_STATE_CONNECT) || (current_vpn_state == NM_VPN_CONNECTION_STATE_IP_CONFIG_GET)) {
int frame = -1;
if (movie())
frame = movie()->frameNumber();
// set the movie
if ((current_vpn_state == NM_VPN_CONNECTION_STATE_PREPARE) || (current_vpn_state == NM_VPN_CONNECTION_STATE_NEED_AUTH)) {
setMovie(TQMovie(KGlobal::iconLoader()->moviePath("nm_stage02_connecting_vpn", KIcon::Panel)));
}
if ((current_vpn_state == NM_VPN_CONNECTION_STATE_CONNECT) || (current_vpn_state == NM_VPN_CONNECTION_STATE_IP_CONFIG_GET)) {
setMovie(TQMovie(KGlobal::iconLoader()->moviePath("nm_stage03_connecting_vpn", KIcon::Panel)));
}
// start at the same frame as the movie before
if (frame > 0)
movie()->step(frame);
// start the animation
movie()->unpause();
}
}
}
nm_device_state_global = state;
//printf("Device state: %d\n\r", nm_device_state_global);
}
void Tray::updateActiveConnection(NMDeviceState state)
{
if (state != NM_DEVICE_STATE_ACTIVATED)
return;
NMProxy* nm = NMProxy::getInstance();
if (d->foregroundTrayComponent) {
Connection* active_conn = nm->getActiveConnection(d->foregroundTrayComponent->device());
if (active_conn)
{
Info* info = dynamic_cast<Info*>(active_conn->getSetting(NM_SETTING_CONNECTION_SETTING_NAME));
if (info)
info->setTimestamp(TQDateTime::currentDateTime());
}
}
}
void Tray::slotDeviceAddedNotify(Device* dev)
{
kdDebug() << "Tray::slotDeviceAddedNotify" << endl;
KNotifyClient::event( winId(), "knm-nm-device-added", i18n("New network device %1 found").arg(dev->getInterface()) );
}
void Tray::slotDeviceRemovedNotify(Device* dev)
{
kdDebug() << "Tray::slotDeviceRemovedNotify" << endl;
KNotifyClient::event( winId(), "knm-nm-device-removed", i18n("Network device %1 removed").arg(dev->getInterface()) );
}
void Tray::slotVPNBannerShow(const TQString& vpnbanner)
{
printf("VPN banner: %s\n\r", vpnbanner.ascii());
KNotifyClient::event(winId(), "knm-nm-vpn-banner", vpnbanner);
}
void Tray::slotStateChangedNotify(TQ_UINT32 state)
{
NMState nm_state = (NMState) state;
// change tray icon according to NM's state
switch(nm_state)
{
case NM_STATE_CONNECTING:
KNotifyClient::event( winId(), "knm-nm-connecting", i18n("NetworkManager is connecting") );
break;
case NM_STATE_DISCONNECTED:
KNotifyClient::event( winId(), "knm-nm-disconnected", i18n("NetworkManager is now disconnected") );
break;
case NM_STATE_CONNECTED:
KNotifyClient::event( winId(), "knm-nm-connected", i18n("NetworkManager is now connected") );
break;
case NM_STATE_ASLEEP:
KNotifyClient::event( winId(), "knm-nm-sleeping", i18n("KNetworkManager Offline") );
break;
case NM_STATE_UNKNOWN:
default:
break;
}
}
void Tray::slotEditNotifications()
{
KNotifyDialog::configure(this);
}
Tray::Tray () : KSystemTray ()
{
d = new TrayPrivate(TQT_TQOBJECT(this));
connect(&d->signalMapper, TQT_SIGNAL(mapped(int)), this, TQT_SLOT(slotDeactivateConnection(int)));
setPixmap (loadIcon ("knetworkmanager"));
setMouseTracking (true);
// Actions used for plugging into the menu
new KAction (i18n ("Switch to offline mode"),
SmallIcon ("no", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotOfflineMode()), actionCollection (), "offline_mode");
new KAction (i18n ("Switch to online mode"),
SmallIcon ("ok", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotOnlineMode()), actionCollection (), "online_mode");
new KAction (i18n ("Disable Wireless"),
SmallIcon ("wireless_off", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotDisableWireless()), actionCollection (), "disable_wireless");
new KAction (i18n ("Enable Wireless"),
SmallIcon ("wireless", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotEnableWireless()), actionCollection (), "enable_wireless");
new KAction (i18n ("Edit Connections"),
SmallIcon ("edit", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotEditConnections()), actionCollection (), "edit_connections");
new KAction (i18n ("Configure Notifications"),
SmallIcon ("knotify", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), TQT_SLOT (slotEditNotifications()), actionCollection (), "configure_notifications");
// this action is only connected when the menu is shown, hence the 0 receiver
new KAction (i18n ("New connection ..."),
SmallIcon ("filenew", TQIconSet::Automatic), 0,
TQT_TQOBJECT(this), 0, actionCollection (), "new_connection");
new KActionMenu (i18n ("New connection ..."),
SmallIcon ("filenew", TQIconSet::Automatic),
actionCollection(), "new_connection_menu");
new KActionMenu (i18n ("Deactivate connection..."),
SmallIcon ("no", TQIconSet::Automatic),
actionCollection (), "deactivate_menu");
// get notified when NM's state changes
NMProxy* nm = NMProxy::getInstance();
connect(nm, TQT_SIGNAL(StateChange(TQ_UINT32)), this, TQT_SLOT(slotStateChanged(TQ_UINT32)));
// get notifier when NM requests new secrets
ConnectionStore* cstore = ConnectionStore::getInstance();
connect(cstore, TQT_SIGNAL(SecretsNeeded(ConnectionSettings::Connection*, ConnectionSettings::ConnectionSetting*, const TQStringList&, bool)), this, TQT_SLOT(slotSecretsNeeded(ConnectionSettings::Connection*, ConnectionSettings::ConnectionSetting*, const TQStringList&, bool)));
// get notified about new/removed devices
DeviceStore* store = DeviceStore::getInstance();
connect(store, TQT_SIGNAL(DeviceStoreChanged()), this, TQT_SLOT(updateDeviceTrays()));
connect(store, TQT_SIGNAL(DeviceAdded(Device*)), this, TQT_SLOT(slotAddDeviceTrayComponent(Device*)));
connect(store, TQT_SIGNAL(DeviceRemoved(Device*)), this, TQT_SLOT(slotRemoveDeviceTrayComponent(Device*)));
// Notifications
connect(store, TQT_SIGNAL(DeviceAdded(Device*)), this, TQT_SLOT(slotDeviceAddedNotify(Device*)));
connect(store, TQT_SIGNAL(DeviceRemoved(Device*)), this, TQT_SLOT(slotDeviceRemovedNotify(Device*)));
connect(nm, TQT_SIGNAL(StateChange(TQ_UINT32)), this, TQT_SLOT(slotStateChangedNotify(TQ_UINT32)));
// initial setup of the device-trays
updateDeviceTrays();
TQT_DBusError err;
slotStateChanged(nm->getState(err));
}
Tray::~Tray ()
{
delete d;
}
#include "knetworkmanager-tray.moc"