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/tdenetman-wireless_device_t...

559 lines
17 KiB

/***************************************************************************
*
* tdenetman-wireless_device_tray.cpp - A NetworkManager frontend for TDE
*
* Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
* Copyright (C) 2005, 2006 Novell, Inc.
*
* Author: Helmut Schaa <hschaa@suse.de>, <helmut.schaa@gmx.de>
*
* 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 <tqevent.h>
#include <tqvbox.h>
#include <tqlayout.h>
#include <tqpushbutton.h>
#include <tqbitmap.h>
#include <tqimage.h>
#include <tqpixmap.h>
#include <tqpixmapcache.h>
#include <tqpainter.h>
#include <tqstyle.h>
#include <tqstring.h>
#include <tqguardedptr.h>
// TDE includes
#include <kdebug.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <knotifyclient.h>
// 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<TDENetworkDevice*>(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<WirelessNetwork>& nets, WirelessNetwork& net)
{
const TDEWiFiConnection* wireless = dynamic_cast<const TDEWiFiConnection*>(conn);
if (!wireless) {
return false;
}
for (TQValueList<WirelessNetwork>::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<TDEWiFiConnection*>& connections)
{
// try to find a connection matching this network
for (TQValueList<TDEWiFiConnection*>::ConstIterator it = connections.begin(); it != connections.end(); ++it) {
const TDEWiFiConnection* wireless = dynamic_cast<const TDEWiFiConnection*>(*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<TDENetworkDevice*>(hwdevices->findByUniqueID(d->dev));
#ifdef DEBUG_STATE
printf("Updating wireless network list\n");
#endif // DEBUG_STATE
// get all wireless networks
TQValueList<WirelessNetwork> nets = WirelessManager::getWirelessNetworks(dev);
// get all wireless connections
TQValueList<TDEWiFiConnection*> 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<TDEWiFiConnection*>::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<TDEWiFiConnection*>::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<const TDEWiFiConnection*>(*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<WirelessNetwork> newnets = WirelessManager::getWirelessNetworks(0, WirelessNetwork::MATCH_SSID);
newWirelessPopupSSIDMap.clear();
for (TQValueList<WirelessNetwork>::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<TDENetworkDevice*>(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<TDENetworkDevice*>(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<TDENetworkDevice*>(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<TDEWiFiConnection*>(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<TDENetworkDevice*>(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<TDENetworkDevice*>(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<TDENetworkDevice*>(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"