diff --git a/src/knemod/CMakeLists.txt b/src/knemod/CMakeLists.txt index 331e8ed..e50d1b9 100644 --- a/src/knemod/CMakeLists.txt +++ b/src/knemod/CMakeLists.txt @@ -1,69 +1,68 @@ include_directories( ../common ) set( knemo_SRCS main.cpp global.cpp interface.cpp - interfaceicon.cpp interfaceplotterdialog.cpp interfacestatistics.cpp interfacestatisticsdialog.cpp interfacestatusdialog.cpp - interfacetray.cpp + trayicon.cpp knemodaemon.cpp plotterconfigdialog.cpp statisticsmodel.cpp statisticsview.cpp backends/backendbase.cpp ../common/data.cpp ../common/utils.cpp storage/sqlstorage.cpp storage/xmlstorage.cpp syncstats/externalstats.cpp syncstats/statsfactory.cpp syncstats/stats_vnstat.cpp ) if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) set( knemo_SRCS ${knemo_SRCS} backends/netlinkbackend.cpp ) if ( LIBIW_FOUND ) set( knemo_SRCS ${knemo_SRCS} backends/netlinkbackend_wireless.cpp ) endif( LIBIW_FOUND ) else ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) set( knemo_SRCS ${knemo_SRCS} backends/bsdbackend.cpp ) endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) ki18n_wrap_ui( knemo_SRCS interfacestatisticsdlg.ui interfacestatusdlg.ui plotterconfigdlg.ui ) add_executable( knemo ${knemo_SRCS} ) target_link_libraries( knemo PUBLIC Qt5::Sql KF5::KIOWidgets KF5::DBusAddons KF5::GlobalAccel KF5::KDELibs4Support KF5::Notifications KF5::Plasma KF5::SignalPlotter KF5::XmlGui KF5::WindowSystem KF5::I18n ${LIBNL_LIBRARIES} ${LIBIW_LIBRARIES} ) install( TARGETS knemo ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) install( FILES knemo.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR} ) install( PROGRAMS knemo.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) install( FILES knemo.desktop DESTINATION ${KDE_INSTALL_AUTOSTARTDIR} ) add_subdirectory( icons ) add_subdirectory( themes ) diff --git a/src/knemod/interface.cpp b/src/knemod/interface.cpp index 04fe627..b7ac205 100644 --- a/src/knemod/interface.cpp +++ b/src/knemod/interface.cpp @@ -1,450 +1,459 @@ /* This file is part of KNemo Copyright (C) 2004, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp 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 "interface.h" + #include #include #include #include #include #include #include "backends/backendbase.h" #include "global.h" #include "utils.h" -#include "interface.h" #include "interfaceplotterdialog.h" #include "interfacestatistics.h" #include "interfacestatusdialog.h" #include "interfacestatisticsdialog.h" +#include "trayicon.h" Interface::Interface( const QString &ifname, const BackendData* data ) : QObject(), mIfaceState( KNemoIface::UnknownState ), mPreviousIfaceState( KNemoIface::UnknownState ), mIfaceName( ifname ), mRealSec( 0.0 ), mUptime( 0 ), mUptimeString( QStringLiteral("00:00:00") ), mRxRate( 0 ), mTxRate( 0 ), - mIcon( this ), + mIcon( 0 ), mIfaceStatistics( 0 ), mStatusDialog( 0 ), mStatisticsDialog( 0 ), mPlotterDialog( 0 ), mBackendData( data ) { mPlotterDialog = new InterfacePlotterDialog( mIfaceName ); - - connect( &mIcon, SIGNAL( statisticsSelected() ), - this, SLOT( showStatisticsDialog() ) ); } Interface::~Interface() { delete mStatusDialog; delete mPlotterDialog; delete mStatisticsDialog; delete mIfaceStatistics; + delete mIcon; } void Interface::configChanged() { KSharedConfig::Ptr config = KSharedConfig::openConfig(); QString group( confg_interface ); group += mIfaceName; KConfigGroup interfaceGroup( config, group ); InterfaceSettings s; mSettings.iconTheme = interfaceGroup.readEntry( conf_iconTheme, s.iconTheme ); // If the theme is not configured, use a sensible default if (mSettings.iconTheme.isEmpty()) { if ( mBackendData->isWireless ) { mSettings.iconTheme = QLatin1String("wireless"); } else { mSettings.iconTheme = QLatin1String("network"); } } // Let's check that the theme is available QStringList themeNames; QList themes = findThemes(); foreach( KNemoTheme theme, themes ) themeNames << theme.internalName; themeNames << NETLOAD_THEME; // If that's not available, default to the text theme if ( !themeNames.contains( mSettings.iconTheme ) ) mSettings.iconTheme = TEXT_THEME; mSettings.barScale = interfaceGroup.readEntry( conf_barScale, s.barScale ); mSettings.maxRate = interfaceGroup.readEntry( conf_maxRate, s.maxRate )*1024; mSettings.minVisibleState = interfaceGroup.readEntry( conf_minVisibleState, s.minVisibleState ); mSettings.activateStatistics = interfaceGroup.readEntry( conf_activateStatistics, s.activateStatistics ); mSettings.trafficThreshold = clamp(interfaceGroup.readEntry( conf_trafficThreshold, s.trafficThreshold ), 0, 1000 ); mSettings.warnRules.clear(); int warnRuleCount = interfaceGroup.readEntry( conf_warnRules, 0 ); for ( int i = 0; i < warnRuleCount; ++i ) { group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_warnRule ).arg( mIfaceName ).arg( i ); if ( config->hasGroup( group ) ) { KConfigGroup warnGroup( config, group ); WarnRule warn; warn.periodUnits = clamp(warnGroup.readEntry( conf_warnPeriodUnits, warn.periodUnits ), KNemoStats::Hour, KNemoStats::Year ); warn.periodCount = clamp(warnGroup.readEntry( conf_warnPeriodCount, warn.periodUnits ), 1, 1000 ); warn.trafficType = clamp(warnGroup.readEntry( conf_warnTrafficType, warn.trafficType ), KNemoStats::Peak, KNemoStats::PeakOffpeak ); warn.trafficDirection = clamp(warnGroup.readEntry( conf_warnTrafficDirection, warn.trafficDirection ), KNemoStats::TrafficIn, KNemoStats::TrafficTotal ); warn.trafficUnits = clamp(warnGroup.readEntry( conf_warnTrafficUnits, warn.trafficUnits ), KNemoStats::UnitB, KNemoStats::UnitG ); warn.threshold = clamp(warnGroup.readEntry( conf_warnThreshold, warn.threshold ), 0.0, 9999.0 ); warn.customText = warnGroup.readEntry( conf_warnCustomText, warn.customText ).trimmed(); mSettings.warnRules << warn; } } mSettings.calendarSystem = static_cast(interfaceGroup.readEntry( conf_calendarSystem, static_cast(KLocale::QDateCalendar) )); mSettings.statsRules.clear(); int statsRuleCount = interfaceGroup.readEntry( conf_statsRules, 0 ); KCalendarSystem *testCal = KCalendarSystem::create( mSettings.calendarSystem ); for ( int i = 0; i < statsRuleCount; ++i ) { group = QString::fromLatin1( "%1%2 #%3" ).arg( confg_statsRule ).arg( mIfaceName ).arg( i ); if ( config->hasGroup( group ) ) { KConfigGroup statsGroup( config, group ); StatsRule rule; rule.startDate = statsGroup.readEntry( conf_statsStartDate, QDate() ); rule.periodUnits = clamp(statsGroup.readEntry( conf_statsPeriodUnits, rule.periodUnits ), KNemoStats::Day, KNemoStats::Year ); rule.periodCount = clamp(statsGroup.readEntry( conf_statsPeriodCount, rule.periodCount ), 1, 1000 ); rule.logOffpeak = statsGroup.readEntry( conf_logOffpeak,rule.logOffpeak ); rule.offpeakStartTime = QTime::fromString( statsGroup.readEntry( conf_offpeakStartTime, rule.offpeakStartTime.toString( Qt::ISODate ) ), Qt::ISODate ); rule.offpeakEndTime = QTime::fromString( statsGroup.readEntry( conf_offpeakEndTime, rule.offpeakEndTime.toString( Qt::ISODate ) ), Qt::ISODate ); rule.weekendIsOffpeak = statsGroup.readEntry( conf_weekendIsOffpeak, rule.weekendIsOffpeak ); rule.weekendDayStart = clamp(statsGroup.readEntry( conf_weekendDayStart, rule.weekendDayStart ), 1, testCal->daysInWeek( QDate::currentDate() ) ); rule.weekendDayEnd = clamp(statsGroup.readEntry( conf_weekendDayEnd, rule.weekendDayEnd ), 1, testCal->daysInWeek( QDate::currentDate() ) ); rule.weekendTimeStart = QTime::fromString( statsGroup.readEntry( conf_weekendTimeStart, rule.weekendTimeStart.toString( Qt::ISODate ) ), Qt::ISODate ); rule.weekendTimeEnd = QTime::fromString( statsGroup.readEntry( conf_weekendTimeEnd, rule.weekendTimeEnd.toString( Qt::ISODate ) ), Qt::ISODate ); if ( rule.isValid( testCal ) ) { mSettings.statsRules << rule; } } } - // This prevents needless regeneration of icon when first shown in tray - if ( mIfaceState == KNemoIface::UnknownState ) + if (mIcon) { - mIfaceState = mBackendData->status; - mPreviousIfaceState = mIfaceState; + mIcon->configChanged(); } - mIcon.configChanged(); if ( mIfaceStatistics ) { mIfaceStatistics->configChanged(); if ( !mSettings.activateStatistics ) stopStatistics(); } else if ( mSettings.activateStatistics ) { startStatistics(); } if ( mStatusDialog ) mStatusDialog->configChanged(); if ( mStatisticsDialog != 0 ) mStatisticsDialog->configChanged(); if ( mPlotterDialog ) mPlotterDialog->useBitrate( generalSettings->useBitrate ); } void Interface::processUpdate() { mPreviousIfaceState = mIfaceState; - unsigned int trafficThreshold = mSettings.trafficThreshold; mIfaceState = mBackendData->status; int units = 1; if ( generalSettings->useBitrate ) units = 8; mRxRate = mBackendData->incomingBytes * units / generalSettings->pollInterval; mTxRate = mBackendData->outgoingBytes * units / generalSettings->pollInterval; mRxRateStr = formattedRate( mRxRate, generalSettings->useBitrate ); mTxRateStr = formattedRate( mTxRate, generalSettings->useBitrate ); QString title = mIfaceName; if ( mIfaceState & KNemoIface::Connected ) { // the interface is connected, look for traffic - if ( ( mBackendData->rxPackets - mBackendData->prevRxPackets ) > trafficThreshold ) + if ( ( mBackendData->rxPackets - mBackendData->prevRxPackets ) > mSettings.trafficThreshold ) mIfaceState |= KNemoIface::RxTraffic; - if ( ( mBackendData->txPackets - mBackendData->prevTxPackets ) > trafficThreshold ) + if ( ( mBackendData->txPackets - mBackendData->prevTxPackets ) > mSettings.trafficThreshold ) mIfaceState |= KNemoIface::TxTraffic; if ( mIfaceStatistics ) { // We only check once an hour if we need to create a new stats entry. // However, the timer will be out of sync if we're resuming from suspend, // so we just check if we need to readjust when an interface becomes connected. if ( mPreviousIfaceState < KNemoIface::Connected ) mIfaceStatistics->checkValidEntry(); mIfaceStatistics->addRxBytes( mBackendData->incomingBytes ); mIfaceStatistics->addTxBytes( mBackendData->outgoingBytes ); } updateTime(); if ( mPreviousIfaceState < KNemoIface::Connected ) { QString connectedStr; if ( mBackendData->isWireless ) connectedStr = i18n( "%1 is connected to %2", title, mBackendData->essid ); else connectedStr = i18n( "%1 is connected", title ); if ( mPreviousIfaceState != KNemoIface::UnknownState ) KNotification::event( QLatin1String("connected"), connectedStr ); } } else if ( mIfaceState & KNemoIface::Available ) { if ( mPreviousIfaceState & KNemoIface::Connected ) { KNotification::event( QLatin1String("disconnected"), i18n( "%1 has disconnected", title ) ); if ( mBackendData->interfaceType == KNemoIface::PPP ) backend->clearTraffic( mIfaceName ); resetUptime(); } else if ( mPreviousIfaceState < KNemoIface::Available ) { if ( mPreviousIfaceState != KNemoIface::UnknownState ) KNotification::event( QLatin1String("available"), i18n( "%1 is available", title ) ); } } else if ( mIfaceState == KNemoIface::Unavailable && mPreviousIfaceState > KNemoIface::Unavailable ) { KNotification::event( QLatin1String("unavailable"), i18n( "%1 is unavailable", title ) ); backend->clearTraffic( mIfaceName ); resetUptime(); } if ( mPreviousIfaceState != mIfaceState ) - mIcon.updateTrayStatus(); + { + if ( mIcon && mIfaceState < mSettings.minVisibleState ) + { + delete mIcon; + mIcon = 0L; + } + else if ( !mIcon && mIfaceState >= mSettings.minVisibleState ) + { + mIcon = new TrayIcon( this, mIfaceName ); + } + } if ( mPlotterDialog ) mPlotterDialog->updatePlotter( mRxRate, mTxRate ); - mIcon.updateToolTip(); + if ( mIcon ) + { + mIcon->processUpdate(); + } if ( mStatusDialog ) mStatusDialog->updateDialog(); } void Interface::resetUptime() { mUptime = 0; mRealSec = 0.0; mUptimeString = QStringLiteral("00:00:00"); mRxRate = 0; mTxRate = 0; mRxRateStr = formattedRate( mRxRate, generalSettings->useBitrate ); mTxRateStr = formattedRate( mTxRate, generalSettings->useBitrate ); } -void Interface::showStatusDialog( bool fromContextMenu ) +void Interface::showStatusDialog( bool onlyActivate ) { // Toggle the status dialog. // First click will show the status dialog, second will hide it. if ( mStatusDialog == 0L ) { mStatusDialog = new InterfaceStatusDialog( this ); if ( mIfaceStatistics != 0 ) { connect( mIfaceStatistics, SIGNAL( currentEntryChanged() ), mStatusDialog, SLOT( statisticsChanged() ) ); mStatusDialog->statisticsChanged(); } } - activateOrHide( mStatusDialog, fromContextMenu ); + activateOrHide( mStatusDialog, onlyActivate ); } -void Interface::showSignalPlotter( bool fromContextMenu ) +void Interface::showSignalPlotter( bool onlyActivate ) { // Toggle the signal plotter. - activateOrHide( mPlotterDialog, fromContextMenu ); + activateOrHide( mPlotterDialog, onlyActivate ); } void Interface::showStatisticsDialog() { if ( mStatisticsDialog == 0 ) { mStatisticsDialog = new InterfaceStatisticsDialog( this ); if ( mIfaceStatistics == 0 ) { // should never happen but you never know... startStatistics(); } connect( mStatisticsDialog, SIGNAL( clearStatistics() ), mIfaceStatistics, SLOT( clearStatistics() ) ); } mStatisticsDialog->show(); } void Interface::updateTime() { mRealSec += generalSettings->pollInterval; if ( mRealSec < 1.0 ) return; mUptime += trunc( mRealSec ); mRealSec -= trunc( mRealSec ); time_t updays = mUptime / 86400; mUptimeString = i18np("1 day, ","%1 days, ",updays); mUptime -= 86400 * updays; // we only want the seconds of today int hrs = mUptime / 3600; int mins = ( mUptime - hrs * 3600 ) / 60; int secs = mUptime - hrs * 3600 - mins * 60; QString time; time.sprintf( "%02d:%02d:%02d", hrs, mins, secs ); mUptimeString += time; } void Interface::startStatistics() { mIfaceStatistics = new InterfaceStatistics( this ); connect( mIfaceStatistics, SIGNAL( warnTraffic( QString, quint64, quint64 ) ), this, SLOT( warnTraffic( QString, quint64, quint64 ) ) ); if ( mStatusDialog != 0 ) { connect( mIfaceStatistics, SIGNAL( currentEntryChanged() ), mStatusDialog, SLOT( statisticsChanged() ) ); mStatusDialog->statisticsChanged(); } } void Interface::stopStatistics() { // this will close an open statistics dialog delete mStatisticsDialog; mStatisticsDialog = 0; delete mIfaceStatistics; mIfaceStatistics = 0; } void Interface::warnTraffic( QString warnText, quint64 threshold, quint64 current ) { if ( !warnText.isEmpty() ) { warnText = warnText.replace( QRegExp(QLatin1String("%i")), mIfaceName ); warnText = warnText.replace( QRegExp(QLatin1String("%t")), KIO::convertSize( threshold ) ); warnText = warnText.replace( QRegExp(QLatin1String("%c")), KIO::convertSize( threshold ) ); } else { warnText = i18n( "" "
%1:Exceeded traffic limit of %2\n" "(currently %3)
", mIfaceName, KIO::convertSize( threshold ), KIO::convertSize( current ) ); } KNotification::event( QLatin1String("exceededTraffic"), warnText ); } void Interface::toggleSignalPlotter( bool show ) { if ( !mPlotterDialog ) return; if ( show ) mPlotterDialog->show(); else mPlotterDialog->hide(); } bool Interface::plotterVisible() { if ( !mPlotterDialog || !mPlotterDialog->isVisible() ) return false; return true; } // taken from ksystemtray.cpp void Interface::activateOrHide( QWidget* widget, bool onlyActivate ) { if ( !widget ) return; KWindowInfo info1 = KWindowInfo( 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 ) { KWindowSystem::setOnDesktop( widget->winId(), KWindowSystem::currentDesktop() ); widget->show(); widget->raise(); } else { QListIterator< WId > it (KWindowSystem::stackingOrder()); it.toBack(); while( it.hasPrevious() ) { WId id = it.previous(); if( id == widget->winId() ) break; KWindowInfo info2 = KWindowInfo( id, 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(); KWindowSystem::activateWindow( widget->winId()); return; } if ( !onlyActivate ) { widget->hide(); } } } #include "moc_interface.cpp" diff --git a/src/knemod/interface.h b/src/knemod/interface.h index a7bb064..60ce62a 100644 --- a/src/knemod/interface.h +++ b/src/knemod/interface.h @@ -1,194 +1,194 @@ /* This file is part of KNemo Copyright (C) 2004, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp 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. */ #ifndef INTERFACE_H #define INTERFACE_H #include -#include "interfaceicon.h" #include "data.h" class InterfacePlotterDialog; class InterfaceStatistics; class InterfaceStatusDialog; class InterfaceStatisticsDialog; +class TrayIcon; /** * This class is the central place for all things that belong to an * interface. It stores some information and knows about the interface * data, icon, monitor and settings. * * @short Central class for every interface * @author Percy Leonhardt */ class Interface : public QObject { Q_OBJECT public: /** * Default Constructor */ Interface(const QString& ifname, const BackendData * const ); /** * Default Destructor */ virtual ~Interface(); int ifaceState() { return mIfaceState; } int previousIfaceState() { return mPreviousIfaceState; } QString uptimeString() { return mUptimeString; } const QString& ifaceName() const { return mIfaceName; } const BackendData* backendData() const { return mBackendData; } InterfaceSettings& settings() { return mSettings; } InterfaceStatistics* ifaceStatistics() { return mIfaceStatistics; } unsigned long rxRate() { return mRxRate; } unsigned long txRate() { return mTxRate; } QString rxRateStr() { return mRxRateStr; } QString txRateStr() { return mTxRateStr; } bool plotterVisible(); /** * Called from reparseConfiguration() when the user changed * the settings. */ void configChanged(); public Q_SLOTS: /** * Called when the backend emits the updateComplete signal. * This looks for changes in interface data or state. */ void processUpdate(); /* * Called when the user left-clicks on the tray icon * Toggles the status dialog by showing it on the first click and * hiding it on the second click. */ - void showStatusDialog( bool fromContextMenu ); + void showStatusDialog( bool onlyActivate = true ); /* * Called when the user middle-clicks on the tray icon * Toggles the signal plotter that displays the incoming and * outgoing traffic. */ - void showSignalPlotter( bool fromContextMenu ); + void showSignalPlotter( bool onlyActivate = true ); void toggleSignalPlotter( bool show ); /* * Called when the user selects the appropriate entry in the context menu. */ void showStatisticsDialog(); private Q_SLOTS: /** * Emit a notification when traffic exceeds a threshold */ void warnTraffic( QString text, quint64 threshold, quint64 current ); private: /** * Start the statistics and load previously saved ones */ void startStatistics(); /** * Store the statistics and stop collecting any further data */ void stopStatistics(); /** * The following function is taken from ksystemtray.cpp for * correct show, raise, focus and hide of status dialog and * signal plotter. */ void activateOrHide( QWidget* widget, bool onlyActivate = false ); void updateTime(); void resetUptime(); int mIfaceState; int mPreviousIfaceState; QString mIfaceName; qreal mRealSec; time_t mUptime; QString mUptimeString; unsigned long mRxRate; unsigned long mTxRate; QString mRxRateStr; QString mTxRateStr; - InterfaceIcon mIcon; + TrayIcon *mIcon; InterfaceSettings mSettings; InterfaceStatistics* mIfaceStatistics; InterfaceStatusDialog* mStatusDialog; InterfaceStatisticsDialog* mStatisticsDialog; InterfacePlotterDialog* mPlotterDialog; const BackendData* mBackendData; }; #endif // INTERFACE_H diff --git a/src/knemod/interfaceicon.cpp b/src/knemod/interfaceicon.cpp deleted file mode 100644 index e4157c5..0000000 --- a/src/knemod/interfaceicon.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* This file is part of KNemo - Copyright (C) 2004, 2005 Percy Leonhardt - Copyright (C) 2009, 2010 John Stamp - - 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 -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "global.h" -#include "utils.h" -#include "interface.h" -#include "knemodaemon.h" -#include "interfaceicon.h" -#include "interfacetray.h" - -#define SHRINK_MAX 0.75 -#define HISTSIZE_STORE 0.5 - -InterfaceIcon::InterfaceIcon( Interface* interface ) - : QObject(), - mInterface( interface ), - mTray( 0L ), - m_rxPrevBarHeight( 0 ), - m_txPrevBarHeight( 0 ) -{ - statusAction = new QAction( i18n( "Show &Status Dialog" ), this ); - plotterAction = new QAction( QIcon::fromTheme( QLatin1String("utilities-system-monitor") ), - i18n( "Show &Traffic Plotter" ), this ); - statisticsAction = new QAction( QIcon::fromTheme( QLatin1String("view-statistics") ), - i18n( "Show St&atistics" ), this ); - configAction = new QAction( QIcon::fromTheme( QLatin1String("configure") ), - i18n( "&Configure KNemo..." ), this ); - - connect( statusAction, SIGNAL( triggered() ), - this, SLOT( showStatus() ) ); - connect( plotterAction, SIGNAL( triggered() ), - this, SLOT( showGraph() ) ); - connect( statisticsAction, SIGNAL( triggered() ), - this, SLOT( showStatistics() ) ); - connect( configAction, SIGNAL( triggered() ), - this, SLOT( showConfigDialog() ) ); -} - -InterfaceIcon::~InterfaceIcon() -{ - delete mTray; -} - -void InterfaceIcon::configChanged() -{ - histSize = HISTSIZE_STORE/generalSettings->pollInterval; - if ( histSize < 2 ) - histSize = 3; - - for ( int i=0; i < histSize; i++ ) - { - m_rxHist.append( 0 ); - m_txHist.append( 0 ); - } - - m_maxRate = mInterface->settings().maxRate; - - updateTrayStatus(); - - if ( mTray != 0L ) - { - updateMenu(); - if ( mInterface->settings().iconTheme == TEXT_THEME ) - updateTextIcon( true ); - else if ( mInterface->settings().iconTheme == NETLOAD_THEME ) - updateBarIcon( true ); - } -} - -void InterfaceIcon::updateIconImage( int status ) -{ - if ( mTray == 0L || mInterface->settings().iconTheme == TEXT_THEME ) - return; - - QString iconName; - if ( mInterface->settings().iconTheme == SYSTEM_THEME ) - iconName = QStringLiteral("network-"); - else - iconName = QLatin1String("knemo-") + mInterface->settings().iconTheme + QLatin1Char('-'); - - // Now set the correct icon depending on the status of the interface. - if ( ( status & KNemoIface::RxTraffic ) && - ( status & KNemoIface::TxTraffic ) ) - { - iconName += ICON_RX_TX; - } - else if ( status & KNemoIface::RxTraffic ) - { - iconName += ICON_RX; - } - else if ( status & KNemoIface::TxTraffic ) - { - iconName += ICON_TX; - } - else if ( status & KNemoIface::Connected ) - { - iconName += ICON_IDLE; - } - else if ( status & KNemoIface::Available ) - { - iconName += ICON_OFFLINE; - } - else - { - iconName += ICON_ERROR; - } - mTray->setIconByName( iconName ); -} - -QList InterfaceIcon::barLevels( QList& rxHist, QList& txHist ) -{ - // get the average rate of the two, then calculate based on the higher - // return ratios for both. - unsigned long histTotal = 0; - foreach( unsigned long j, rxHist ) - { - histTotal += j; - } - unsigned long rxAvgRate = histTotal / histSize; - - histTotal = 0; - foreach( unsigned long j, txHist ) - { - histTotal += j; - } - unsigned long txAvgRate = histTotal / histSize; - - // Adjust the scale of the bar icons when we don't have a fixed ceiling. - if ( !mInterface->settings().barScale ) - { - QListrxSortedMax( rxHist ); - QListtxSortedMax( txHist ); - qSort( rxSortedMax ); - qSort( txSortedMax ); - int multiplier = 1024; - if ( generalSettings->useBitrate ) - multiplier = 1000; - if( qMax(rxAvgRate, txAvgRate) > m_maxRate ) - { - m_maxRate = qMax(rxAvgRate, txAvgRate); - } - else if( qMax( rxSortedMax.last(), txSortedMax.last() ) < m_maxRate * SHRINK_MAX - && m_maxRate * SHRINK_MAX >= multiplier ) - { - m_maxRate *= SHRINK_MAX; - } - } - - QList levels; - qreal rxLevel = static_cast(rxAvgRate)/m_maxRate; - if ( rxLevel > 1.0 ) - rxLevel = 1.0; - levels.append(rxLevel); - qreal txLevel = static_cast(txAvgRate)/m_maxRate; - if ( txLevel > 1.0 ) - txLevel = 1.0; - levels.append(txLevel); - return levels; -} - -bool InterfaceIcon::conStatusChanged() -{ - return !( mInterface->backendData()->status & - mInterface->backendData()->prevStatus & - (KNemoIface::Connected | KNemoIface::Available | KNemoIface::Unavailable) ); -} - -void InterfaceIcon::updateBarIcon( bool doUpdate ) -{ - // Has color changed? - if ( conStatusChanged() ) - { - doUpdate = true; - } - - QSize iconSize = getIconSize(); - - // If either of the bar heights have changed since the last time, we have - // to do an update. - QList levels = barLevels( m_rxHist, m_txHist ); - int barHeight = static_cast(round(iconSize.height() * levels.at(0)) + 0.5); - if ( barHeight != m_rxPrevBarHeight ) - { - doUpdate = true; - m_rxPrevBarHeight = barHeight; - } - barHeight = static_cast(round(iconSize.height() * levels.at(1)) + 0.5); - if ( barHeight != m_txPrevBarHeight ) - { - doUpdate = true; - m_txPrevBarHeight = barHeight; - } - - if ( !doUpdate ) - return; - - const BackendData * data = mInterface->backendData(); - - mTray->setIconByPixmap( genBarIcon( levels.at(0), levels.at(1), data->status ) ); - QPixmapCache::clear(); -} - -QString InterfaceIcon::compactTrayText(unsigned long data ) -{ - QString dataString; - // Space is tight, so no space between number and units, and the complete - // string should be no more than 4 chars. - /* Visually confusing to display bytes - if ( bytes < 922 ) // 922B = 0.9K - byteString = i18n( "%1B", bytes ); - */ - double multiplier = 1024; - if ( generalSettings->useBitrate ) - multiplier = 1000; - - int precision = 0; - if ( data < multiplier*9.95 ) // < 9.95K - { - precision = 1; - } - if ( data < multiplier*999.5 ) // < 999.5K - { - if ( generalSettings->useBitrate ) - dataString = i18n( "%1k", QString::number( data/multiplier, 'f', precision ) ); - else - dataString = i18n( "%1K", QString::number( data/multiplier, 'f', precision ) ); - return dataString; - } - - if ( data < pow(multiplier, 2)*9.95 ) // < 9.95M - precision = 1; - if ( data < pow(multiplier, 2)*999.5 ) // < 999.5M - { - dataString = i18n( "%1M", QString::number( data/pow(multiplier, 2), 'f', precision ) ); - return dataString; - } - - if ( data < pow(multiplier, 3)*9.95 ) // < 9.95G - precision = 1; - // xgettext: no-c-format - dataString = i18n( "%1G", QString::number( data/pow(multiplier, 3), 'f', precision) ); - return dataString; -} - -void InterfaceIcon::updateTextIcon( bool doUpdate ) -{ - // Has color changed? - if ( conStatusChanged() ) - { - doUpdate = true; - } - - // Has text changed? - QString byteText = compactTrayText( mInterface->rxRate() ); - if ( byteText != m_rxText ) - { - doUpdate = true; - m_rxText = byteText; - } - byteText = compactTrayText( mInterface->txRate() ); - if ( byteText != m_txText ) - { - doUpdate = true; - m_txText = byteText; - } - - if ( !doUpdate ) - return; - - mTray->setIconByPixmap( genTextIcon(m_rxText, m_txText, plasmaTheme->smallestFont(), mInterface->backendData()->status) ); - QPixmapCache::clear(); -} - -void InterfaceIcon::updateToolTip() -{ - if ( mTray == 0L ) - return; - m_rxHist.prepend( mInterface->rxRate() ); - m_txHist.prepend( mInterface->txRate() ); - while ( m_rxHist.count() > histSize ) - { - m_rxHist.removeLast(); - m_txHist.removeLast(); - } - - - if ( mInterface->settings().iconTheme == TEXT_THEME ) - updateTextIcon(); - else if ( mInterface->settings().iconTheme == NETLOAD_THEME ) - updateBarIcon(); - mTray->updateToolTip(); -} - -void InterfaceIcon::updateMenu() -{ - QMenu* menu = mTray->contextMenu(); - - InterfaceSettings& settings = mInterface->settings(); - - if ( settings.activateStatistics ) - menu->insertAction( configAction, statisticsAction ); - else - menu->removeAction( statisticsAction ); -} - -void InterfaceIcon::updateTrayStatus() -{ - const QString ifaceName( mInterface->ifaceName() ); - const BackendData * data = mInterface->backendData(); - int currentStatus = data->status; - int minVisibleState = mInterface->settings().minVisibleState; - - QString title = ifaceName; - - if ( mTray != 0L && currentStatus < minVisibleState ) - { - delete mTray; - mTray = 0L; - } - else if ( mTray == 0L && currentStatus >= minVisibleState ) - { - mTray = new InterfaceTray( mInterface, ifaceName ); - QMenu* menu = mTray->contextMenu(); - - menu->removeAction( menu->actions().at( 0 ) ); - // FIXME: title for QMenu? - //menu->addTitle( QIcon::fromTheme( QLatin1String("knemo") ), i18n( "KNemo - %1", title ) ); - menu->addAction( statusAction ); - menu->addAction( plotterAction ); - menu->addAction( configAction ); - KHelpMenu* helpMenu( new KHelpMenu( menu, KAboutData::applicationData(), false ) ); - menu->addMenu( helpMenu->menu() )->setIcon( QIcon::fromTheme( QLatin1String("help-contents") ) ); - - if ( mInterface->settings().iconTheme == TEXT_THEME ) - updateTextIcon(); - else if ( mInterface->settings().iconTheme == NETLOAD_THEME ) - updateBarIcon(); - else - updateIconImage( mInterface->ifaceState() ); - updateMenu(); - } - else if ( mTray != 0L ) - { - if ( mInterface->settings().iconTheme != TEXT_THEME && - mInterface->settings().iconTheme != NETLOAD_THEME ) - updateIconImage( mInterface->ifaceState() ); - } -} - -void InterfaceIcon::showConfigDialog() -{ - KNemoDaemon::sSelectedInterface = mInterface->ifaceName(); - - KProcess process; - process << QLatin1String("kcmshell5") << QLatin1String("kcm_knemo"); - process.startDetached(); -} - -void InterfaceIcon::showStatistics() -{ - emit statisticsSelected(); -} - -void InterfaceIcon::showStatus() -{ - mInterface->showStatusDialog( true ); -} - -void InterfaceIcon::showGraph() -{ - mInterface->showSignalPlotter( true ); -} - -#include "moc_interfaceicon.cpp" diff --git a/src/knemod/interfaceicon.h b/src/knemod/interfaceicon.h deleted file mode 100644 index 1df86d7..0000000 --- a/src/knemod/interfaceicon.h +++ /dev/null @@ -1,123 +0,0 @@ -/* This file is part of KNemo - Copyright (C) 2004, 2005 Percy Leonhardt - Copyright (C) 2009, 2010 John Stamp - - 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. -*/ - -#ifndef INTERFACEICON_H -#define INTERFACEICON_H - -class Interface; -class InterfaceTray; -class KActionCollection; -class QAction; - -/** - * This is the logical representation of the systemtray icon. It handles - * creation and deletion of the real icon, setting the tooltip, setting - * the correct icon image and displaying of the settings dialog. - * - * @short Logical representation of the systemtray icon - * @author Percy Leonhardt - */ - -class InterfaceIcon : public QObject -{ - Q_OBJECT -public: - /** - * Default Constructor - */ - InterfaceIcon( Interface* interface ); - - /** - * Default Destructor - */ - virtual ~InterfaceIcon(); - -Q_SIGNALS: - void statisticsSelected(); - -public Q_SLOTS: - /* - * Creates or deletes the tray icon - */ - void updateTrayStatus(); - - /* - * Update tool tip text - */ - void updateToolTip(); - - /* - * Fill the context menu with entries if the user configured - * start and stop command - */ - void updateMenu(); - - void configChanged(); - -private Q_SLOTS: - /* - * Called when the user selects 'Configure KNemo' from the context menu - */ - void showConfigDialog(); - - /* - * Returns a string with a compact transfer rate - * This should not be more than 4 chars, including the units - */ - QString compactTrayText( unsigned long ); - - void showStatus(); - void showGraph(); - void showStatistics(); - -private: - /* - * Changes the icon displayed in the tray - */ - void updateIconImage( int status ); - - bool conStatusChanged(); - QList barLevels( QList& rxHist, QList& txHist ); - void updateBarIcon( bool doUpdate = false ); - void updateTextIcon( bool doUpdate = false ); - // the interface this icon belongs to - Interface* mInterface; - // the real tray icon - InterfaceTray* mTray; - KActionCollection* commandActions; - QAction* statusAction; - QAction* plotterAction; - QAction* statisticsAction; - QAction* configAction; - QString m_rxText; - QString m_txText; - int iconWidth; - int histSize; - int m_rxPrevBarHeight; - int m_txPrevBarHeight; - int barWidth; - int leftMargin; - int midMargin; - QListm_rxHist; - QListm_txHist; - unsigned int m_maxRate; -}; - -#endif // INTERFACEICON_H diff --git a/src/knemod/interfacetray.cpp b/src/knemod/interfacetray.cpp deleted file mode 100644 index 7d04505..0000000 --- a/src/knemod/interfacetray.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* This file is part of KNemo - Copyright (C) 2004, 2005 Percy Leonhardt - Copyright (C) 2009, 2010 John Stamp - - 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 "global.h" -#include "interfacetray.h" - -#ifdef __linux__ -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -InterfaceTray::InterfaceTray( Interface* interface, const QString &id, QWidget* parent ) : - KStatusNotifierItem( id, parent ) -{ - mInterface = interface; - setToolTipIconByName( QLatin1String("knemo") ); - setCategory(Hardware); - setStatus(Active); - connect(this, SIGNAL(secondaryActivateRequested(QPoint)), this, SLOT(togglePlotter())); - setupMappings(); - QAction *quitAction = new QAction(this); - quitAction->setText(KStatusNotifierItem::tr("Quit")); - quitAction->setIcon(QIcon::fromTheme(QLatin1String("application-exit"))); - QObject::connect(quitAction, SIGNAL(triggered()), this, SLOT(slotQuit())); - // Replace the standard quit action - addAction(QLatin1String("quit"), quitAction); -} - -InterfaceTray::~InterfaceTray() -{ -} - -void InterfaceTray::updateToolTip() -{ - QString currentTip; - QString title = i18n( "KNemo - %1", mInterface->ifaceName() ); - if ( toolTipTitle() != title ) - setToolTipTitle( title ); - currentTip = toolTipData(); - if ( currentTip != toolTipSubTitle() ) - setToolTipSubTitle( currentTip ); -} - -void InterfaceTray::slotQuit() -{ - int autoStart = KMessageBox::questionYesNoCancel(0, i18n("Should KNemo start automatically when you login?"), - i18n("Automatically Start KNemo?"), KGuiItem(i18n("Start")), - KGuiItem(i18n("Do Not Start")), KStandardGuiItem::cancel(), QLatin1String("StartAutomatically")); - - KSharedConfig::Ptr config = KSharedConfig::openConfig(); - KConfigGroup generalGroup( config, confg_general ); - if ( autoStart == KMessageBox::Yes ) { - generalGroup.writeEntry( conf_autoStart, true ); - } else if ( autoStart == KMessageBox::No) { - generalGroup.writeEntry( conf_autoStart, false ); - } else // cancel chosen; don't quit - return; - config->sync(); - - qApp->quit(); -} - -void InterfaceTray::activate(const QPoint&) -{ - mInterface->showStatusDialog( false ); -} - -void InterfaceTray::togglePlotter() -{ - mInterface->showSignalPlotter( false ); -} - -QString InterfaceTray::formatTip( const QString& field, const QString& data, bool insertBreak ) -{ - QString ltip; - if (insertBreak) - ltip = QLatin1String("
"); - return ltip += i18nc( "field: value", "%1: %2", field, data ); -} - -QString InterfaceTray::toolTipData() -{ - QString tipData; - QString tipVal; - int toolTipContent = generalSettings->toolTipContent; - const BackendData * data = mInterface->backendData(); - if ( !data ) - return QString(); - - tipData = QLatin1String(""); - tipVal = QLatin1String(""); - - if ( toolTipContent & INTERFACE ) - tipData = formatTip( i18n( "Interface" ), mInterface->ifaceName(), !tipData.isEmpty() ); - - if ( toolTipContent & STATUS ) - { - if ( data->status & KNemoIface::Connected ) - tipVal = i18n( "Connected" ); - else if ( data->status & KNemoIface::Up ) - tipVal = i18n( "Disconnected" ); - else if ( data->status & KNemoIface::Available ) - tipVal += i18n( "Down" ); - else - tipVal += i18n( "Unavailable" ); - tipData += formatTip( i18n( "Status" ), tipVal, !tipData.isEmpty() ); - } - - if ( data->status & KNemoIface::Connected && - toolTipContent & UPTIME ) - { - tipData += formatTip( i18n( "Connection time"), mInterface->uptimeString(), !tipData.isEmpty() ); - } - - if ( data->status & KNemoIface::Up ) - { - QStringList keys = data->addrData.keys(); - QString ip4Tip; - QString ip6Tip; - foreach ( QString key, keys ) - { - AddrData addrData = data->addrData.value( key ); - - if ( addrData.afType == AF_INET ) - { - if ( toolTipContent & IP_ADDRESS ) - ip4Tip += formatTip( i18n( "IPv4 Address"), key, !tipData.isEmpty() ); - if ( toolTipContent & SCOPE ) - ip4Tip += formatTip( i18n( "Scope & Flags"), mScope.value( addrData.scope ) + addrData.ipv6Flags, !tipData.isEmpty() ); - if ( toolTipContent & BCAST_ADDRESS && !addrData.hasPeer ) - ip4Tip += formatTip( i18n( "Broadcast Address"), addrData.broadcastAddress, !tipData.isEmpty() ); - else if ( toolTipContent & PTP_ADDRESS && addrData.hasPeer ) - ip4Tip += formatTip( i18n( "PtP Address"), addrData.broadcastAddress, !tipData.isEmpty() ); - } - else - { - if ( toolTipContent & IP_ADDRESS ) - ip6Tip += formatTip( i18n( "IPv6 Address"), key, !tipData.isEmpty() ); - if ( toolTipContent & SCOPE ) - ip4Tip += formatTip( i18n( "Scope & Flags"), mScope.value( addrData.scope ), !tipData.isEmpty() ); - if ( toolTipContent & PTP_ADDRESS && addrData.hasPeer ) - ip4Tip += formatTip( i18n( "PtP Address"), addrData.broadcastAddress, !tipData.isEmpty() ); - } - } - tipData += ip4Tip + ip6Tip; - - if ( KNemoIface::Ethernet == data->interfaceType ) - { - if ( toolTipContent & GATEWAY ) - { - if ( !data->ip4DefaultGateway.isEmpty() ) - tipData += formatTip( i18n( "IPv4 Default Gateway"), data->ip4DefaultGateway, !tipData.isEmpty() ); - if ( !data->ip6DefaultGateway.isEmpty() ) - tipData += formatTip( i18n( "IPv6 Default Gateway"), data->ip6DefaultGateway, !tipData.isEmpty() ); - } - } - } - - if ( data->status & KNemoIface::Available ) - { - if ( toolTipContent & HW_ADDRESS ) - tipData += formatTip( i18n( "MAC Address"), data->hwAddress, !tipData.isEmpty() ); - if ( toolTipContent & RX_PACKETS ) - tipData += formatTip( i18n( "Packets Received"), QString::number( data->rxPackets ), !tipData.isEmpty() ); - if ( toolTipContent & TX_PACKETS ) - tipData += formatTip( i18n( "Packets Sent"), QString::number( data->txPackets ), !tipData.isEmpty() ); - if ( toolTipContent & RX_BYTES ) - tipData += formatTip( i18n( "Bytes Received"), data->rxString, !tipData.isEmpty() ); - if ( toolTipContent & TX_BYTES ) - tipData += formatTip( i18n( "Bytes Sent"), data->txString, !tipData.isEmpty() ); - } - - if ( data->status & KNemoIface::Connected ) - { - if ( toolTipContent & DOWNLOAD_SPEED ) - tipData += formatTip( i18n( "Download Speed"), mInterface->rxRateStr(), !tipData.isEmpty() ); - if ( toolTipContent & UPLOAD_SPEED ) - tipData += formatTip( i18n( "Upload Speed"), mInterface->txRateStr(), !tipData.isEmpty() ); - } - - if ( data->status & KNemoIface::Connected && data->isWireless ) - { - if ( toolTipContent & ESSID ) - tipData += formatTip( i18n( "ESSID"), data->essid, !tipData.isEmpty() ); - if ( toolTipContent & MODE ) - tipData += formatTip( i18n( "Mode"), data->mode, !tipData.isEmpty() ); - if ( toolTipContent & FREQUENCY ) - tipData += formatTip( i18n( "Frequency"), data->frequency, !tipData.isEmpty() ); - if ( toolTipContent & BIT_RATE ) - tipData += formatTip( i18n( "Bit Rate"), data->bitRate, !tipData.isEmpty() ); - if ( toolTipContent & ACCESS_POINT ) - tipData += formatTip( i18n( "Access Point"), data->accessPoint, !tipData.isEmpty() ); - if ( toolTipContent & LINK_QUALITY ) - tipData += formatTip( i18n( "Link Quality"), data->linkQuality, !tipData.isEmpty() ); -#ifdef __linux__ - if ( toolTipContent & NICK_NAME ) - tipData += formatTip( i18n( "Nickname"), data->nickName, !tipData.isEmpty() ); -#endif - if ( toolTipContent & ENCRYPTION ) - { - if ( data->isEncrypted == true ) - { - tipVal = i18n( "active" ); - } - else - { - tipVal = i18n( "off" ); - } - tipData += formatTip( i18n( "Encryption"), tipVal, !tipData.isEmpty() ); - } - } - return tipData; -} - -void InterfaceTray::setupMappings() -{ - // Cannot make this data static as the i18n macro doesn't seem - // to work when called to early i.e. before setting the catalogue. - mScope.insert( RT_SCOPE_NOWHERE, i18nc( "ipv6 address scope", "none" ) ); - mScope.insert( RT_SCOPE_HOST, i18nc( "ipv6 address scope", "host" ) ); - mScope.insert( RT_SCOPE_LINK, i18nc( "ipv6 address scope", "link" ) ); - mScope.insert( RT_SCOPE_SITE, i18nc( "ipv6 address scope", "site" ) ); - mScope.insert( RT_SCOPE_UNIVERSE, i18nc( "ipv6 address scope", "global" ) ); -} - -#include "moc_interfacetray.cpp" diff --git a/src/knemod/knemodaemon.cpp b/src/knemod/knemodaemon.cpp index e6259dc..ea4789e 100644 --- a/src/knemod/knemodaemon.cpp +++ b/src/knemod/knemodaemon.cpp @@ -1,213 +1,213 @@ /* This file is part of KNemo Copyright (C) 2004, 2006 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp 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 #include #include #include #include #include #include #include #include #include #include "global.h" #include "knemodaemon.h" #include "interface.h" #include "backends/backendfactory.h" #include "utils.h" QString KNemoDaemon::sSelectedInterface = QString::null; BackendBase *backend = NULL; GeneralSettings *generalSettings = NULL; Plasma::Theme *plasmaTheme = NULL; KNemoDaemon::KNemoDaemon() : QObject() { migrateKde4Conf(); generalSettings = new GeneralSettings(); plasmaTheme = new Plasma::Theme( this ); backend = BackendFactory::backend(); QDBusConnection::sessionBus().registerObject(QLatin1String("/knemo"), this, QDBusConnection::ExportScriptableSlots); mPollTimer = new QTimer(); connect( mPollTimer, SIGNAL( timeout() ), this, SLOT( updateInterfaces() ) ); KActionCollection* ac = new KActionCollection( this ); QAction* action = new QAction( i18n( "Toggle Traffic Plotters" ), this ); ac->addAction( QLatin1String("toggleTrafficPlotters"), action ); connect( action, SIGNAL( triggered() ), SLOT( togglePlotters() ) ); KGlobalAccel::setGlobalShortcut( action, QKeySequence() ); readConfig(); } KNemoDaemon::~KNemoDaemon() { mPollTimer->stop(); delete mPollTimer; foreach ( QString key, mInterfaceHash.keys() ) { Interface *interface = mInterfaceHash.take( key ); delete interface; } delete generalSettings; } void KNemoDaemon::readConfig() { mPollTimer->stop(); KSharedConfig::Ptr config = KSharedConfig::openConfig(); // For when reparseConfiguration() is called config->reparseConfiguration(); // General GeneralSettings g; KConfigGroup generalGroup( config, confg_general ); generalSettings->pollInterval = clamp(generalGroup.readEntry( conf_pollInterval, g.pollInterval ), 0.1, 2.0 ); generalSettings->pollInterval = validatePoll( generalSettings->pollInterval ); generalSettings->useBitrate = generalGroup.readEntry( conf_useBitrate, g.useBitrate ); generalSettings->saveInterval = clamp(generalGroup.readEntry( conf_saveInterval, g.saveInterval ), 0, 300 ); generalSettings->statisticsDir = g.statisticsDir; generalSettings->toolTipContent = generalGroup.readEntry( conf_toolTipContent, g.toolTipContent ); QStringList interfaceList = generalGroup.readEntry( conf_interfaces, QStringList() ); // Remove interfaces that are no longer monitored foreach ( QString key, mInterfaceHash.keys() ) { if ( !interfaceList.contains( key ) ) { Interface *interface = mInterfaceHash.take( key ); delete interface; backend->removeIface( key ); // If knemo is running while config removes an interface to monitor, // it will keep the interface and plotter groups. Delete them here. KConfigGroup interfaceGroup( config, QString( confg_interface + key ) ); KConfigGroup plotterGroup( config, QString( confg_plotter + key ) ); interfaceGroup.deleteGroup(); plotterGroup.deleteGroup(); config->sync(); } } // If an interface has the default route, add it even if it's not // explicitly configured. It will just use the default settings. // This should minimize user confusion. QString ifaceName = backend->defaultRouteIface( AF_INET ); if ( ifaceName.isEmpty() ) ifaceName = backend->defaultRouteIface( AF_INET6 ); - if ( !ifaceName.isEmpty() ) + if ( !ifaceName.isEmpty() && !interfaceList.contains( ifaceName ) ) { interfaceList << ifaceName; } // Add/update those that do need to be monitored QStringList newIfaces; foreach ( QString key, interfaceList ) { if ( !mInterfaceHash.contains( key ) ) { const BackendData * data = backend->addIface( key ); Interface *iface = new Interface( key, data ); mInterfaceHash.insert( key, iface ); newIfaces << key; } } // Now (re)config interfaces, but new interfaces need extra work so // they don't show bogus icon traffic states on startup. updateInterfaces(); foreach( QString key, interfaceList ) { Interface *iface = mInterfaceHash.value( key ); iface->configChanged(); if ( newIfaces.contains( key ) ) { backend->updatePackets( key ); iface->processUpdate(); connect( backend, SIGNAL( updateComplete() ), iface, SLOT( processUpdate() ) ); } } bool statsActivated = false; foreach ( Interface *iface, mInterfaceHash ) { if ( iface->settings().activateStatistics ) statsActivated = true; } if ( statsActivated ) { QStringList drivers = QSqlDatabase::drivers(); if ( !drivers.contains( QLatin1String("QSQLITE") ) ) { KMessageBox::sorry( 0, i18n( "The Qt4 SQLite database plugin is not available.\n" "Please install it to store traffic statistics." ) ); } } mPollTimer->start( generalSettings->pollInterval * 1000 ); } void KNemoDaemon::reparseConfiguration() { readConfig(); } QString KNemoDaemon::getSelectedInterface() { // Reset the variable to avoid preselecting an interface when // the user opens the control center module from the control // center afterwards. QString tmp = sSelectedInterface; sSelectedInterface = QString::null; return tmp; } void KNemoDaemon::updateInterfaces() { backend->update(); } void KNemoDaemon::togglePlotters() { bool showPlotters = false; foreach ( QString key, mInterfaceHash.keys() ) { // If only some of the plotters are visible, show them all if ( !mInterfaceHash.value( key )->plotterVisible() ) showPlotters = true; } foreach ( QString key, mInterfaceHash.keys() ) { mInterfaceHash.value( key )->toggleSignalPlotter( showPlotters ); } } #include "moc_knemodaemon.cpp" diff --git a/src/knemod/trayicon.cpp b/src/knemod/trayicon.cpp new file mode 100644 index 0000000..8c3d6f2 --- /dev/null +++ b/src/knemod/trayicon.cpp @@ -0,0 +1,564 @@ +/* This file is part of KNemo + Copyright (C) 2004, 2005 Percy Leonhardt + Copyright (C) 2009, 2010 John Stamp + + 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 "trayicon.h" +#include "global.h" +#include "interface.h" +#include "knemodaemon.h" +#include "utils.h" + +#ifdef __linux__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SHRINK_MAX 0.75 +#define HISTSIZE_STORE 0.5 + +TrayIcon::TrayIcon( Interface* interface, const QString &id, QWidget* parent ) : + KStatusNotifierItem( id, parent ) +{ + mInterface = interface; + setToolTipIconByName( QLatin1String("knemo") ); + setCategory(Hardware); + setStatus(Active); + connect(this, SIGNAL(secondaryActivateRequested(QPoint)), this, SLOT(togglePlotter())); + + // Cannot make this data static as the i18n macro doesn't seem + // to work when called to early i.e. before setting the catalogue. + mScope.insert( RT_SCOPE_NOWHERE, i18nc( "ipv6 address scope", "none" ) ); + mScope.insert( RT_SCOPE_HOST, i18nc( "ipv6 address scope", "host" ) ); + mScope.insert( RT_SCOPE_LINK, i18nc( "ipv6 address scope", "link" ) ); + mScope.insert( RT_SCOPE_SITE, i18nc( "ipv6 address scope", "site" ) ); + mScope.insert( RT_SCOPE_UNIVERSE, i18nc( "ipv6 address scope", "global" ) ); + + // Replace the standard quit action with ours + QAction *quitAction = new QAction(this); + quitAction->setText(KStatusNotifierItem::tr("Quit")); + quitAction->setIcon(QIcon::fromTheme(QLatin1String("application-exit"))); + QObject::connect(quitAction, SIGNAL(triggered()), this, SLOT(slotQuit())); + addAction(QLatin1String("quit"), quitAction); + + statusAction = new QAction( i18n( "Show &Status Dialog" ), this ); + plotterAction = new QAction( QIcon::fromTheme( QLatin1String("utilities-system-monitor") ), + i18n( "Show &Traffic Plotter" ), this ); + statisticsAction = new QAction( QIcon::fromTheme( QLatin1String("view-statistics") ), + i18n( "Show St&atistics" ), this ); + configAction = new QAction( QIcon::fromTheme( QLatin1String("configure") ), + i18n( "&Configure KNemo..." ), this ); + + connect( statusAction, SIGNAL( triggered() ), + mInterface, SLOT( showStatusDialog() ) ); + connect( plotterAction, SIGNAL( triggered() ), + mInterface, SLOT( showSignalPlotter() ) ); + connect( statisticsAction, SIGNAL( triggered() ), + mInterface, SLOT( showStatisticsDialog() ) ); + connect( configAction, SIGNAL( triggered() ), + this, SLOT( showConfigDialog() ) ); + + QMenu* menu = contextMenu(); + // FIXME: title for QMenu? + //menu->addTitle( QIcon::fromTheme( QLatin1String("knemo") ), i18n( "KNemo - %1", title ) ); + menu->addAction( statusAction ); + menu->addAction( plotterAction ); + menu->addAction( configAction ); + KHelpMenu* helpMenu( new KHelpMenu( menu, KAboutData::applicationData(), false ) ); + menu->addMenu( helpMenu->menu() )->setIcon( QIcon::fromTheme( QLatin1String("help-contents") ) ); + + configChanged(); +} + +TrayIcon::~TrayIcon() +{ +} + +void TrayIcon::showConfigDialog() +{ + KNemoDaemon::sSelectedInterface = mInterface->ifaceName(); + + KProcess process; + process << QLatin1String("kcmshell5") << QLatin1String("kcm_knemo"); + process.startDetached(); +} + +void TrayIcon::slotQuit() +{ + int autoStart = KMessageBox::questionYesNoCancel(0, i18n("Should KNemo start automatically when you login?"), + i18n("Automatically Start KNemo?"), KGuiItem(i18n("Start")), + KGuiItem(i18n("Do Not Start")), KStandardGuiItem::cancel(), QLatin1String("StartAutomatically")); + + KSharedConfig::Ptr config = KSharedConfig::openConfig(); + KConfigGroup generalGroup( config, confg_general ); + if ( autoStart == KMessageBox::Yes ) { + generalGroup.writeEntry( conf_autoStart, true ); + } else if ( autoStart == KMessageBox::No) { + generalGroup.writeEntry( conf_autoStart, false ); + } else // cancel chosen; don't quit + return; + config->sync(); + + qApp->quit(); +} + +void TrayIcon::activate(const QPoint&) +{ + mInterface->showStatusDialog( false ); +} + +void TrayIcon::togglePlotter() +{ + mInterface->showSignalPlotter( false ); +} + +void TrayIcon::configChanged() +{ + m_maxRate = mInterface->settings().maxRate; + + histSize = HISTSIZE_STORE/generalSettings->pollInterval; + if ( histSize < 2 ) + histSize = 3; + + for ( int i=0; i < histSize; i++ ) + { + m_rxHist.append( 0 ); + m_txHist.append( 0 ); + } + + // Add/remove statisticsAction + QMenu* menu = contextMenu(); + if ( mInterface->settings().activateStatistics ) + menu->insertAction( configAction, statisticsAction ); + else + menu->removeAction( statisticsAction ); + + // Now force update the icon + if ( mInterface->settings().iconTheme == TEXT_THEME ) + updateTextIcon( true ); + else if ( mInterface->settings().iconTheme == NETLOAD_THEME ) + updateBarIcon( true ); + else + updateImgIcon( mInterface->ifaceState() ); +} + +void TrayIcon::processUpdate() +{ + if ( mInterface->previousIfaceState() != mInterface->ifaceState() && + mInterface->settings().iconTheme != TEXT_THEME && + mInterface->settings().iconTheme != NETLOAD_THEME ) + { + updateImgIcon( mInterface->ifaceState() ); + } + + m_rxHist.prepend( mInterface->rxRate() ); + m_txHist.prepend( mInterface->txRate() ); + while ( m_rxHist.count() > histSize ) + { + m_rxHist.removeLast(); + m_txHist.removeLast(); + } + if ( mInterface->settings().iconTheme == TEXT_THEME ) + updateTextIcon(); + else if ( mInterface->settings().iconTheme == NETLOAD_THEME ) + updateBarIcon(); + QString currentTip; + QString title = i18n( "KNemo - %1", mInterface->ifaceName() ); + if ( toolTipTitle() != title ) + setToolTipTitle( title ); + currentTip = toolTipData(); + if ( currentTip != toolTipSubTitle() ) + setToolTipSubTitle( currentTip ); +} + +bool TrayIcon::conStatusChanged() +{ + int mask = (KNemoIface::Unavailable | KNemoIface::Available | KNemoIface::Connected ); + return (mInterface->backendData()->status & mask) != (mInterface->backendData()->prevStatus & mask); +} + +/* + * ImgIcon + */ + +void TrayIcon::updateImgIcon( int status ) +{ + QString iconName; + if ( mInterface->settings().iconTheme == SYSTEM_THEME ) + iconName = QStringLiteral("network-"); + else + iconName = QLatin1String("knemo-") + mInterface->settings().iconTheme + QLatin1Char('-'); + + // Now set the correct icon depending on the status of the interface. + if ( ( status & KNemoIface::RxTraffic ) && + ( status & KNemoIface::TxTraffic ) ) + { + iconName += ICON_RX_TX; + } + else if ( status & KNemoIface::RxTraffic ) + { + iconName += ICON_RX; + } + else if ( status & KNemoIface::TxTraffic ) + { + iconName += ICON_TX; + } + else if ( status & KNemoIface::Connected ) + { + iconName += ICON_IDLE; + } + else if ( status & KNemoIface::Available ) + { + iconName += ICON_OFFLINE; + } + else + { + iconName += ICON_ERROR; + } + setIconByName( iconName ); +} + +/* + * Bar Icon + */ + +QList TrayIcon::barLevels( QList& rxHist, QList& txHist ) +{ + // get the average rate of the two, then calculate based on the higher + // return ratios for both. + unsigned long histTotal = 0; + foreach( unsigned long j, rxHist ) + { + histTotal += j; + } + unsigned long rxAvgRate = histTotal / histSize; + + histTotal = 0; + foreach( unsigned long j, txHist ) + { + histTotal += j; + } + unsigned long txAvgRate = histTotal / histSize; + + // Adjust the scale of the bar icons when we don't have a fixed ceiling. + if ( !mInterface->settings().barScale ) + { + QListrxSortedMax( rxHist ); + QListtxSortedMax( txHist ); + qSort( rxSortedMax ); + qSort( txSortedMax ); + int multiplier = 1024; + if ( generalSettings->useBitrate ) + multiplier = 1000; + if( qMax(rxAvgRate, txAvgRate) > m_maxRate ) + { + m_maxRate = qMax(rxAvgRate, txAvgRate); + } + else if( qMax( rxSortedMax.last(), txSortedMax.last() ) < m_maxRate * SHRINK_MAX + && m_maxRate * SHRINK_MAX >= multiplier ) + { + m_maxRate *= SHRINK_MAX; + } + } + + QList levels; + qreal rxLevel = static_cast(rxAvgRate)/m_maxRate; + if ( rxLevel > 1.0 ) + rxLevel = 1.0; + levels.append(rxLevel); + qreal txLevel = static_cast(txAvgRate)/m_maxRate; + if ( txLevel > 1.0 ) + txLevel = 1.0; + levels.append(txLevel); + return levels; +} + +void TrayIcon::updateBarIcon( bool force ) +{ + // Has color changed? + if ( conStatusChanged() ) + { + force = true; + } + + QSize iconSize = getIconSize(); + + // If either of the bar heights have changed since the last time, we have + // to do an update. + QList levels = barLevels( m_rxHist, m_txHist ); + int barHeight = static_cast(round(iconSize.height() * levels.at(0)) + 0.5); + if ( barHeight != m_rxPrevBarHeight ) + { + force = true; + m_rxPrevBarHeight = barHeight; + } + barHeight = static_cast(round(iconSize.height() * levels.at(1)) + 0.5); + if ( barHeight != m_txPrevBarHeight ) + { + force = true; + m_txPrevBarHeight = barHeight; + } + + if ( !force ) + return; + + const BackendData * data = mInterface->backendData(); + + setIconByPixmap( genBarIcon( levels.at(0), levels.at(1), data->status ) ); + QPixmapCache::clear(); +} + +/* + * Text Icon + */ + +QString TrayIcon::compactTrayText(unsigned long data ) +{ + QString dataString; + // Space is tight, so no space between number and units, and the complete + // string should be no more than 4 chars. + /* Visually confusing to display bytes + if ( bytes < 922 ) // 922B = 0.9K + byteString = i18n( "%1B", bytes ); + */ + double multiplier = 1024; + if ( generalSettings->useBitrate ) + multiplier = 1000; + + int precision = 0; + if ( data < multiplier*9.95 ) // < 9.95K + { + precision = 1; + } + if ( data < multiplier*999.5 ) // < 999.5K + { + if ( generalSettings->useBitrate ) + dataString = i18n( "%1k", QString::number( data/multiplier, 'f', precision ) ); + else + dataString = i18n( "%1K", QString::number( data/multiplier, 'f', precision ) ); + return dataString; + } + + if ( data < pow(multiplier, 2)*9.95 ) // < 9.95M + precision = 1; + if ( data < pow(multiplier, 2)*999.5 ) // < 999.5M + { + dataString = i18n( "%1M", QString::number( data/pow(multiplier, 2), 'f', precision ) ); + return dataString; + } + + if ( data < pow(multiplier, 3)*9.95 ) // < 9.95G + precision = 1; + // xgettext: no-c-format + dataString = i18n( "%1G", QString::number( data/pow(multiplier, 3), 'f', precision) ); + return dataString; +} + +void TrayIcon::updateTextIcon( bool force ) +{ + // Has color changed? + if ( conStatusChanged() ) + { + force = true; + } + + // Has text changed? + QString byteText = compactTrayText( mInterface->rxRate() ); + if ( byteText != m_rxText ) + { + force = true; + m_rxText = byteText; + } + byteText = compactTrayText( mInterface->txRate() ); + if ( byteText != m_txText ) + { + force = true; + m_txText = byteText; + } + + if ( !force ) + return; + + setIconByPixmap( genTextIcon(m_rxText, m_txText, plasmaTheme->smallestFont(), mInterface->backendData()->status) ); + QPixmapCache::clear(); +} + +/* + * Tooltip + */ + +QString TrayIcon::formatTip( const QString& field, const QString& data, bool insertBreak ) +{ + QString ltip; + if (insertBreak) + ltip = QLatin1String("
"); + return ltip += i18nc( "field: value", "%1: %2", field, data ); +} + +QString TrayIcon::toolTipData() +{ + QString tipData; + QString tipVal; + int toolTipContent = generalSettings->toolTipContent; + const BackendData * data = mInterface->backendData(); + if ( !data ) + return QString(); + + tipData = QLatin1String(""); + tipVal = QLatin1String(""); + + if ( toolTipContent & INTERFACE ) + tipData = formatTip( i18n( "Interface" ), mInterface->ifaceName(), !tipData.isEmpty() ); + + if ( toolTipContent & STATUS ) + { + if ( data->status & KNemoIface::Connected ) + tipVal = i18n( "Connected" ); + else if ( data->status & KNemoIface::Up ) + tipVal = i18n( "Disconnected" ); + else if ( data->status & KNemoIface::Available ) + tipVal += i18n( "Down" ); + else + tipVal += i18n( "Unavailable" ); + tipData += formatTip( i18n( "Status" ), tipVal, !tipData.isEmpty() ); + } + + if ( data->status & KNemoIface::Connected && + toolTipContent & UPTIME ) + { + tipData += formatTip( i18n( "Connection time"), mInterface->uptimeString(), !tipData.isEmpty() ); + } + + if ( data->status & KNemoIface::Up ) + { + QStringList keys = data->addrData.keys(); + QString ip4Tip; + QString ip6Tip; + foreach ( QString key, keys ) + { + AddrData addrData = data->addrData.value( key ); + + if ( addrData.afType == AF_INET ) + { + if ( toolTipContent & IP_ADDRESS ) + ip4Tip += formatTip( i18n( "IPv4 Address"), key, !tipData.isEmpty() ); + if ( toolTipContent & SCOPE ) + ip4Tip += formatTip( i18n( "Scope & Flags"), mScope.value( addrData.scope ) + addrData.ipv6Flags, !tipData.isEmpty() ); + if ( toolTipContent & BCAST_ADDRESS && !addrData.hasPeer ) + ip4Tip += formatTip( i18n( "Broadcast Address"), addrData.broadcastAddress, !tipData.isEmpty() ); + else if ( toolTipContent & PTP_ADDRESS && addrData.hasPeer ) + ip4Tip += formatTip( i18n( "PtP Address"), addrData.broadcastAddress, !tipData.isEmpty() ); + } + else + { + if ( toolTipContent & IP_ADDRESS ) + ip6Tip += formatTip( i18n( "IPv6 Address"), key, !tipData.isEmpty() ); + if ( toolTipContent & SCOPE ) + ip4Tip += formatTip( i18n( "Scope & Flags"), mScope.value( addrData.scope ), !tipData.isEmpty() ); + if ( toolTipContent & PTP_ADDRESS && addrData.hasPeer ) + ip4Tip += formatTip( i18n( "PtP Address"), addrData.broadcastAddress, !tipData.isEmpty() ); + } + } + tipData += ip4Tip + ip6Tip; + + if ( KNemoIface::Ethernet == data->interfaceType ) + { + if ( toolTipContent & GATEWAY ) + { + if ( !data->ip4DefaultGateway.isEmpty() ) + tipData += formatTip( i18n( "IPv4 Default Gateway"), data->ip4DefaultGateway, !tipData.isEmpty() ); + if ( !data->ip6DefaultGateway.isEmpty() ) + tipData += formatTip( i18n( "IPv6 Default Gateway"), data->ip6DefaultGateway, !tipData.isEmpty() ); + } + } + } + + if ( data->status & KNemoIface::Available ) + { + if ( toolTipContent & HW_ADDRESS ) + tipData += formatTip( i18n( "MAC Address"), data->hwAddress, !tipData.isEmpty() ); + if ( toolTipContent & RX_PACKETS ) + tipData += formatTip( i18n( "Packets Received"), QString::number( data->rxPackets ), !tipData.isEmpty() ); + if ( toolTipContent & TX_PACKETS ) + tipData += formatTip( i18n( "Packets Sent"), QString::number( data->txPackets ), !tipData.isEmpty() ); + if ( toolTipContent & RX_BYTES ) + tipData += formatTip( i18n( "Bytes Received"), data->rxString, !tipData.isEmpty() ); + if ( toolTipContent & TX_BYTES ) + tipData += formatTip( i18n( "Bytes Sent"), data->txString, !tipData.isEmpty() ); + } + + if ( data->status & KNemoIface::Connected ) + { + if ( toolTipContent & DOWNLOAD_SPEED ) + tipData += formatTip( i18n( "Download Speed"), mInterface->rxRateStr(), !tipData.isEmpty() ); + if ( toolTipContent & UPLOAD_SPEED ) + tipData += formatTip( i18n( "Upload Speed"), mInterface->txRateStr(), !tipData.isEmpty() ); + } + + if ( data->status & KNemoIface::Connected && data->isWireless ) + { + if ( toolTipContent & ESSID ) + tipData += formatTip( i18n( "ESSID"), data->essid, !tipData.isEmpty() ); + if ( toolTipContent & MODE ) + tipData += formatTip( i18n( "Mode"), data->mode, !tipData.isEmpty() ); + if ( toolTipContent & FREQUENCY ) + tipData += formatTip( i18n( "Frequency"), data->frequency, !tipData.isEmpty() ); + if ( toolTipContent & BIT_RATE ) + tipData += formatTip( i18n( "Bit Rate"), data->bitRate, !tipData.isEmpty() ); + if ( toolTipContent & ACCESS_POINT ) + tipData += formatTip( i18n( "Access Point"), data->accessPoint, !tipData.isEmpty() ); + if ( toolTipContent & LINK_QUALITY ) + tipData += formatTip( i18n( "Link Quality"), data->linkQuality, !tipData.isEmpty() ); +#ifdef __linux__ + if ( toolTipContent & NICK_NAME ) + tipData += formatTip( i18n( "Nickname"), data->nickName, !tipData.isEmpty() ); +#endif + if ( toolTipContent & ENCRYPTION ) + { + if ( data->isEncrypted == true ) + { + tipVal = i18n( "active" ); + } + else + { + tipVal = i18n( "off" ); + } + tipData += formatTip( i18n( "Encryption"), tipVal, !tipData.isEmpty() ); + } + } + return tipData; +} + +#include "moc_trayicon.cpp" diff --git a/src/knemod/interfacetray.h b/src/knemod/trayicon.h similarity index 57% rename from src/knemod/interfacetray.h rename to src/knemod/trayicon.h index 50361f6..4c18c7d 100644 --- a/src/knemod/interfacetray.h +++ b/src/knemod/trayicon.h @@ -1,61 +1,85 @@ /* This file is part of KNemo Copyright (C) 2004, 2005 Percy Leonhardt Copyright (C) 2009, 2010 John Stamp 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. */ -#ifndef INTERFACETRAY_H -#define INTERFACETRAY_H +#ifndef TRAYICON_H +#define TRAYICON_H #include "config-knemo.h" #include -#include "interface.h" +class Interface; -class InterfaceTray : public KStatusNotifierItem +class TrayIcon : public KStatusNotifierItem { Q_OBJECT public: /** * Default Constructor */ - InterfaceTray( Interface* interface, const QString &id, QWidget* parent = 0 ); + TrayIcon( Interface* interface, const QString &id, QWidget* parent = 0 ); /** * Default Destructor */ - virtual ~InterfaceTray(); + virtual ~TrayIcon(); - void updateToolTip(); + void configChanged(); + void processUpdate(); public Q_SLOTS: void activate(const QPoint &pos); private: + bool conStatusChanged(); + QList barLevels( QList& rxHist, QList& txHist ); + void updateBarIcon( bool force = false ); + QString compactTrayText( unsigned long ); + void updateTextIcon( bool force = false ); + void updateImgIcon( int status ); + QString toolTipData(); + QString formatTip( const QString& field, const QString& data, bool insertBreak ); + + Interface* mInterface; QMap mScope; - QString toolTipData(); - QString formatTip( const QString& field, const QString& data, bool insertBreak ); - void setupMappings(); + QAction* statusAction; + QAction* plotterAction; + QAction* statisticsAction; + QAction* configAction; + QString m_rxText; + QString m_txText; + int m_rxPrevBarHeight; + int m_txPrevBarHeight; + int histSize; + QListm_rxHist; + QListm_txHist; + unsigned int m_maxRate; private Q_SLOTS: void togglePlotter(); void slotQuit(); + /* + * Called when the user selects 'Configure KNemo' from the context menu + */ + void showConfigDialog(); }; -#endif // INTERFACETRAY_H +#endif // TRAYICON_H