/***************************************************************************
*
* tdenetman - wireless_device_tray . cpp - A NetworkManager frontend for TDE
*
* 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 <klocale.h>
# include <knotifyclient.h>
// KNM 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 ;
extern char use_new_wireless_essid ;
extern TQByteArray new_wireless_essid ;
class WirelessDeviceTrayPrivate
{
public :
WirelessDeviceTrayPrivate ( ) : dev ( 0 ) , activeAccessPoint ( 0 ) { }
~ WirelessDeviceTrayPrivate ( ) { }
TQString dev ;
TQGuardedPtr < TDENetworkWiFiAPInfo > activeAccessPoint ;
} ;
TQStringList WirelessDeviceTray : : getToolTipText ( )
{
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
TQStringList tooltip = DeviceTrayComponent : : getToolTipText ( ) ;
TDENetworkConnectionManager * deviceConnMan = dev - > connectionManager ( ) ;
TDENetworkWiFiAPInfo * ap = deviceConnMan - > findAccessPointByBSSID ( deviceConnMan - > deviceInformation ( ) . wiFiInfo . activeAccessPointBSSID ) ;
if ( ap ) {
tooltip . append ( i18n ( " Network: %1 " ) . arg ( ap - > friendlySSID ( ) ) ) ;
}
return tooltip ;
}
void WirelessDeviceTray : : newConnection ( )
{
TDEGlobalNetworkManager * nm = KGlobal : : networkManager ( ) ;
// create a new wireless connection
TDENetworkConnection * conn = new TDEWiFiConnection ( ) ;
nm - > loadConnectionAllowedValues ( conn ) ;
// open a dialog for editing the connection
use_new_wireless_essid = 0 ; // deactivate autofill for now
ConnectionSettingsDialogImpl * dlg = new ConnectionSettingsDialogImpl ( conn , true , 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 ( KPopupMenu * menu )
{
TDEGlobalNetworkManager * nm = KGlobal : : networkManager ( ) ;
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
printf ( " Updating wireless network list \n \r " ) ;
// 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 - > connectionManager ( ) ;
TDENetworkConnection * active_conn = NULL ;
if ( ( ! ( deviceConnMan - > deviceInformation ( ) . statusFlags & TDENetworkConnectionStatus : : Disconnected ) )
& & ( ! ( deviceConnMan - > deviceInformation ( ) . statusFlags & TDENetworkConnectionStatus : : Invalid ) ) ) {
active_conn = nm - > findConnectionByUUID ( deviceConnMan - > deviceInformation ( ) . 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 ;
TDEWiFiConnection * wireless = dynamic_cast < const TDEWiFiConnection * > ( * it ) ;
if ( ! wireless ) {
continue ;
}
wirelessNetworkItem = new WirelessNetworkItem ( menu ,
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 ) ;
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 ( 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 )
{
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
// get the currently active connection
TDEGlobalNetworkManager * nm = KGlobal : : 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 ) ;
// bolding subhead instead
//menu->insertSeparator();
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
KAction * 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 ( flag > 0 ) {
if ( states & flag ) {
setPixmapForState ( flag , pixmap ) ;
}
flag = ( TDENetworkConnectionStatus : : TDENetworkConnectionStatus ) ( flag > > 1 ) ;
}
}
void WirelessDeviceTray : : slotUpdateDeviceState ( TDENetworkConnectionStatus : : TDENetworkConnectionStatus state )
{
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
slotCheckActiveAccessPoint ( ) ;
if ( state = = TDENetworkConnectionStatus : : Connected ) {
// trigger an update of the connections seen bssids property
TDENetworkConnectionManager * deviceConnMan = dev - > connectionManager ( ) ;
TDENetworkWiFiAPInfo * ap = deviceConnMan - > findAccessPointByBSSID ( deviceConnMan - > deviceInformation ( ) . wiFiInfo . activeAccessPointBSSID ) ;
if ( ap ) {
int strength = ( ap - > signalQuality * 100.0 ) ;
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 " ) ;
}
}
}
}
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
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
// get the currently active connection
TDEGlobalNetworkManager * nm = KGlobal : : networkManager ( ) ;
TDENetworkConnectionManager * deviceConnMan = dev - > connectionManager ( ) ;
TDENetworkConnection * active_conn = NULL ;
if ( ( ! ( deviceConnMan - > deviceInformation ( ) . statusFlags & TDENetworkConnectionStatus : : Disconnected ) )
& & ( ! ( deviceConnMan - > deviceInformation ( ) . statusFlags & TDENetworkConnectionStatus : : Invalid ) ) ) {
active_conn = nm - > findConnectionByUUID ( deviceConnMan - > deviceInformation ( ) . activeConnectionUUID ) ;
}
if ( active_conn & & deviceConnMan - > deviceInformation ( ) . statusFlags = = TDENetworkConnectionStatus : : Connected ) {
TDENetworkWiFiAPInfo * activeap = deviceConnMan - > findAccessPointByBSSID ( deviceConnMan - > deviceInformation ( ) . wiFiInfo . activeAccessPointBSSID ) ;
if ( activeap ! = d - > activeAccessPoint ) {
if ( ! d - > activeAccessPoint . isNull ( ) ) {
disconnect ( deviceConnMan , TQT_SIGNAL ( accessPointStatusChanged ( TDEMACAddress , TDENetworkAPEventType : : TDENetworkAPEventType ) ) , this , TQT_SLOT ( apPropertyChanged ( TDEMACAddress , TDENetworkAPEventType : : TDENetworkAPEventType ) ) ) ;
}
d - > activeAccessPoint = activeap ;
if ( d - > activeAccessPoint ) {
connect ( deviceConnMan , TQT_SIGNAL ( accessPointStatusChanged ( TDEMACAddress , TDENetworkAPEventType : : TDENetworkAPEventType ) ) , this , TQT_SLOT ( apPropertyChanged ( TDEMACAddress , TDENetworkAPEventType : : TDENetworkAPEventType ) ) ) ;
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 )
{
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * dev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > dev ) ) ;
if ( event = = TDENetworkAPEventType : : SignalStrengthChanged ) {
TDENetworkConnectionManager * deviceConnMan = dev - > connectionManager ( ) ;
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 " ) ;
}
emit uiUpdated ( ) ;
}
}
}
void WirelessDeviceTray : : slotAccessPointAdded ( TDENetworkWiFiAPInfo * ap )
{
KNotifyClient : : event ( tray ( ) - > winId ( ) , " knm-nm-network-found " , i18n ( " TDENetworkManager New Wireless Network Found " ) ) ;
}
void WirelessDeviceTray : : slotAccessPointRemoved ( const TQString & )
{
KNotifyClient : : event ( tray ( ) - > winId ( ) , " knm-nm-network-gone " , i18n ( " TDENetworkManager Wireless Network Disappeared " ) ) ;
}
WirelessDeviceTray : : WirelessDeviceTray ( TQString dev , KSystemTray * parent , const char * name )
: DeviceTrayComponent ( dev , parent , name )
{
d = new WirelessDeviceTrayPrivate ( ) ;
d - > dev = dev ;
TDEHardwareDevices * hwdevices = KGlobal : : hardwareDevices ( ) ;
TDENetworkDevice * hwdev = dynamic_cast < TDENetworkDevice * > ( hwdevices - > findByUniqueID ( d - > 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 " ) ;
// TDENM FIXME
// These TQt connections will need to be re-established whenever the device list changes, e.g. after a call to TDEHardwareDevices::queryHardwareInformation()
// Therefore, this class should listen to hardwareEvent(TDEHardwareEvent::TDEHardwareEvent, TQString) and reload devices if TDEHardwareEvent::HardwareListModified is passed
// get notified when the device state changes
connect ( hwdev , TQT_SIGNAL ( StateChanged ( TDENetworkConnectionStatus : : TDENetworkConnectionStatus ) ) , this , TQT_SLOT ( slotUpdateDeviceState ( TDENetworkConnectionStatus : : TDENetworkConnectionStatus ) ) ) ;
// if the active access point changed but not the connection we roamed to a new AP
connect ( hwdev , TQT_SIGNAL ( propertiesChanged ( ) ) , this , TQT_SLOT ( slotCheckActiveAccessPoint ( ) ) ) ;
// get notified of all AP changes
connect ( hwdev , TQT_SIGNAL ( accessPointAdded ( TDENetworkWiFiAPInfo * ) ) , this , TQT_SLOT ( slotAccessPointAdded ( TDENetworkWiFiAPInfo * ) ) ) ;
connect ( hwdev , TQT_SIGNAL ( accessPointRemoved ( const TQString & ) ) , this , TQT_SLOT ( slotAccessPointRemoved ( const TQString & ) ) ) ;
}
WirelessDeviceTray : : ~ WirelessDeviceTray ( )
{
delete d ;
}
# include "tdenetman-wireless_device_tray.moc"