/*************************************************************************** * * tdenetman-wireless_device_tray.cpp - A NetworkManager frontend for TDE * * Copyright (C) 2012 Timothy Pearson * 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 // TDE includes #include #include #include #include // TDENM includes #include "tdenetman-wireless_device_tray.h" #include "tdenetman-wireless_menuitem.h" #include "tdenetman-wireless_network.h" #include "tdenetman-menu_subhead.h" #include "tdenetman-wireless_manager.h" #include "tdenetman-connection_settings_dialog.h" using namespace ConnectionSettings; class WirelessDeviceTrayPrivate { public: WirelessDeviceTrayPrivate() :dev(0), activeAccessPoint(0) { } ~WirelessDeviceTrayPrivate() {} TQString dev; TDENetworkWiFiAPInfo* activeAccessPoint; }; TQStringList WirelessDeviceTray::getToolTipText() { TQStringList tooltip = DeviceTrayComponent::getToolTipText(); TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); if (dev) { TDENetworkConnectionManager* deviceConnMan = dev->connectionManager(); if (deviceConnMan) { TDENetworkWiFiAPInfo * ap = deviceConnMan->findAccessPointByBSSID(deviceConnMan->deviceInformation().wiFiInfo.activeAccessPointBSSID); if (ap) { tooltip.append(i18n("Network: %1").arg(ap->friendlySSID())); int strength = (ap->signalQuality*100.0); tooltip.append(i18n("Signal Strength: %1%").arg(strength)); } } } return tooltip; } void WirelessDeviceTray::newConnection() { newConnection(0); } void WirelessDeviceTray::newConnection(int id) { TDEGlobalNetworkManager* nm = TDEGlobal::networkManager(); if (!nm) { return; } // create a new wireless connection TDENetworkConnection* conn = new TDEWiFiConnection(); nm->loadConnectionAllowedValues(conn); // open a dialog for editing the connection char use_new_wireless_essid = 0; if ((id < 0) && newWirelessPopupSSIDMap.contains(id)) { use_new_wireless_essid = 1; } ConnectionSettingsDialogImpl* dlg = new ConnectionSettingsDialogImpl(conn, true, (use_new_wireless_essid)?newWirelessPopupSSIDMap[id]:TQByteArray(), tray(), "connect_something", false, TQt::WDestructiveClose); dlg->show(); } bool WirelessDeviceTray::findMatchingNetwork(const TDEWiFiConnection* conn, const TQValueList& nets, WirelessNetwork& net) { const TDEWiFiConnection* wireless = dynamic_cast(conn); if (!wireless) { return false; } for (TQValueList::ConstIterator it = nets.begin(); it != nets.end(); ++it) { if (wireless->SSID == (*it).getSsid()) { net = *it; return true; } } return false; } TDEWiFiConnection* 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) { const TDEWiFiConnection* wireless = dynamic_cast(*it); if (!wireless) { continue; } if (wireless->SSID == net.getSsid()) { return *it; } } return NULL; } void WirelessDeviceTray::addWirelessNetworks(TDEPopupMenu* menu) { TDEGlobalNetworkManager* nm = TDEGlobal::networkManager(); TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); #ifdef DEBUG_STATE printf("Updating wireless network list\n"); #endif // DEBUG_STATE // get all wireless networks TQValueList nets = WirelessManager::getWirelessNetworks(dev); // get all wireless connections TQValueList conns = WirelessManager::getWirelessConnections(); // get the currently active connection TDENetworkConnectionManager* deviceConnMan = (dev ? dev->connectionManager() : NULL); TDENetworkConnection* active_conn = NULL; if (nm && deviceConnMan) { TDENetworkDeviceInformation devInfo = deviceConnMan->deviceStatus(); if ((!(devInfo.statusFlags & TDENetworkConnectionStatus::Disconnected)) && (!(devInfo.statusFlags & TDENetworkConnectionStatus::Invalid))) { active_conn = nm->findConnectionByUUID(devInfo.activeConnectionUUID); } } // 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)->UUID, false); int id = menu->insertItem (wirelessNetworkItem, -1, -1); menu->setItemChecked(id, ((TDENetworkConnection*)(*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; } const TDEWiFiConnection* wireless = dynamic_cast(*it); if (!wireless) { continue; } wirelessNetworkItem = new WirelessNetworkItem (popup, d->dev, net, (*it)->UUID, 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); uint newnetworkItemsAdded = 0; TQValueList newnets = WirelessManager::getWirelessNetworks(0, WirelessNetwork::MATCH_SSID); newWirelessPopupSSIDMap.clear(); 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 (newpopup, d->dev, *it, NULL, false); int id = newpopup->insertItem (wirelessNetworkItem, -1, -1); newWirelessPopupSSIDMap[id] = (*it).getSsid(); newpopup->connectItem(id, this, TQT_SLOT(newConnection(int))); newnetworkItemsAdded += 1; } if (newnetworkItemsAdded) { menu->insertSeparator(); menu->insertItem(i18n("Connect to new network"), newpopup); } // Signal done with wireless menu //menu->insertSeparator(); } void WirelessDeviceTray::addMenuItems(TDEPopupMenu* menu) { TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); if (!dev) { return; } // get the currently active connection TDEGlobalNetworkManager* nm = TDEGlobal::networkManager(); // device title Subhead* subhead = new Subhead (menu, "subhead", TQString("Wireless Connection (%1)").arg(dev->deviceNode()), SmallIcon("wireless", TQIconSet::Automatic)); menu->insertItem (subhead, -1, -1); TDENetworkConnectionManager* deviceConnMan = dev->connectionManager(); if (!nm || !deviceConnMan || !deviceConnMan->deviceInformation().managed) { // device is not managed by NM -> do not show any connections subhead = new Subhead(menu, "subhead2", i18n("Not managed"), SmallIcon("no", TQIconSet::Automatic)); menu->insertItem(subhead, -1, -1); } else if (!nm->wiFiEnabled()) { // 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->wiFiHardwareEnabled()) { // 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 TDEAction* deactivate = tray()->actionCollection()->action("deactivate_device"); if (deactivate) { deactivate->plug(menu); } } menu->insertSeparator(); } void WirelessDeviceTray::setPixmapForStates(TDENetworkConnectionStatus::TDENetworkConnectionStatus states, TQString pixmap) { TDENetworkConnectionStatus::TDENetworkConnectionStatus flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)0x80000000; while ((TQ_UINT32)flag > 0) { if (states & flag) { setPixmapForState(flag, pixmap); } flag = (TDENetworkConnectionStatus::TDENetworkConnectionStatus)((TQ_UINT32)flag >> 1); } } void WirelessDeviceTray::slotUpdateDeviceState(TDENetworkConnectionStatus::TDENetworkConnectionStatus newState, TDENetworkConnectionStatus::TDENetworkConnectionStatus prevState, TQString deviceNode) { TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); if (!dev) { return; } if (dev->deviceNode() != deviceNode) { kdDebug() << k_funcinfo << "WARNING: Got networkDeviceStateChanged signal for interface '" << deviceNode << "', but my interface is '" << dev->deviceNode() << "'! Ignoring..."; return; } #ifdef DEBUG_STATE printf("Wireless state: 0x%08x\n", newState); #endif // DEBUG_STATE slotCheckActiveAccessPoint(); if (newState == TDENetworkConnectionStatus::Connected) { // trigger an update of the connections seen bssids property TDENetworkConnectionManager* deviceConnMan = dev->connectionManager(); if (deviceConnMan) { TDENetworkWiFiAPInfo * ap = deviceConnMan->findAccessPointByBSSID(deviceConnMan->deviceInformation().wiFiInfo.activeAccessPointBSSID); if (ap) { int strength = (ap->signalQuality*100.0); if (strength > 80) { setPixmapForStates(newState, "nm_signal_100"); } else if (strength > 55) { setPixmapForStates(newState, "nm_signal_75"); } else if (strength > 30) { setPixmapForStates(newState, "nm_signal_50"); } else if (strength > 5) { setPixmapForStates(newState, "nm_signal_25"); } else { setPixmapForStates(newState, "nm_signal_00"); } } } } // Update tray icon TQTimer::singleShot(0, this, TQT_SLOT(sendUpdateUI())); } 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 TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); // get the currently active connection TDEGlobalNetworkManager* nm = TDEGlobal::networkManager(); TDENetworkConnectionManager* deviceConnMan = (dev ? dev->connectionManager() : NULL); TDENetworkConnection* active_conn = NULL; if (nm && deviceConnMan) { TDENetworkDeviceInformation devInfo = deviceConnMan->deviceStatus(); if ((!(devInfo.statusFlags & TDENetworkConnectionStatus::Disconnected)) && (!(devInfo.statusFlags & TDENetworkConnectionStatus::Invalid))) { active_conn = nm->findConnectionByUUID(devInfo.activeConnectionUUID); } if (active_conn && devInfo.statusFlags == TDENetworkConnectionStatus::Connected) { TDENetworkDeviceInformation devInfo = deviceConnMan->deviceInformation(); TDENetworkWiFiAPInfo * activeap = deviceConnMan->findAccessPointByBSSID(devInfo.wiFiInfo.activeAccessPointBSSID); if ( activeap != d->activeAccessPoint) { d->activeAccessPoint = activeap; if ( d->activeAccessPoint ) { TDEWiFiConnection* wireless = dynamic_cast(active_conn); if (wireless) { if (!(wireless->heardBSSIDs.contains(d->activeAccessPoint->BSSID))) { wireless->heardBSSIDs.append(d->activeAccessPoint->BSSID); } } } } } } } void WirelessDeviceTray::apPropertyChanged(TDEMACAddress BSSID, TDENetworkAPEventType::TDENetworkAPEventType event) { TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); if (!dev) { return; } if (event == TDENetworkAPEventType::SignalStrengthChanged) { TDENetworkConnectionManager* deviceConnMan = dev->connectionManager(); if (deviceConnMan) { TDENetworkWiFiAPInfo * ap = deviceConnMan->findAccessPointByBSSID(BSSID); if (ap) { TQ_UINT32 strength = (ap->signalQuality*100.0); kdDebug() << k_funcinfo << strength << endl; TDENetworkConnectionStatus::TDENetworkConnectionStatus state = deviceConnMan->deviceInformation().statusFlags; if (strength > 80) { setPixmapForStates(state, "nm_signal_100"); } else if (strength > 55) { setPixmapForStates(state, "nm_signal_75"); } else if (strength > 30) { setPixmapForStates(state, "nm_signal_50"); } else if (strength > 5) { setPixmapForStates(state, "nm_signal_25"); } else { setPixmapForStates(state, "nm_signal_00"); } TQTimer::singleShot(0, this, TQT_SLOT(sendUpdateUI())); } } } } void WirelessDeviceTray::slotAccessPointAdded(TDENetworkWiFiAPInfo* ap) { KNotifyClient::event( tray()->winId(), "tdenm-nm-network-found", i18n("TDENetworkManager New Wireless Network Found") ); } void WirelessDeviceTray::slotAccessPointRemoved(TDEMACAddress) { KNotifyClient::event( tray()->winId(), "tdenm-nm-network-gone", i18n("TDENetworkManager Wireless Network Disappeared") ); } void WirelessDeviceTray::tdeAccessPointStatusChangedHandler(TDEMACAddress BSSID, TDENetworkAPEventType::TDENetworkAPEventType event) { TDENetworkDevice* dev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); if (!dev) { return; } TDENetworkConnectionManager* deviceConnMan = dev->connectionManager(); if (event == TDENetworkAPEventType::Discovered) { if (deviceConnMan) { TDENetworkWiFiAPInfo* apinfo = deviceConnMan->findAccessPointByBSSID(BSSID); slotAccessPointAdded(apinfo); } } else if (event == TDENetworkAPEventType::Lost) { slotAccessPointRemoved(BSSID); } else if (event == TDENetworkAPEventType::SignalStrengthChanged) { if (deviceConnMan && deviceConnMan->deviceInformation().wiFiInfo.activeAccessPointBSSID == BSSID) { apPropertyChanged(BSSID, event); } } else if (event == TDENetworkAPEventType::AccessPointChanged) { slotCheckActiveAccessPoint(); } } void WirelessDeviceTray::sendUpdateUI() { emit uiUpdated(); } WirelessDeviceTray::WirelessDeviceTray (TQString dev, KSystemTray * parent, const char * name) : DeviceTrayComponent (dev, parent, name) { hwdevices = TDEGlobal::hardwareDevices(); d = new WirelessDeviceTrayPrivate(); d->dev = dev; // we want other icons for wireless devices setPixmapForState(TDENetworkConnectionStatus::Invalid, "wireless_off"); setPixmapForState(TDENetworkConnectionStatus::LinkUnavailable, "wireless_off"); setPixmapForState(TDENetworkConnectionStatus::UnManaged, "wireless_off"); setPixmapForState(TDENetworkConnectionStatus::Disconnected, "wireless"); setPixmapForState(TDENetworkConnectionStatus::Connected, "nm_signal_50"); // initial hardware information update TDENetworkDevice* netdev = dynamic_cast(hwdevices->findByUniqueID(d->dev)); TDENetworkConnectionManager* deviceConnMan = (netdev)?netdev->connectionManager():NULL; // get notified when the device state changes connect(deviceConnMan, TQT_SIGNAL(networkDeviceStateChanged(TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString)), this, TQT_SLOT(slotUpdateDeviceState(TDENetworkConnectionStatus::TDENetworkConnectionStatus, TDENetworkConnectionStatus::TDENetworkConnectionStatus, TQString))); // get notified of all AP changes connect(deviceConnMan, TQT_SIGNAL(accessPointStatusChanged(TDEMACAddress, TDENetworkAPEventType::TDENetworkAPEventType)), this, TQT_SLOT(tdeAccessPointStatusChangedHandler(TDEMACAddress, TDENetworkAPEventType::TDENetworkAPEventType))); // force status update to ensure correct icon is shown on startup if ((netdev) && (deviceConnMan)) { slotUpdateDeviceState(deviceConnMan->deviceInformation().statusFlags, TDENetworkConnectionStatus::Invalid, netdev->deviceNode()); } } WirelessDeviceTray::~WirelessDeviceTray () { delete d; } #include "tdenetman-wireless_device_tray.moc"