/*************************************************************************** * * knetworkmanager-wireless_device_tray.cpp - A NetworkManager frontend for KDE * * Copyright (C) 2005, 2006 Novell, Inc. * * Author: Helmut Schaa , * * 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 * **************************************************************************/ // TQt includes #include #include #include #include #include #include #include #include #include #include #include #include // KDE includes #include #include #include #include // QT DBus #include #include // KNM includes #include "knetworkmanager-wireless_device_tray.h" #include "knetworkmanager-wireless_device.h" #include "knetworkmanager-wireless_menuitem.h" #include "knetworkmanager-wireless_network.h" #include "knetworkmanager-accesspoint.h" #include "knetworkmanager-menu_subhead.h" #include "knetworkmanager-connection_store.h" #include "knetworkmanager-wireless_connection.h" #include "knetworkmanager-connection_setting_info.h" #include "knetworkmanager-connection_setting_wireless.h" #include "knetworkmanager-connection_setting_wireless_security.h" #include "knetworkmanager-nm_proxy.h" #include "knetworkmanager-wireless_manager.h" #include "knetworkmanager-connection_settings_dialog.h" using namespace ConnectionSettings; extern char use_new_wireless_essid; extern TQByteArray new_wireless_essid; class WirelessDeviceTrayPrivate { public: WirelessDeviceTrayPrivate() :dev(0), activeAccessPoint(0) { } ~WirelessDeviceTrayPrivate() {} WirelessDevice* dev; TQGuardedPtr activeAccessPoint; }; TQStringList WirelessDeviceTray::getToolTipText() { TQStringList tooltip = DeviceTrayComponent::getToolTipText(); AccessPoint * ap = d->dev->getActiveAccessPoint(); if (ap) tooltip.append(i18n("Network: %1").tqarg(ap->getDisplaySsid())); return tooltip; } void WirelessDeviceTray::newConnection() { // create a new wireless connection Connection* conn = new WirelessConnection(); // open a dialog for editing the connection use_new_wireless_essid = 0; // deactivate autofill for now ConnectionSettingsDialogImpl* dlg = new ConnectionSettingsDialogImpl(conn, true, NULL, tray(), "connect_something", false, TQt::WDestructiveClose); dlg->show(); } bool WirelessDeviceTray::findMatchingNetwork(const WirelessConnection* conn, const TQValueList& nets, WirelessNetwork& net) { Wireless* wireless = conn->getWirelessSetting(); WirelessSecurity* security = conn->getWirelessSecuritySetting(); if (!wireless && !security) return false; for (TQValueList::ConstIterator it = nets.begin(); it != nets.end(); ++it) { if (wireless->getEssid() == (*it).getSsid()) { net = *it; return true; } } return false; } WirelessConnection* WirelessDeviceTray::findMatchingConnection(const WirelessNetwork& net, const TQValueList& connections) { // try to find a connection matching this network for (TQValueList::ConstIterator it = connections.begin(); it != connections.end(); ++it) { Wireless* wireless = (*it)->getWirelessSetting(); WirelessSecurity* security = (*it)->getWirelessSecuritySetting(); // should not happen but its ever better to check if (!wireless || !security) continue; if (wireless->getEssid() == net.getSsid()) { return *it; } } return NULL; } void WirelessDeviceTray::addWirelessNetworks(KPopupMenu* menu) { printf("Updating wireless network list\n\r"); // get all wireless networks TQValueList nets = WirelessManager::getWirelessNetworks(d->dev); // get all wireless connections TQValueList conns = WirelessManager::getWirelessConnections(); // get the currently active connection NMProxy* nm = NMProxy::getInstance(); Connection* active_conn = nm->getActiveConnection(d->dev); if (active_conn) kdDebug() << active_conn->getObjectPath().data() << endl; // add all wireless connections in range // (we may have more then one connection per network) for (TQValueList::iterator it = conns.begin(); it != conns.end(); ++it) { WirelessNetworkItem* wirelessNetworkItem; WirelessNetwork net; // only show connections which are in range if ( !findMatchingNetwork(*it, nets, net) ) continue; wirelessNetworkItem = new WirelessNetworkItem (menu, d->dev, net, *it, false); int id = menu->insertItem (wirelessNetworkItem, -1, -1); menu->setItemChecked(id, ((Connection*)(*it) == active_conn)); menu->connectItem(id, wirelessNetworkItem, TQT_SLOT(slotActivate())); } // now add all connections which are not in range to a submenu TQPopupMenu* popup = new TQPopupMenu(menu); uint networkItemsAdded = 0; for (TQValueList::iterator it = conns.begin(); it != conns.end(); ++it) { WirelessNetworkItem* wirelessNetworkItem; WirelessNetwork net; // only show connections which are out of range if ( findMatchingNetwork(*it, nets, net) ) continue; Info* info = (*it)->getInfoSetting(); Wireless* wireless = (*it)->getWirelessSetting(); if (!info || !wireless) continue; wirelessNetworkItem = new WirelessNetworkItem (menu, d->dev, net, *it, false); int id = popup->insertItem (wirelessNetworkItem, -1, -1); popup->connectItem(id, wirelessNetworkItem, TQT_SLOT(slotActivate())); networkItemsAdded += 1; } if (networkItemsAdded) { menu->insertSeparator(); menu->insertItem(i18n("Connect to saved network"), popup); } // // List available unsaved networks TQPopupMenu* newpopup = new TQPopupMenu(menu); WirelessConnection* newconn; uint newnetworkItemsAdded = 0; TQValueList newnets = WirelessManager::getWirelessNetworks(0, WirelessNetwork::MATCH_SSID); for (TQValueList::Iterator it = newnets.begin(); it != newnets.end(); ++it) { // Only display networks with no existing connnection if ( findMatchingConnection(*it, conns) != NULL) continue; WirelessNetworkItem* wirelessNetworkItem; wirelessNetworkItem = new WirelessNetworkItem (menu, d->dev, *it, NULL, false); int id = newpopup->insertItem (wirelessNetworkItem, -1, -1); newpopup->connectItem(id, this, TQT_SLOT(newConnection())); newnetworkItemsAdded += 1; } if (newnetworkItemsAdded) { menu->insertSeparator(); menu->insertItem(i18n("Connect to new network"), newpopup); } // Signal done with wireless menu //menu->insertSeparator(); } void WirelessDeviceTray::addMenuItems(KPopupMenu* menu) { NMProxy* nm = NMProxy::getInstance(); TQT_DBusError err; // device title Subhead* subhead = new Subhead (menu, "subhead", TQString("Wireless Connection (%1)").tqarg(d->dev->getInterface()), SmallIcon("wireless", TQIconSet::Automatic)); menu->insertItem (subhead, -1, -1); // bolding subhead instead //menu->insertSeparator(); if (!nm->getWirelessEnabled(err)) { // wireless disabled -> do not show any connections subhead = new Subhead(menu, "subhead2", i18n("Wireless disabled"), SmallIcon("no", TQIconSet::Automatic)); menu->insertItem(subhead, -1, -1); } else if (!nm->getWirelessHardwareEnabled(err)) { // wireless disabled -> do not show any connections subhead = new Subhead(menu, "subhead2", i18n("Wireless disabled by Killswitch"), SmallIcon("no", TQIconSet::Automatic)); menu->insertItem(subhead, -1, -1); } else { // networks addWirelessNetworks(menu); // bring the device down KAction* deactivate = tray()->actionCollection()->action("deactivate_device"); if (deactivate) deactivate->plug(menu); } menu->insertSeparator(); } void WirelessDeviceTray::slotUpdateDeviceState(NMDeviceState state) { slotCheckActiveAccessPoint(); if (state == NM_DEVICE_STATE_ACTIVATED) { // trigger an update of the connections seen bssids property AccessPoint * ap = d->dev->getActiveAccessPoint(); if (ap) { int strength = ap->getStrength(); if (strength > 80) setPixmapForState((NMDeviceState)state, "nm_signal_100"); else if (strength > 55) setPixmapForState((NMDeviceState)state, "nm_signal_75"); else if (strength > 30) setPixmapForState((NMDeviceState)state, "nm_signal_50"); else if (strength > 5) setPixmapForState((NMDeviceState)state, "nm_signal_25"); else setPixmapForState((NMDeviceState)state, "nm_signal_00"); } } } void WirelessDeviceTray::slotCheckActiveAccessPoint() { // the active AP changed, if a connection is already active we have roamed // thus add the bssid to the list of seen bssids NMProxy* nm = NMProxy::getInstance(); if (!nm) return; WirelessConnection* active_conn = dynamic_cast(nm->getActiveConnection(d->dev)); if (active_conn && d->dev->getState() == NM_DEVICE_STATE_ACTIVATED) { if ( d->dev->getActiveAccessPoint() != d->activeAccessPoint) { if (!d->activeAccessPoint.isNull()) disconnect( d->activeAccessPoint, TQT_SIGNAL(strengthChanged(TQ_UINT8)), this, TQT_SLOT(apStrengthChanged(TQ_UINT8))); d->activeAccessPoint = d->dev->getActiveAccessPoint(); if ( d->activeAccessPoint ) { connect( d->activeAccessPoint, TQT_SIGNAL(strengthChanged(TQ_UINT8)), this, TQT_SLOT(apStrengthChanged(TQ_UINT8))); ConnectionSettings::Wireless* wireless = active_conn->getWirelessSetting(); wireless->addSeenBssid(d->activeAccessPoint->getHwAddress()); } } } } void WirelessDeviceTray::apStrengthChanged(TQ_UINT8 strength) { kdDebug() << k_funcinfo << (uint)strength << endl; NMDeviceState state = device()->getState(); if (strength > 80) setPixmapForState(state, "nm_signal_100"); else if (strength > 55) setPixmapForState(state, "nm_signal_75"); else if (strength > 30) setPixmapForState(state, "nm_signal_50"); else if (strength > 5) setPixmapForState(state, "nm_signal_25"); else setPixmapForState(state, "nm_signal_00"); emit uiUpdated(); } void WirelessDeviceTray::slotAccessPointAdded(AccessPoint* ap) { KNotifyClient::event( tray()->winId(), "knm-nm-network-found", i18n("KNetworkManager New Wireless Network Found") ); } void WirelessDeviceTray::slotAccessPointRemoved(const TQString&) { KNotifyClient::event( tray()->winId(), "knm-nm-network-gone", i18n("KNetworkManager Wireless Network Disappeared") ); } WirelessDeviceTray::WirelessDeviceTray (WirelessDevice* dev, KSystemTray * parent, const char * name) : DeviceTrayComponent (dev, parent, name) { d = new WirelessDeviceTrayPrivate(); d->dev = dev; // we want other icons for wireless devices setPixmapForState(NM_DEVICE_STATE_UNKNOWN, "wireless_off"); setPixmapForState(NM_DEVICE_STATE_UNAVAILABLE, "wireless_off"); setPixmapForState(NM_DEVICE_STATE_UNMANAGED, "wireless_off"); setPixmapForState(NM_DEVICE_STATE_DISCONNECTED, "wireless"); setPixmapForState(NM_DEVICE_STATE_ACTIVATED, "nm_signal_50"); // get notified when the device state changes connect(dev, TQT_SIGNAL(StateChanged(NMDeviceState)), this, TQT_SLOT(slotUpdateDeviceState(NMDeviceState))); // if the active access point changed but not the connection we roamed to a new AP connect(dev, TQT_SIGNAL(propertiesChanged()), this, TQT_SLOT(slotCheckActiveAccessPoint())); // get notified of all AP changes connect(dev, TQT_SIGNAL(accessPointAdded(AccessPoint*)), this, TQT_SLOT(slotAccessPointAdded(AccessPoint*))); connect(dev, TQT_SIGNAL(accessPointRemoved(const TQString&)), this, TQT_SLOT(slotAccessPointRemoved(const TQString&))); } WirelessDeviceTray::~WirelessDeviceTray () { delete d; } #include "knetworkmanager-wireless_device_tray.moc"