00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "wireless.h"
00015 #include "mgraph.h"
00016 #include "advancedconfig.h"
00017
00018
00019 #include <opie2/odebug.h>
00020 #include <opie2/onetwork.h>
00021 #include <opie2/otaskbarapplet.h>
00022 #include <qpe/config.h>
00023 #include <qpe/qpeapplication.h>
00024 using namespace Opie::Core;
00025 using namespace Opie::Ui;
00026 using namespace Opie::Net;
00027
00028
00029 #include <qradiobutton.h>
00030 #include <qpushbutton.h>
00031 #include <qpainter.h>
00032 #include <qlabel.h>
00033 #include <qslider.h>
00034 #include <qbuttongroup.h>
00035 #include <qlayout.h>
00036 #include <qfile.h>
00037 #include <qtextstream.h>
00038
00039
00040 #include <math.h>
00041 #include <sys/types.h>
00042 #include <signal.h>
00043 #if defined (__GNUC__) && (__GNUC__ < 3)
00044 #define round qRound
00045 #endif
00046
00047
00048 #undef MDEBUG
00049
00050 WirelessControl::WirelessControl( WirelessApplet *applet, QWidget *parent, const char *name )
00051 : QFrame( parent, name, WStyle_StaysOnTop | WType_Popup ), applet( applet )
00052 {
00053
00054 readConfig();
00055 writeConfigEntry( "UpdateFrequency", updateFrequency );
00056
00057 setFrameStyle( QFrame::PopupPanel | QFrame::Raised );
00058 QGridLayout *grid = new QGridLayout( this, 3, 2, 6, 2, "top layout" );
00059
00060
00061
00062 statusLabel = new QLabel( this, "statuslabel" );
00063 QString text( "Wireless Status:<br>"
00064 "*** Unknown ***<br>"
00065 "Card not inserted ?<br>"
00066 "Or Sharp ROM ?<br>"
00067 "CELL: 00:00:00:00:00:00" );
00068
00069
00070
00071
00072
00073 statusLabel->setText( text );
00074 statusLabel->setFixedSize( statusLabel->sizeHint() );
00075 grid->addWidget( statusLabel, 0, 0 );
00076
00077
00078
00079
00080
00081 mgraph = new MGraph( this );
00082 mgraph->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00083 mgraph->setMin( 0 );
00084 mgraph->setMax( 92 );
00085 grid->addWidget( mgraph, 1, 0 );
00086 mgraph->setFocusPolicy( QWidget::NoFocus );
00087
00088
00089
00090 QPushButton* advanced = new QPushButton( "Advanced...", this );
00091 advanced->setFocusPolicy( QWidget::NoFocus );
00092 grid->addWidget( advanced, 2, 0, Qt::AlignCenter );
00093 connect( advanced, SIGNAL( clicked() ),
00094 this, SLOT( advancedConfigClicked() ) );
00095
00096
00097
00098 updateLabel = new QLabel( this );
00099 text.sprintf( "Update every %d s", updateFrequency );
00100 updateLabel->setText( text );
00101 grid->addWidget( updateLabel, 2, 1 );
00102
00103
00104
00105 QSlider* updateSlider = new QSlider( QSlider::Horizontal, this );
00106 updateSlider->setRange( 0, 9 );
00107 updateSlider->setValue( updateFrequency );
00108 updateSlider->setTickmarks( QSlider::Both );
00109 updateSlider->setTickInterval( 1 );
00110 updateSlider->setSteps( 1, 1 );
00111 updateSlider->setFocusPolicy( QWidget::NoFocus );
00112 grid->addWidget( updateSlider, 1, 1 );
00113 connect( updateSlider, SIGNAL( valueChanged(int) ),
00114 this, SLOT( updateDelayChange(int) ) );
00115
00116 setFixedSize( sizeHint() );
00117 setFocusPolicy( QWidget::NoFocus );
00118
00119 applet->updateDelayChange( updateFrequency );
00120
00121 applet->updateDHCPConfig( rocESSID, rocFREQ, rocAP, rocMODE );
00122 }
00123
00124 void WirelessControl::advancedConfigClicked()
00125 {
00126 AdvancedConfig * a = new AdvancedConfig( this, "dialog", TRUE );
00127 int result = a->exec();
00128 a->hide();
00129 delete a;
00130 if ( result == QDialog::Accepted )
00131 {
00132 readConfig();
00133 applet->updateDHCPConfig( rocESSID, rocFREQ, rocAP, rocMODE );
00134 }
00135 }
00136
00137 void WirelessControl::updateDelayChange( int delay )
00138 {
00139 QString text;
00140 text.sprintf( "Update every %d s", delay );
00141 updateLabel->setText( text );
00142 applet->updateDelayChange( delay );
00143 writeConfigEntry( "UpdateFrequency", delay );
00144 }
00145
00146 void WirelessControl::displayStyleChange( int style )
00147 {
00148 applet->displayStyleChange( style );
00149 writeConfigEntry( "DisplayStyle", style );
00150 }
00151
00152 void WirelessControl::show ( bool )
00153 {
00154 QPoint curPos = applet->mapToGlobal( QPoint ( 0, 0 ) );
00155
00156 int w = sizeHint().width();
00157 int x = curPos.x() - ( w / 2 );
00158
00159 if ( ( x + w ) > QPEApplication::desktop() ->width() )
00160 x = QPEApplication::desktop ( ) -> width ( ) - w;
00161
00162 move( QMAX(x,0), curPos.y () - sizeHint().height () );
00163 QFrame::show();
00164 }
00165
00166 void WirelessControl::readConfig()
00167 {
00168 Config cfg( "qpe" );
00169 cfg.setGroup( "Wireless" );
00170
00171 updateFrequency = cfg.readNumEntry( "UpdateFrequency", 2 );
00172 rocESSID = cfg.readBoolEntry( "renew_dhcp_on_essid_change", false );
00173 rocFREQ = cfg.readBoolEntry( "renew_dhcp_on_freq_change", false );
00174 rocAP = cfg.readBoolEntry( "renew_dhcp_on_ap_change", false );
00175 rocMODE = cfg.readBoolEntry( "renew_dhcp_on_mode_change", false );
00176 }
00177
00178 void WirelessControl::writeConfigEntry( const char *entry, int val )
00179 {
00180 Config cfg( "qpe" );
00181 cfg.setGroup( "Wireless" );
00182 cfg.writeEntry( entry, val );
00183 }
00184
00185
00186
00187 WirelessApplet::WirelessApplet( QWidget *parent, const char *name )
00188 : QWidget( parent, name ),
00189 timer( 0 ), interface( 0 ), oldiface( 0 ),
00190 rocESSID( false ), rocFREQ( false ), rocAP( false ), rocMODE( false )
00191 {
00192 setFixedHeight( 18 );
00193 setFixedWidth( 14 );
00194 status = new WirelessControl( this, this, "wireless status" );
00195 }
00196
00197 void WirelessApplet::checkInterface()
00198 {
00199 interface = 0L;
00200 ONetwork* net = ONetwork::instance();
00201 net->synchronize();
00202 ONetwork::InterfaceIterator it = net->iterator();
00203
00204 while ( it.current() && !it.current()->isWireless() ) ++it;
00205
00206 if ( it.current() && it.current()->isWireless() )
00207 interface = static_cast<OWirelessNetworkInterface*>( it.current() );
00208
00209 if ( interface )
00210 {
00211 #ifdef MDEBUG
00212 odebug << "WIFIAPPLET: using interface '" << ( const char* ) interface->name() << "'" << oendl;
00213 #endif
00214
00215 }
00216 else
00217 {
00218 #ifdef MDEBUG
00219 odebug << "WIFIAPPLET: D'oh! No Wireless interface present... :(" << oendl;
00220 #endif
00221 hide();
00222 }
00223 }
00224
00225 void WirelessApplet::renewDHCP()
00226 {
00227 #ifdef MDEBUG
00228 odebug << "WIFIAPPLET: Going to request a DHCP configuration renew." << oendl;
00229 #endif
00230
00231 QString pidfile;
00232 if ( !interface )
00233 return ;
00234 QString ifacename( interface->name() );
00235
00236
00237
00238 pidfile.sprintf( "/var/run/dhcpcd-%s.pid", ( const char* ) ifacename );
00239 #ifdef MDEBUG
00240 odebug << "WIFIAPPLET: dhcpcd pidfile is '" << ( const char* ) pidfile << "'" << oendl;
00241 #endif
00242 int pid;
00243 QFile pfile( pidfile );
00244 bool hasFile = pfile.open( IO_ReadOnly );
00245 QTextStream s( &pfile );
00246 if ( hasFile )
00247 {
00248 s >> pid;
00249 #ifdef MDEBUG
00250 odebug << "WIFIAPPLET: sent SIGALARM to pid " << pid << "" << oendl;
00251 #endif
00252 kill( pid, SIGALRM );
00253 return ;
00254 }
00255
00256
00257 #ifdef MDEBUG
00258 odebug << "WIFIAPPLET: dhcpcd not available." << oendl;
00259 #endif
00260 pidfile.sprintf( "/var/run/udhcpc.%s.pid", ( const char* ) ifacename );
00261 #ifdef MDEBUG
00262 odebug << "WIFIAPPLET: udhcpc pidfile is '" << ( const char* ) pidfile << "'" << oendl;
00263 #endif
00264 QFile pfile2( pidfile );
00265 hasFile = pfile2.open( IO_ReadOnly );
00266 QTextStream s2( &pfile2 );
00267 if ( hasFile )
00268 {
00269 s2 >> pid;
00270 #ifdef MDEBUG
00271 odebug << "WIFIAPPLET: sent SIGUSR1 to pid " << pid << "" << oendl;
00272 #endif
00273 kill( pid, SIGUSR1 );
00274 return ;
00275 }
00276 }
00277
00278 void WirelessApplet::updateDHCPConfig( bool ESSID, bool FREQ, bool AP, bool MODE )
00279 {
00280 rocESSID = ESSID;
00281 rocFREQ = FREQ;
00282 rocAP = AP;
00283 rocMODE = MODE;
00284 }
00285
00286 void WirelessApplet::updateDelayChange( int delay )
00287 {
00288 if ( timer )
00289 killTimer( timer );
00290 delay *= 1000;
00291 if ( delay == 0 )
00292 delay = 50;
00293 timer = startTimer( delay );
00294 }
00295
00296 void WirelessApplet::displayStyleChange( int style )
00297 {
00298 visualStyle = style;
00299 repaint();
00300 }
00301
00302 WirelessApplet::~WirelessApplet()
00303 {}
00304
00305 void WirelessApplet::timerEvent( QTimerEvent* )
00306 {
00307 #ifdef MDEBUG
00308 odebug << "WirelessApplet::timerEvent" << oendl;
00309 #endif
00310 if ( interface )
00311 {
00312 if ( !ONetwork::instance()->isPresent( (const char*) interface->name() ) )
00313 {
00314 #ifdef MDEBUG
00315 odebug << "WIFIAPPLET: Interface no longer present." << oendl;
00316 #endif
00317 interface = 0L;
00318 mustRepaint();
00319 return;
00320 }
00321
00322 if ( mustRepaint() )
00323 {
00324 #ifdef MDEBUG
00325 odebug << "WIFIAPPLET: A value has changed -> repainting." << oendl;
00326 #endif
00327 repaint();
00328 }
00329
00330 if ( status->isVisible() )
00331 {
00332 updatePopupWindow();
00333 }
00334 }
00335 else
00336 {
00337 checkInterface();
00338 }
00339 }
00340
00341 void WirelessApplet::mousePressEvent( QMouseEvent * )
00342 {
00343 if ( status->isVisible() )
00344 status->hide();
00345 else
00346 status->show( true );
00347 }
00348
00349 bool WirelessApplet::mustRepaint()
00350 {
00351
00352
00353
00354
00355 if ( interface != oldiface )
00356 {
00357 oldiface = interface;
00358 if ( interface )
00359 {
00360 #ifdef MDEBUG
00361 odebug << "WIFIAPPLET: We had no interface but now we have one! :-)" << oendl;
00362 #endif
00363 show();
00364 }
00365 else
00366 {
00367 #ifdef MDEBUG
00368 odebug << "WIFIAPPLET: We had a interface but now we don't have one! ;-(" << oendl;
00369 #endif
00370 hide();
00371 return true;
00372 }
00373 }
00374
00375 int rings = numberOfRings();
00376
00377 if ( rings != oldrings )
00378 {
00379 oldrings = rings;
00380 return true;
00381 }
00382
00383 int noiseH = 50;
00384 int signalH = interface->signalStrength() * ( height() - 3 ) / 100;
00385 int qualityH = 50;
00386
00387 if ( ( noiseH != oldnoiseH )
00388 || ( signalH != oldsignalH )
00389 || ( qualityH != oldqualityH ) )
00390 {
00391 oldnoiseH = noiseH;
00392 oldsignalH = signalH;
00393 oldqualityH = qualityH;
00394 return true;
00395 }
00396
00397 if ( rocESSID && ( oldESSID != interface->SSID() ) )
00398 {
00399 #ifdef MDEBUG
00400 odebug << "WIFIAPPLET: ESSID has changed." << oendl;
00401 #endif
00402 renewDHCP();
00403 }
00404 else if ( rocFREQ && ( oldFREQ != interface->frequency() ) )
00405 {
00406 #ifdef MDEBUG
00407 odebug << "WIFIAPPLET: FREQ has changed." << oendl;
00408 #endif
00409 renewDHCP();
00410 }
00411 else if ( rocAP && ( oldAP != interface->associatedAP().toString() ) )
00412 {
00413 #ifdef MDEBUG
00414 odebug << "WIFIAPPLET: AP has changed." << oendl;
00415 #endif
00416 renewDHCP();
00417 }
00418 else if ( rocMODE && ( oldMODE != interface->mode() ) )
00419 {
00420 #ifdef MDEBUG
00421 odebug << "WIFIAPPLET: MODE has changed." << oendl;
00422 #endif
00423 renewDHCP();
00424 }
00425
00426 oldESSID = interface->SSID();
00427 oldMODE = interface->mode();
00428 oldFREQ = interface->frequency();
00429 oldAP = interface->associatedAP().toString();
00430
00431 return false;
00432 }
00433
00434 void WirelessApplet::updatePopupWindow()
00435 {
00436 int qualityH = interface->signalStrength();
00437
00438 if ( status->mgraph )
00439 status->mgraph->addValue( qualityH, false );
00440
00441 QString freqString;
00442 QString cell = ( interface->mode() == "Managed" ) ? "AP: " : "Cell: ";
00443 freqString.sprintf( "%.3f GHz", interface->frequency() );
00444 status->statusLabel->setText( "Station: " + interface->nickName() + "<br>" +
00445 "ESSID: " + interface->SSID() + "<br>" +
00446 "MODE: " + interface->mode() + "<br>" +
00447 "FREQ: " + freqString + "<br>" +
00448 cell + " " + interface->associatedAP().toString() );
00449 }
00450
00451 int WirelessApplet::numberOfRings()
00452 {
00453 if ( !interface ) return -1;
00454 int qualityH = interface->signalStrength();
00455 odebug << "quality = " << qualityH << "" << oendl;
00456 if ( qualityH < 1 ) return -1;
00457 if ( qualityH < 20 ) return 0;
00458 if ( qualityH < 40 ) return 1;
00459 if ( qualityH < 60 ) return 2;
00460 if ( qualityH < 65 ) return 3;
00461 return 4;
00462 }
00463
00464 void WirelessApplet::paintEvent( QPaintEvent* )
00465 {
00466 QPainter p( this );
00467 int h = height();
00468 int w = width();
00469 int m = 2;
00470
00471 p.drawLine( m, h-m-1, round( w/2.0 ), round( 0+h/3.0 ) );
00472 p.drawLine( round( w/2.0 ), round( 0+h/3.0 ), w-m, h-m-1 );
00473 p.setPen( QColor( 150, 150, 150 ) );
00474 p.drawLine( w-m, h-m-1, m, h-m-1 );
00475
00476 int rings = numberOfRings();
00477
00478 if ( rings == -1 )
00479 {
00480 p.setPen( QPen( QColor( 200, 20, 20 ), 2 ) );
00481 p.drawLine( w/2-m-m, h/2-m-m, w/2+m+m, h/2+m+m );
00482 p.drawLine( w/2+m+m, h/2-m-m, w/2-m-m, h/2+m+m );
00483 return;
00484 }
00485
00486 odebug << "WirelessApplet: painting " << rings << " rings" << oendl;
00487 int radius = 2;
00488 int rstep = 4;
00489 int maxrings = w/rstep;
00490
00491 p.setPen( QColor( 200, 20, 20 ) );
00492 for ( int i = 0; i < rings; ++i )
00493 {
00494 p.drawEllipse( w/2 - radius/2, h/3 - radius/2, radius, radius );
00495 radius += rstep;
00496 };
00497
00498
00499
00500 }
00501
00502
00503 int WirelessApplet::position()
00504 {
00505 return 6;
00506 }
00507
00508 EXPORT_OPIE_APPLET_v1( WirelessApplet )
00509