KNemo – network interfaces monitor for systray
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.

488 lines
16KB

  1. /* This file is part of KNemo
  2. Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de>
  3. KNemo is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of
  6. the License, or (at your option) any later version.
  7. KNemo is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. Boston, MA 02110-1301, USA.
  15. */
  16. #include <tqtimer.h>
  17. #include <tqpixmap.h>
  18. #include <twin.h>
  19. #include <kdebug.h>
  20. #include <tdelocale.h>
  21. #include <twinmodule.h>
  22. #include <kiconloader.h>
  23. #include "interface.h"
  24. #include "signalplotter.h"
  25. #include "interfacestatistics.h"
  26. #include "interfacestatusdialog.h"
  27. #include "interfacestatisticsdialog.h"
  28. Interface::Interface( TQString ifname,
  29. const GeneralData& generalData,
  30. const PlotterSettings& plotterSettings )
  31. : TQObject(),
  32. mType( UNKNOWN_TYPE ),
  33. mState( UNKNOWN_STATE ),
  34. mOutgoingPos( 0 ),
  35. mIncomingPos( 0 ),
  36. mName( ifname ),
  37. mPlotterTimer( 0 ),
  38. mIcon( this ),
  39. mStatistics( 0 ),
  40. mStatusDialog( 0 ),
  41. mStatisticsDialog( 0 ),
  42. mPlotter( 0 ),
  43. mVisibleBeams( NONE ),
  44. mGeneralData( generalData ),
  45. mPlotterSettings( plotterSettings )
  46. {
  47. connect( &mMonitor, TQT_SIGNAL( statusChanged( int ) ),
  48. &mIcon, TQT_SLOT( updateStatus( int ) ) );
  49. connect( &mMonitor, TQT_SIGNAL( available( int ) ),
  50. &mIcon, TQT_SLOT( updateTrayStatus( int ) ) );
  51. connect( &mMonitor, TQT_SIGNAL( notAvailable( int ) ),
  52. &mIcon, TQT_SLOT( updateTrayStatus( int ) ) );
  53. connect( &mMonitor, TQT_SIGNAL( notExisting( int ) ),
  54. &mIcon, TQT_SLOT( updateTrayStatus( int ) ) );
  55. connect( &mMonitor, TQT_SIGNAL( available( int ) ),
  56. this, TQT_SLOT( setStartTime( int ) ) );
  57. connect( &mMonitor, TQT_SIGNAL( statusChanged( int ) ),
  58. this, TQT_SLOT( resetData( int ) ) );
  59. connect( &mIcon, TQT_SIGNAL( statisticsSelected() ),
  60. this, TQT_SLOT( showStatisticsDialog() ) );
  61. }
  62. Interface::~Interface()
  63. {
  64. if ( mStatusDialog != 0 )
  65. {
  66. delete mStatusDialog;
  67. }
  68. if ( mPlotter != 0 )
  69. {
  70. delete mPlotter;
  71. }
  72. if ( mPlotterTimer != 0 )
  73. {
  74. mPlotterTimer->stop();
  75. delete mPlotterTimer;
  76. }
  77. if ( mStatistics != 0 )
  78. {
  79. // this will also delete a possibly open statistics dialog
  80. stopStatistics();
  81. }
  82. }
  83. void Interface::configChanged()
  84. {
  85. // UNKNOWN_STATE to avoid notification
  86. mIcon.updateTrayStatus( UNKNOWN_STATE );
  87. // handle changed iconset by user
  88. mIcon.updateStatus( mState );
  89. mIcon.updateToolTip();
  90. mIcon.updateMenu();
  91. if ( mPlotter != 0L )
  92. {
  93. configurePlotter();
  94. }
  95. if ( mStatistics != 0 )
  96. {
  97. mStatistics->configChanged();
  98. }
  99. if ( mSettings.activateStatistics && mStatistics == 0 )
  100. {
  101. // user turned on statistics
  102. startStatistics();
  103. }
  104. else if ( !mSettings.activateStatistics && mStatistics != 0 )
  105. {
  106. // user turned off statistics
  107. stopStatistics();
  108. }
  109. if ( mStatusDialog )
  110. {
  111. mStatusDialog->setStatisticsGroupEnabled( mSettings.activateStatistics );
  112. }
  113. }
  114. void Interface::activateMonitor()
  115. {
  116. mMonitor.checkStatus( this );
  117. }
  118. void Interface::setStartTime( int )
  119. {
  120. mStartTime.setDate( TQDate::currentDate() );
  121. mStartTime.setTime( TQTime::currentTime() );
  122. }
  123. void Interface::showStatusDialog()
  124. {
  125. // Toggle the status dialog.
  126. // First click will show the status dialog, second will hide it.
  127. if ( mStatusDialog == 0L )
  128. {
  129. mStatusDialog = new InterfaceStatusDialog( this );
  130. connect( &mMonitor, TQT_SIGNAL( available( int ) ),
  131. mStatusDialog, TQT_SLOT( enableNetworkGroups( int ) ) );
  132. connect( &mMonitor, TQT_SIGNAL( notAvailable( int ) ),
  133. mStatusDialog, TQT_SLOT( disableNetworkGroups( int ) ) );
  134. connect( &mMonitor, TQT_SIGNAL( notExisting( int ) ),
  135. mStatusDialog, TQT_SLOT( disableNetworkGroups( int ) ) );
  136. if ( mStatistics != 0 )
  137. {
  138. connect( mStatistics, TQT_SIGNAL( currentEntryChanged() ),
  139. mStatusDialog, TQT_SLOT( statisticsChanged() ) );
  140. mStatusDialog->statisticsChanged();
  141. }
  142. activateOrHide( mStatusDialog, true );
  143. }
  144. else
  145. {
  146. // Toggle the status dialog.
  147. activateOrHide( mStatusDialog );
  148. }
  149. }
  150. void Interface::showSignalPlotter( bool wasMiddleButton )
  151. {
  152. // No plotter, create it.
  153. if ( mPlotter == 0L )
  154. {
  155. mPlotter = new SignalPlotter( 0L, mName.local8Bit() );
  156. mPlotter->setIcon( SmallIcon( "knemo" ) );
  157. mPlotter->setCaption( mName + " " + i18n( "Traffic" ) );
  158. mPlotter->setTitle( mName );
  159. configurePlotter();
  160. activateOrHide( mPlotter, true );
  161. mPlotterTimer = new TQTimer();
  162. connect( mPlotterTimer, TQT_SIGNAL( timeout() ),
  163. this, TQT_SLOT( updatePlotter() ) );
  164. mPlotterTimer->start( 1000 );
  165. }
  166. else
  167. {
  168. if ( wasMiddleButton )
  169. {
  170. // Toggle the signal plotter.
  171. activateOrHide( mPlotter );
  172. }
  173. else
  174. {
  175. // Called from the context menu, show the dialog.
  176. activateOrHide( mPlotter, true );
  177. }
  178. }
  179. }
  180. void Interface::showStatisticsDialog()
  181. {
  182. if ( mStatisticsDialog == 0 )
  183. {
  184. mStatisticsDialog = new InterfaceStatisticsDialog( this );
  185. if ( mStatistics == 0 )
  186. {
  187. // should never happen but you never know...
  188. startStatistics();
  189. }
  190. connect( mStatistics, TQT_SIGNAL( dayStatisticsChanged() ),
  191. mStatisticsDialog, TQT_SLOT( updateDays() ) );
  192. connect( mStatistics, TQT_SIGNAL( monthStatisticsChanged() ),
  193. mStatisticsDialog, TQT_SLOT( updateMonths() ) );
  194. connect( mStatistics, TQT_SIGNAL( yearStatisticsChanged() ),
  195. mStatisticsDialog, TQT_SLOT( updateYears() ) );
  196. connect( mStatistics, TQT_SIGNAL( currentEntryChanged() ),
  197. mStatisticsDialog, TQT_SLOT( updateCurrentEntry() ) );
  198. connect( mStatisticsDialog, TQT_SIGNAL( clearDailyStatisticsClicked() ),
  199. mStatistics, TQT_SLOT( clearDayStatistics() ) );
  200. connect( mStatisticsDialog, TQT_SIGNAL( clearMonthlyStatisticsClicked() ),
  201. mStatistics, TQT_SLOT( clearMonthStatistics() ) );
  202. connect( mStatisticsDialog, TQT_SIGNAL( clearYearlyStatisticsClicked() ),
  203. mStatistics, TQT_SLOT( clearYearStatistics() ) );
  204. mStatisticsDialog->updateDays();
  205. mStatisticsDialog->updateMonths();
  206. mStatisticsDialog->updateYears();
  207. }
  208. mStatisticsDialog->show();
  209. }
  210. void Interface::resetData( int state )
  211. {
  212. // For PPP interfaces we will reset all data to zero when the
  213. // interface gets disconnected. If the driver also resets its data
  214. // (like PPP seems to do) we will start from zero for every new
  215. // connection.
  216. if ( mType == PPP &&
  217. ( state == NOT_AVAILABLE ||
  218. state == NOT_EXISTING ) )
  219. {
  220. mData.prevTxBytes = mData.txBytes = 0;
  221. mData.prevRxBytes = mData.rxBytes = 0;
  222. mData.prevTxPackets = mData.txPackets = 0;
  223. mData.prevRxPackets = mData.rxPackets = 0;
  224. }
  225. }
  226. void Interface::updatePlotter()
  227. {
  228. if ( mPlotter )
  229. {
  230. double outgoingBytes = mData.outgoingBytes / 1024.0 / (double) mGeneralData.pollInterval;
  231. double incomingBytes = mData.incomingBytes / 1024.0 / (double) mGeneralData.pollInterval;
  232. TQValueList<double> trafficList;
  233. switch ( mVisibleBeams )
  234. {
  235. case BOTH:
  236. if ( mIncomingPos == 1 )
  237. {
  238. trafficList.append( outgoingBytes );
  239. trafficList.append( incomingBytes );
  240. }
  241. else
  242. {
  243. trafficList.append( incomingBytes );
  244. trafficList.append( outgoingBytes );
  245. }
  246. mPlotter->addSample( trafficList );
  247. break;
  248. case INCOMING_TRAFFIC:
  249. trafficList.append( incomingBytes );
  250. mPlotter->addSample( trafficList );
  251. break;
  252. case OUTGOING_TRAFFIC:
  253. trafficList.append( outgoingBytes );
  254. mPlotter->addSample( trafficList );
  255. break;
  256. case NONE:
  257. break;
  258. }
  259. }
  260. }
  261. void Interface::configurePlotter()
  262. {
  263. mPlotter->setFontSize( mPlotterSettings.fontSize );
  264. if ( !mPlotterSettings.automaticDetection )
  265. {
  266. mPlotter->setMinValue( mPlotterSettings.minimumValue );
  267. mPlotter->setMaxValue( mPlotterSettings.maximumValue );
  268. }
  269. mPlotter->setHorizontalScale( mPlotterSettings.pixel );
  270. mPlotter->setHorizontalLinesCount( mPlotterSettings.count );
  271. mPlotter->setVerticalLinesDistance( mPlotterSettings.distance );
  272. mPlotter->setShowLabels( mPlotterSettings.labels );
  273. mPlotter->setShowTopBar( mPlotterSettings.topBar );
  274. mPlotter->setShowVerticalLines( mPlotterSettings.verticalLines );
  275. mPlotter->setShowHorizontalLines( mPlotterSettings.horizontalLines );
  276. mPlotter->setUseAutoRange( mPlotterSettings.automaticDetection );
  277. mPlotter->setVerticalLinesScroll( mPlotterSettings.verticalLinesScroll );
  278. mPlotter->setVerticalLinesColor( mPlotterSettings.colorVLines );
  279. mPlotter->setHorizontalLinesColor( mPlotterSettings.colorHLines );
  280. mPlotter->setBackgroundColor( mPlotterSettings.colorBackground );
  281. // add or remove beams according to user settings
  282. VisibleBeams nextVisibleBeams = NONE;
  283. if ( mPlotterSettings.showOutgoing )
  284. nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | OUTGOING_TRAFFIC );
  285. if ( mPlotterSettings.showIncoming )
  286. nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | INCOMING_TRAFFIC );
  287. TQValueList<TQColor>& colors = mPlotter->beamColors();
  288. switch( mVisibleBeams )
  289. {
  290. case NONE:
  291. if ( nextVisibleBeams == BOTH )
  292. {
  293. mOutgoingPos = 0;
  294. mPlotter->addBeam( mPlotterSettings.colorOutgoing );
  295. mIncomingPos = 1;
  296. mPlotter->addBeam( mPlotterSettings.colorIncoming );
  297. }
  298. else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
  299. {
  300. mOutgoingPos = 0;
  301. mPlotter->addBeam( mPlotterSettings.colorOutgoing );
  302. }
  303. else if ( nextVisibleBeams == INCOMING_TRAFFIC )
  304. {
  305. mIncomingPos = 0;
  306. mPlotter->addBeam( mPlotterSettings.colorIncoming );
  307. }
  308. break;
  309. case INCOMING_TRAFFIC:
  310. if ( nextVisibleBeams == BOTH )
  311. {
  312. mOutgoingPos = 1;
  313. mPlotter->addBeam( mPlotterSettings.colorOutgoing );
  314. }
  315. else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
  316. {
  317. mPlotter->removeBeam( mIncomingPos );
  318. mOutgoingPos = 0;
  319. mPlotter->addBeam( mPlotterSettings.colorOutgoing );
  320. }
  321. else if ( nextVisibleBeams == INCOMING_TRAFFIC )
  322. {
  323. colors[mIncomingPos] = ( mPlotterSettings.colorIncoming );
  324. }
  325. else if ( nextVisibleBeams == NONE )
  326. {
  327. mPlotter->removeBeam( mIncomingPos );
  328. }
  329. break;
  330. case OUTGOING_TRAFFIC:
  331. if ( nextVisibleBeams == BOTH )
  332. {
  333. mIncomingPos = 1;
  334. mPlotter->addBeam( mPlotterSettings.colorIncoming );
  335. }
  336. else if ( nextVisibleBeams == INCOMING_TRAFFIC )
  337. {
  338. mPlotter->removeBeam( mOutgoingPos );
  339. mIncomingPos = 0;
  340. mPlotter->addBeam( mPlotterSettings.colorIncoming );
  341. }
  342. else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
  343. {
  344. colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing );
  345. }
  346. else if ( nextVisibleBeams == NONE )
  347. {
  348. mPlotter->removeBeam( mOutgoingPos );
  349. }
  350. break;
  351. case BOTH:
  352. if ( nextVisibleBeams == BOTH )
  353. {
  354. colors[mIncomingPos] = ( mPlotterSettings.colorIncoming );
  355. colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing );
  356. }
  357. else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
  358. {
  359. mOutgoingPos = 0;
  360. mPlotter->removeBeam( mIncomingPos );
  361. }
  362. else if ( nextVisibleBeams == INCOMING_TRAFFIC )
  363. {
  364. mIncomingPos = 0;
  365. mPlotter->removeBeam( mOutgoingPos );
  366. }
  367. else if ( nextVisibleBeams == NONE )
  368. {
  369. mPlotter->removeBeam( 0 );
  370. mPlotter->removeBeam( 0 );
  371. }
  372. break;
  373. }
  374. mVisibleBeams = nextVisibleBeams;
  375. mPlotter->repaint();
  376. }
  377. void Interface::startStatistics()
  378. {
  379. mStatistics = new InterfaceStatistics( this );
  380. connect( &mMonitor, TQT_SIGNAL( incomingData( unsigned long ) ),
  381. mStatistics, TQT_SLOT( addIncomingData( unsigned long ) ) );
  382. connect( &mMonitor, TQT_SIGNAL( outgoingData( unsigned long ) ),
  383. mStatistics, TQT_SLOT( addOutgoingData( unsigned long ) ) );
  384. if ( mStatusDialog != 0 )
  385. {
  386. connect( mStatistics, TQT_SIGNAL( currentEntryChanged() ),
  387. mStatusDialog, TQT_SLOT( statisticsChanged() ) );
  388. mStatusDialog->statisticsChanged();
  389. }
  390. mStatistics->loadStatistics();
  391. }
  392. void Interface::stopStatistics()
  393. {
  394. if ( mStatisticsDialog != 0 )
  395. {
  396. // this will close an open statistics dialog
  397. delete mStatisticsDialog;
  398. mStatisticsDialog = 0;
  399. }
  400. mStatistics->saveStatistics();
  401. delete mStatistics;
  402. mStatistics = 0;
  403. }
  404. // taken from ksystemtray.cpp
  405. void Interface::activateOrHide( TQWidget* widget, bool onlyActivate )
  406. {
  407. if ( !widget )
  408. return;
  409. KWin::WindowInfo info1 = KWin::windowInfo( widget->winId(), NET::XAWMState | NET::WMState );
  410. // mapped = visible (but possibly obscured)
  411. bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
  412. // - not mapped -> show, raise, focus
  413. // - mapped
  414. // - obscured -> raise, focus
  415. // - not obscured -> hide
  416. if( !mapped )
  417. {
  418. KWin::setOnDesktop( widget->winId(), KWin::currentDesktop() );
  419. widget->show();
  420. widget->raise();
  421. KWin::activateWindow( widget->winId() );
  422. }
  423. else
  424. {
  425. KWinModule module;
  426. for( TQValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
  427. it != module.stackingOrder().end() && (*it) != widget->winId();
  428. --it )
  429. {
  430. KWin::WindowInfo info2 = KWin::windowInfo( *it, (unsigned long)
  431. NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
  432. if( info2.mappingState() != NET::Visible )
  433. continue; // not visible on current desktop -> ignore
  434. if( !info2.geometry().intersects( widget->geometry()))
  435. continue; // not obscuring the window -> ignore
  436. if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
  437. continue; // obscured by window kept above -> ignore
  438. NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
  439. | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
  440. | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
  441. if( type == NET::Dock || type == NET::TopMenu )
  442. continue; // obscured by dock or topmenu -> ignore
  443. widget->raise();
  444. KWin::activateWindow( widget->winId());
  445. return;
  446. }
  447. if ( !onlyActivate )
  448. {
  449. widget->hide();
  450. }
  451. }
  452. }
  453. #include "interface.moc"