diff options
Diffstat (limited to 'knetworkmanager-0.8/src/knetworkmanager-tray.cpp')
-rw-r--r-- | knetworkmanager-0.8/src/knetworkmanager-tray.cpp | 1127 |
1 files changed, 1127 insertions, 0 deletions
diff --git a/knetworkmanager-0.8/src/knetworkmanager-tray.cpp b/knetworkmanager-0.8/src/knetworkmanager-tray.cpp new file mode 100644 index 0000000..24a91a9 --- /dev/null +++ b/knetworkmanager-0.8/src/knetworkmanager-tray.cpp @@ -0,0 +1,1127 @@ +/*************************************************************************** + * + * knetworkmanager-tray.cpp - A NetworkManager frontend for KDE + * + * Copyright (C) 2005, 2006 Novell, Inc. + * + * Author: Timo Hoenig <[email protected]>, <[email protected]> + * Will Stephenson <[email protected]>, <[email protected]> + * Valentine Sinitsyn <[email protected]> + * Helmut Schaa <[email protected]>, <[email protected]> + * Alexander Naumov <[email protected]>, <[email protected]> + * Author: Timothy Pearson <[email protected]> + * + * 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 ").tqarg(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").tqarg(dev_comp->device()->getInterface()); + TQString menuCaption = TQString("%1").tqarg(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").tqarg("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").tqarg(conn->getID()).tqarg(dev ? dev->getInterface() : ""); + KAction * deviceNewConnAction = actionCollection ()->action (actionName); + TQString actionText = conn->getInfoSetting()->getName(); + if (dev) + actionText += TQString(" (%1)").tqarg(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").tqarg(id).tqarg(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").tqarg(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::tqcurrentDateTime()); + } + } +} + +void Tray::slotDeviceAddedNotify(Device* dev) +{ + kdDebug() << "Tray::slotDeviceAddedNotify" << endl; + KNotifyClient::event( winId(), "knm-nm-device-added", i18n("New network device %1 found").tqarg(dev->getInterface()) ); +} + +void Tray::slotDeviceRemovedNotify(Device* dev) +{ + kdDebug() << "Tray::slotDeviceRemovedNotify" << endl; + KNotifyClient::event( winId(), "knm-nm-device-removed", i18n("Network device %1 removed").tqarg(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" + |