summaryrefslogtreecommitdiffstats
path: root/src/knemod/interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/knemod/interface.cpp')
-rw-r--r--src/knemod/interface.cpp487
1 files changed, 487 insertions, 0 deletions
diff --git a/src/knemod/interface.cpp b/src/knemod/interface.cpp
new file mode 100644
index 0000000..2378662
--- /dev/null
+++ b/src/knemod/interface.cpp
@@ -0,0 +1,487 @@
+/* This file is part of KNemo
+ Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de>
+
+ KNemo is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ KNemo 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtimer.h>
+#include <qpixmap.h>
+
+#include <kwin.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kwinmodule.h>
+#include <kiconloader.h>
+
+#include "interface.h"
+#include "signalplotter.h"
+#include "interfacestatistics.h"
+#include "interfacestatusdialog.h"
+#include "interfacestatisticsdialog.h"
+
+Interface::Interface( QString ifname,
+ const GeneralData& generalData,
+ const PlotterSettings& plotterSettings )
+ : QObject(),
+ mType( UNKNOWN_TYPE ),
+ mState( UNKNOWN_STATE ),
+ mOutgoingPos( 0 ),
+ mIncomingPos( 0 ),
+ mName( ifname ),
+ mPlotterTimer( 0 ),
+ mIcon( this ),
+ mStatistics( 0 ),
+ mStatusDialog( 0 ),
+ mStatisticsDialog( 0 ),
+ mPlotter( 0 ),
+ mVisibleBeams( NONE ),
+ mGeneralData( generalData ),
+ mPlotterSettings( plotterSettings )
+{
+ connect( &mMonitor, SIGNAL( statusChanged( int ) ),
+ &mIcon, SLOT( updateStatus( int ) ) );
+ connect( &mMonitor, SIGNAL( available( int ) ),
+ &mIcon, SLOT( updateTrayStatus( int ) ) );
+ connect( &mMonitor, SIGNAL( notAvailable( int ) ),
+ &mIcon, SLOT( updateTrayStatus( int ) ) );
+ connect( &mMonitor, SIGNAL( notExisting( int ) ),
+ &mIcon, SLOT( updateTrayStatus( int ) ) );
+ connect( &mMonitor, SIGNAL( available( int ) ),
+ this, SLOT( setStartTime( int ) ) );
+ connect( &mMonitor, SIGNAL( statusChanged( int ) ),
+ this, SLOT( resetData( int ) ) );
+ connect( &mIcon, SIGNAL( statisticsSelected() ),
+ this, SLOT( showStatisticsDialog() ) );
+}
+
+Interface::~Interface()
+{
+ if ( mStatusDialog != 0 )
+ {
+ delete mStatusDialog;
+ }
+ if ( mPlotter != 0 )
+ {
+ delete mPlotter;
+ }
+ if ( mPlotterTimer != 0 )
+ {
+ mPlotterTimer->stop();
+ delete mPlotterTimer;
+ }
+ if ( mStatistics != 0 )
+ {
+ // this will also delete a possibly open statistics dialog
+ stopStatistics();
+ }
+}
+
+void Interface::configChanged()
+{
+ // UNKNOWN_STATE to avoid notification
+ mIcon.updateTrayStatus( UNKNOWN_STATE );
+ // handle changed iconset by user
+ mIcon.updateStatus( mState );
+ mIcon.updateToolTip();
+ mIcon.updateMenu();
+
+ if ( mPlotter != 0L )
+ {
+ configurePlotter();
+ }
+
+ if ( mStatistics != 0 )
+ {
+ mStatistics->configChanged();
+ }
+
+ if ( mSettings.activateStatistics && mStatistics == 0 )
+ {
+ // user turned on statistics
+ startStatistics();
+ }
+ else if ( !mSettings.activateStatistics && mStatistics != 0 )
+ {
+ // user turned off statistics
+ stopStatistics();
+ }
+
+ if ( mStatusDialog )
+ {
+ mStatusDialog->setStatisticsGroupEnabled( mSettings.activateStatistics );
+ }
+}
+
+void Interface::activateMonitor()
+{
+ mMonitor.checkStatus( this );
+}
+
+void Interface::setStartTime( int )
+{
+ mStartTime.setDate( QDate::currentDate() );
+ mStartTime.setTime( QTime::currentTime() );
+}
+
+void Interface::showStatusDialog()
+{
+ // Toggle the status dialog.
+ // First click will show the status dialog, second will hide it.
+ if ( mStatusDialog == 0L )
+ {
+ mStatusDialog = new InterfaceStatusDialog( this );
+ connect( &mMonitor, SIGNAL( available( int ) ),
+ mStatusDialog, SLOT( enableNetworkGroups( int ) ) );
+ connect( &mMonitor, SIGNAL( notAvailable( int ) ),
+ mStatusDialog, SLOT( disableNetworkGroups( int ) ) );
+ connect( &mMonitor, SIGNAL( notExisting( int ) ),
+ mStatusDialog, SLOT( disableNetworkGroups( int ) ) );
+ if ( mStatistics != 0 )
+ {
+ connect( mStatistics, SIGNAL( currentEntryChanged() ),
+ mStatusDialog, SLOT( statisticsChanged() ) );
+ mStatusDialog->statisticsChanged();
+ }
+ activateOrHide( mStatusDialog, true );
+ }
+ else
+ {
+ // Toggle the status dialog.
+ activateOrHide( mStatusDialog );
+ }
+}
+
+void Interface::showSignalPlotter( bool wasMiddleButton )
+{
+ // No plotter, create it.
+ if ( mPlotter == 0L )
+ {
+ mPlotter = new SignalPlotter( 0L, mName.local8Bit() );
+ mPlotter->setIcon( SmallIcon( "knemo" ) );
+ mPlotter->setCaption( mName + " " + i18n( "Traffic" ) );
+ mPlotter->setTitle( mName );
+ configurePlotter();
+ activateOrHide( mPlotter, true );
+
+ mPlotterTimer = new QTimer();
+ connect( mPlotterTimer, SIGNAL( timeout() ),
+ this, SLOT( updatePlotter() ) );
+ mPlotterTimer->start( 1000 );
+ }
+ else
+ {
+ if ( wasMiddleButton )
+ {
+ // Toggle the signal plotter.
+ activateOrHide( mPlotter );
+ }
+ else
+ {
+ // Called from the context menu, show the dialog.
+ activateOrHide( mPlotter, true );
+ }
+ }
+}
+
+void Interface::showStatisticsDialog()
+{
+ if ( mStatisticsDialog == 0 )
+ {
+ mStatisticsDialog = new InterfaceStatisticsDialog( this );
+ if ( mStatistics == 0 )
+ {
+ // should never happen but you never know...
+ startStatistics();
+ }
+ connect( mStatistics, SIGNAL( dayStatisticsChanged() ),
+ mStatisticsDialog, SLOT( updateDays() ) );
+ connect( mStatistics, SIGNAL( monthStatisticsChanged() ),
+ mStatisticsDialog, SLOT( updateMonths() ) );
+ connect( mStatistics, SIGNAL( yearStatisticsChanged() ),
+ mStatisticsDialog, SLOT( updateYears() ) );
+ connect( mStatistics, SIGNAL( currentEntryChanged() ),
+ mStatisticsDialog, SLOT( updateCurrentEntry() ) );
+ connect( mStatisticsDialog, SIGNAL( clearDailyStatisticsClicked() ),
+ mStatistics, SLOT( clearDayStatistics() ) );
+ connect( mStatisticsDialog, SIGNAL( clearMonthlyStatisticsClicked() ),
+ mStatistics, SLOT( clearMonthStatistics() ) );
+ connect( mStatisticsDialog, SIGNAL( clearYearlyStatisticsClicked() ),
+ mStatistics, SLOT( clearYearStatistics() ) );
+
+ mStatisticsDialog->updateDays();
+ mStatisticsDialog->updateMonths();
+ mStatisticsDialog->updateYears();
+ }
+ mStatisticsDialog->show();
+}
+
+void Interface::resetData( int state )
+{
+ // For PPP interfaces we will reset all data to zero when the
+ // interface gets disconnected. If the driver also resets its data
+ // (like PPP seems to do) we will start from zero for every new
+ // connection.
+ if ( mType == PPP &&
+ ( state == NOT_AVAILABLE ||
+ state == NOT_EXISTING ) )
+ {
+ mData.prevTxBytes = mData.txBytes = 0;
+ mData.prevRxBytes = mData.rxBytes = 0;
+ mData.prevTxPackets = mData.txPackets = 0;
+ mData.prevRxPackets = mData.rxPackets = 0;
+ }
+}
+
+void Interface::updatePlotter()
+{
+ if ( mPlotter )
+ {
+ double outgoingBytes = mData.outgoingBytes / 1024.0 / (double) mGeneralData.pollInterval;
+ double incomingBytes = mData.incomingBytes / 1024.0 / (double) mGeneralData.pollInterval;
+
+ QValueList<double> trafficList;
+ switch ( mVisibleBeams )
+ {
+ case BOTH:
+ if ( mIncomingPos == 1 )
+ {
+ trafficList.append( outgoingBytes );
+ trafficList.append( incomingBytes );
+ }
+ else
+ {
+ trafficList.append( incomingBytes );
+ trafficList.append( outgoingBytes );
+ }
+ mPlotter->addSample( trafficList );
+ break;
+ case INCOMING_TRAFFIC:
+ trafficList.append( incomingBytes );
+ mPlotter->addSample( trafficList );
+ break;
+ case OUTGOING_TRAFFIC:
+ trafficList.append( outgoingBytes );
+ mPlotter->addSample( trafficList );
+ break;
+ case NONE:
+ break;
+ }
+ }
+}
+
+void Interface::configurePlotter()
+{
+ mPlotter->setFontSize( mPlotterSettings.fontSize );
+ if ( !mPlotterSettings.automaticDetection )
+ {
+ mPlotter->setMinValue( mPlotterSettings.minimumValue );
+ mPlotter->setMaxValue( mPlotterSettings.maximumValue );
+ }
+ mPlotter->setHorizontalScale( mPlotterSettings.pixel );
+ mPlotter->setHorizontalLinesCount( mPlotterSettings.count );
+ mPlotter->setVerticalLinesDistance( mPlotterSettings.distance );
+ mPlotter->setShowLabels( mPlotterSettings.labels );
+ mPlotter->setShowTopBar( mPlotterSettings.topBar );
+ mPlotter->setShowVerticalLines( mPlotterSettings.verticalLines );
+ mPlotter->setShowHorizontalLines( mPlotterSettings.horizontalLines );
+ mPlotter->setUseAutoRange( mPlotterSettings.automaticDetection );
+ mPlotter->setVerticalLinesScroll( mPlotterSettings.verticalLinesScroll );
+ mPlotter->setVerticalLinesColor( mPlotterSettings.colorVLines );
+ mPlotter->setHorizontalLinesColor( mPlotterSettings.colorHLines );
+ mPlotter->setBackgroundColor( mPlotterSettings.colorBackground );
+
+ // add or remove beams according to user settings
+ VisibleBeams nextVisibleBeams = NONE;
+ if ( mPlotterSettings.showOutgoing )
+ nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | OUTGOING_TRAFFIC );
+ if ( mPlotterSettings.showIncoming )
+ nextVisibleBeams = (VisibleBeams) ( nextVisibleBeams | INCOMING_TRAFFIC );
+
+ QValueList<QColor>& colors = mPlotter->beamColors();
+ switch( mVisibleBeams )
+ {
+ case NONE:
+ if ( nextVisibleBeams == BOTH )
+ {
+ mOutgoingPos = 0;
+ mPlotter->addBeam( mPlotterSettings.colorOutgoing );
+ mIncomingPos = 1;
+ mPlotter->addBeam( mPlotterSettings.colorIncoming );
+ }
+ else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
+ {
+ mOutgoingPos = 0;
+ mPlotter->addBeam( mPlotterSettings.colorOutgoing );
+ }
+ else if ( nextVisibleBeams == INCOMING_TRAFFIC )
+ {
+ mIncomingPos = 0;
+ mPlotter->addBeam( mPlotterSettings.colorIncoming );
+ }
+ break;
+ case INCOMING_TRAFFIC:
+ if ( nextVisibleBeams == BOTH )
+ {
+ mOutgoingPos = 1;
+ mPlotter->addBeam( mPlotterSettings.colorOutgoing );
+ }
+ else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
+ {
+ mPlotter->removeBeam( mIncomingPos );
+ mOutgoingPos = 0;
+ mPlotter->addBeam( mPlotterSettings.colorOutgoing );
+ }
+ else if ( nextVisibleBeams == INCOMING_TRAFFIC )
+ {
+ colors[mIncomingPos] = ( mPlotterSettings.colorIncoming );
+ }
+ else if ( nextVisibleBeams == NONE )
+ {
+ mPlotter->removeBeam( mIncomingPos );
+ }
+ break;
+ case OUTGOING_TRAFFIC:
+ if ( nextVisibleBeams == BOTH )
+ {
+ mIncomingPos = 1;
+ mPlotter->addBeam( mPlotterSettings.colorIncoming );
+ }
+ else if ( nextVisibleBeams == INCOMING_TRAFFIC )
+ {
+ mPlotter->removeBeam( mOutgoingPos );
+ mIncomingPos = 0;
+ mPlotter->addBeam( mPlotterSettings.colorIncoming );
+ }
+ else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
+ {
+ colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing );
+ }
+ else if ( nextVisibleBeams == NONE )
+ {
+ mPlotter->removeBeam( mOutgoingPos );
+ }
+ break;
+ case BOTH:
+ if ( nextVisibleBeams == BOTH )
+ {
+ colors[mIncomingPos] = ( mPlotterSettings.colorIncoming );
+ colors[mOutgoingPos] = ( mPlotterSettings.colorOutgoing );
+ }
+ else if ( nextVisibleBeams == OUTGOING_TRAFFIC )
+ {
+ mOutgoingPos = 0;
+ mPlotter->removeBeam( mIncomingPos );
+ }
+ else if ( nextVisibleBeams == INCOMING_TRAFFIC )
+ {
+ mIncomingPos = 0;
+ mPlotter->removeBeam( mOutgoingPos );
+ }
+ else if ( nextVisibleBeams == NONE )
+ {
+ mPlotter->removeBeam( 0 );
+ mPlotter->removeBeam( 0 );
+ }
+ break;
+ }
+ mVisibleBeams = nextVisibleBeams;
+ mPlotter->repaint();
+}
+
+void Interface::startStatistics()
+{
+ mStatistics = new InterfaceStatistics( this );
+ connect( &mMonitor, SIGNAL( incomingData( unsigned long ) ),
+ mStatistics, SLOT( addIncomingData( unsigned long ) ) );
+ connect( &mMonitor, SIGNAL( outgoingData( unsigned long ) ),
+ mStatistics, SLOT( addOutgoingData( unsigned long ) ) );
+ if ( mStatusDialog != 0 )
+ {
+ connect( mStatistics, SIGNAL( currentEntryChanged() ),
+ mStatusDialog, SLOT( statisticsChanged() ) );
+ mStatusDialog->statisticsChanged();
+ }
+
+ mStatistics->loadStatistics();
+}
+
+void Interface::stopStatistics()
+{
+ if ( mStatisticsDialog != 0 )
+ {
+ // this will close an open statistics dialog
+ delete mStatisticsDialog;
+ mStatisticsDialog = 0;
+ }
+
+ mStatistics->saveStatistics();
+
+ delete mStatistics;
+ mStatistics = 0;
+}
+
+// taken from ksystemtray.cpp
+void Interface::activateOrHide( QWidget* widget, bool onlyActivate )
+{
+ if ( !widget )
+ return;
+
+ KWin::WindowInfo info1 = KWin::windowInfo( widget->winId(), NET::XAWMState | NET::WMState );
+ // mapped = visible (but possibly obscured)
+ bool mapped = (info1.mappingState() == NET::Visible) && !info1.isMinimized();
+ // - not mapped -> show, raise, focus
+ // - mapped
+ // - obscured -> raise, focus
+ // - not obscured -> hide
+ if( !mapped )
+ {
+ KWin::setOnDesktop( widget->winId(), KWin::currentDesktop() );
+ widget->show();
+ widget->raise();
+ KWin::activateWindow( widget->winId() );
+ }
+ else
+ {
+ KWinModule module;
+ for( QValueList< WId >::ConstIterator it = module.stackingOrder().fromLast();
+ it != module.stackingOrder().end() && (*it) != widget->winId();
+ --it )
+ {
+ KWin::WindowInfo info2 = KWin::windowInfo( *it, (unsigned long)
+ NET::WMGeometry | NET::XAWMState | NET::WMState | NET::WMWindowType );
+ if( info2.mappingState() != NET::Visible )
+ continue; // not visible on current desktop -> ignore
+ if( !info2.geometry().intersects( widget->geometry()))
+ continue; // not obscuring the window -> ignore
+ if( !info1.hasState( NET::KeepAbove ) && info2.hasState( NET::KeepAbove ))
+ continue; // obscured by window kept above -> ignore
+ NET::WindowType type = info2.windowType( NET::NormalMask | NET::DesktopMask
+ | NET::DockMask | NET::ToolbarMask | NET::MenuMask | NET::DialogMask
+ | NET::OverrideMask | NET::TopMenuMask | NET::UtilityMask | NET::SplashMask );
+ if( type == NET::Dock || type == NET::TopMenu )
+ continue; // obscured by dock or topmenu -> ignore
+ widget->raise();
+ KWin::activateWindow( widget->winId());
+ return;
+ }
+ if ( !onlyActivate )
+ {
+ widget->hide();
+ }
+ }
+}
+
+#include "interface.moc"