diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 1f15cc8..4816d60 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -1,467 +1,468 @@ /* This file is part of KNemo 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. Portions taken from FreeSWITCH Copyright (c) 2007-2008, Thomas BERNARD Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. */ +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "data.h" #include "utils.h" #ifdef __linux__ #include #include #else #include #include #include #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ l = sizeof(struct sockaddr); memmove(cp, &(u), l); cp += l;\ } #define rtm m_rtmsg.m_rtm #endif #ifdef __linux__ QString ipv4gwi; QString ipv6gwi; QString ipv4gw; QString ipv6gw; void parseNetlinkRoute( struct nl_object *object, void * ) { struct rtnl_route *const route = reinterpret_cast(object); int rtfamily = rtnl_route_get_family( route ); if ( rtfamily == AF_INET || rtfamily == AF_INET6 ) { struct rtnl_nexthop *nh = NULL; struct nl_addr *addr = NULL; if ( rtnl_route_get_nnexthops( route ) > 0 ) { nh = rtnl_route_nexthop_n ( route, 0 ); addr = rtnl_route_nh_get_gateway( nh ); } if ( addr ) { char gwaddr[ INET6_ADDRSTRLEN ]; char gwname[ IFNAMSIZ ]; memset( gwaddr, 0, sizeof( gwaddr ) ); struct in_addr * inad = reinterpret_cast(nl_addr_get_binary_addr( addr )); nl_addr2str( addr, gwaddr, sizeof( gwaddr ) ); inet_ntop( rtfamily, &inad->s_addr, gwaddr, sizeof( gwaddr ) ); int oif = rtnl_route_nh_get_ifindex( nh ); if_indextoname( oif, gwname ); if ( rtfamily == AF_INET ) { ipv4gw = QLatin1String(gwaddr); ipv4gwi = QLatin1String(gwname); } else if ( rtfamily == AF_INET6 ) { ipv6gw = QLatin1String(gwaddr); ipv6gwi = QLatin1String(gwname); } } } } QString getNetlinkRoute( int afType, QString *defaultGateway, void *data ) { if ( !data ) return QString(); struct nl_cache* rtlcache = static_cast(data); if ( afType == AF_INET ) { ipv4gw.clear(); ipv4gwi.clear(); } else if ( afType == AF_INET6 ) { ipv6gw.clear(); ipv6gwi.clear(); } nl_cache_foreach( rtlcache, parseNetlinkRoute, NULL); if ( afType == AF_INET ) { if ( defaultGateway ) *defaultGateway = ipv4gw; return ipv4gwi; } else { if ( defaultGateway ) *defaultGateway = ipv6gw; return ipv6gwi; } } #else QString getSocketRoute( int afType, QString *defaultGateway ) { struct { struct rt_msghdr m_rtm; char m_space[ 512 ]; } m_rtmsg; int s, seq, l, rtm_addrs, i; pid_t pid; struct sockaddr so_dst, so_mask; char *cp = m_rtmsg.m_space; struct sockaddr *gate = NULL, *sa; struct rt_msghdr *msg_hdr; char outBuf[ INET6_ADDRSTRLEN ]; memset( &outBuf, 0, sizeof( outBuf ) ); void *tempAddrPtr = NULL; QString ifname; pid = getpid(); seq = 0; rtm_addrs = RTA_DST | RTA_NETMASK; memset( &so_dst, 0, sizeof( so_dst ) ); memset( &so_mask, 0, sizeof( so_mask ) ); memset( &rtm, 0, sizeof( struct rt_msghdr ) ); rtm.rtm_type = RTM_GET; rtm.rtm_flags = RTF_UP | RTF_GATEWAY; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = ++seq; rtm.rtm_addrs = rtm_addrs; if ( afType == AF_INET ) { so_dst.sa_family = AF_INET; so_mask.sa_family = AF_INET; } else { so_dst.sa_family = AF_INET6; so_mask.sa_family = AF_INET6; } NEXTADDR( RTA_DST, so_dst ); NEXTADDR( RTA_NETMASK, so_mask ); rtm.rtm_msglen = l = cp - reinterpret_cast(&m_rtmsg); s = socket(PF_ROUTE, SOCK_RAW, 0); if ( write( s, reinterpret_cast(&m_rtmsg), l ) < 0 ) { close( s ); return ifname; } do { l = read(s, reinterpret_cast(&m_rtmsg), sizeof( m_rtmsg ) ); } while ( l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid) ); close( s ); msg_hdr = &rtm; cp = reinterpret_cast(msg_hdr + 1); if ( msg_hdr->rtm_addrs ) { for ( i = 1; i; i <<= 1 ) if ( i & msg_hdr->rtm_addrs ) { sa = reinterpret_cast(cp); if ( i == RTA_GATEWAY ) { gate = sa; char tempname[ IFNAMSIZ ]; if_indextoname( msg_hdr->rtm_index, tempname ); ifname = tempname; } cp += SA_SIZE( sa ); } } else return ifname; if ( AF_INET == afType ) tempAddrPtr = & reinterpret_cast(gate)->sin_addr; else tempAddrPtr = & reinterpret_cast(gate)->sin6_addr; inet_ntop( gate->sa_family, tempAddrPtr, outBuf, sizeof( outBuf ) ); if ( defaultGateway && strncmp( outBuf, "0.0.0.0", 7 ) != 0 ) *defaultGateway = outBuf; return ifname; } #endif QString getDefaultRoute( int afType, QString *defaultGateway, void *data ) { #ifdef __linux__ return getNetlinkRoute( afType, defaultGateway, data ); #else return getSocketRoute( afType, defaultGateway ); #endif } QList findThemes() { const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("knemo/themes"), QStandardPaths::LocateDirectory); QStringList themelist; Q_FOREACH (const QString& dir, dirs) { const QStringList fileNames = QDir(dir).entryList(QStringList() << QLatin1String("*.desktop")); Q_FOREACH (const QString& file, fileNames) { themelist.append(dir + QLatin1Char('/') + file); } } QList iconThemes; foreach ( QString themeFile, themelist ) { KSharedConfig::Ptr conf = KSharedConfig::openConfig( themeFile ); KConfigGroup cfg( conf, QLatin1String("Desktop Entry") ); KNemoTheme theme; theme.name = cfg.readEntry(QLatin1String("Name")); theme.comment = cfg.readEntry(QLatin1String("Comment")); theme.internalName = cfg.readEntry( QLatin1String("X-KNemo-Theme") ); iconThemes << theme; } return iconThemes; } QSize getIconSize() { // This is borrowed from the plasma system tray: // plasma-workspace/applets/systemtray/package/contents/ui/main.qml // plasma-workspace/applets/systemtray/package/contents/code/Layout.js int preferredItemSize = 128; Plasma::Theme theme; int baseSize = theme.mSize(theme.defaultFont()).height(); int suggestedsize = min(baseSize * 2, preferredItemSize); QSize resultingsize; if (suggestedsize < 16 || suggestedsize >= 64) { resultingsize = QSize(suggestedsize, suggestedsize); } else if (suggestedsize < 22) { resultingsize = QSize(16, 16); } else if (suggestedsize < 24) { resultingsize = QSize(22, 22); } else if (suggestedsize < 32) { resultingsize = QSize(24, 24); } else if (suggestedsize < 48) { resultingsize = QSize(32, 32); } else if (suggestedsize < 64) { resultingsize = QSize(48, 48); } return resultingsize; } QPixmap genTextIcon(const QString& incomingText, const QString& outgoingText, const QFont& font, int status) { QSize iconSize = getIconSize(); QPixmap textIcon(iconSize); QRect topRect( 0, 0, iconSize.width(), iconSize.height()/2 ); QRect bottomRect( 0, iconSize.width()/2, iconSize.width(), iconSize.height()/2 ); textIcon.fill( Qt::transparent ); QPainter p( &textIcon ); p.setBrush( Qt::NoBrush ); p.setOpacity( 1.0 ); QColor textColor; // rxFont and txFont should be the same size per poll period QFont rxFont = setIconFont( incomingText, font, iconSize.height() ); QFont txFont = setIconFont( outgoingText, font, iconSize.height() ); rxFont.setPointSizeF( qMin(rxFont.pointSizeF(), txFont.pointSizeF()) ); if ( status & KNemoIface::Connected ) textColor = KColorScheme(QPalette::Active).foreground(KColorScheme::NormalText).color(); else if ( status & KNemoIface::Available ) textColor = KColorScheme(QPalette::Active).foreground(KColorScheme::InactiveText).color(); else textColor = KColorScheme(QPalette::Active).foreground(KColorScheme::NegativeText).color(); p.setFont( rxFont ); p.setPen( textColor ); p.drawText( topRect, Qt::AlignCenter | Qt::AlignRight, incomingText ); p.drawText( bottomRect, Qt::AlignCenter | Qt::AlignRight, outgoingText ); return textIcon; } QPixmap genBarIcon(qreal rxLevel, qreal txLevel, int status) { QSize iconSize = getIconSize(); QColor rxColor; QColor txColor; QColor bgColor; if ( status & KNemoIface::Connected ) { rxColor = KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::ActiveText).color(); txColor = KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::NeutralText).color(); bgColor = KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::InactiveText).color(); bgColor.setAlpha( 77 ); } else if ( status & KNemoIface::Available ) { bgColor = KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::InactiveText).color(); bgColor.setAlpha( 153 ); } else { bgColor = KColorScheme(QPalette::Active, KColorScheme::Window).foreground(KColorScheme::NegativeText).color(); } int barWidth = static_cast(round(iconSize.width()/3.0) + 0.5); int margins = iconSize.width() - (barWidth*2); int midMargin = static_cast(round(margins/3.0) + 0.5); int outerMargin = static_cast(round((margins - midMargin)/2.0) + 0.5); midMargin = outerMargin + barWidth + midMargin; QPixmap barIcon( iconSize ); barIcon.fill( Qt::transparent ); int top = iconSize.height() - static_cast(round(iconSize.height() * txLevel) + 0.5); QRect topLeftRect( outerMargin, 0, barWidth, top ); QRect leftRect( outerMargin, top, barWidth, iconSize.height() ); top = iconSize.height() - static_cast(round(iconSize.height() * rxLevel) + 0.5); QRect topRightRect( midMargin, 0, barWidth, top ); QRect rightRect( midMargin, top, barWidth, iconSize.height() ); QPainter p( &barIcon ); p.fillRect( leftRect, txColor ); p.fillRect( rightRect, rxColor ); p.fillRect( topLeftRect, bgColor ); p.fillRect( topRightRect, bgColor ); return barIcon; } QFont setIconFont( const QString& text, const QFont& font, int iconWidth ) { // Is there a better way to do this? QFont f( font ); qreal pointSize = f.pointSizeF(); QFontMetricsF fm( f ); qreal w = fm.width( text ); if ( w != iconWidth ) { pointSize *= qreal( iconWidth ) / w; if ( pointSize < 0.5 ) pointSize = 0.5; f.setPointSizeF( pointSize ); fm = QFontMetricsF( f ); while ( pointSize > 0.5 && fm.width( text ) > iconWidth ) { pointSize -= 0.5; f.setPointSizeF( pointSize ); fm = QFontMetricsF( f ); } } // Don't want decender()...space too tight if ( fm.ascent() > iconWidth/2.0 ) { pointSize *= iconWidth / 2.0 / fm.ascent(); if ( pointSize < 0.5 ) pointSize = 0.5; f.setPointSizeF( pointSize ); fm = QFontMetricsF( f ); while ( pointSize > 0.5 && fm.ascent() > iconWidth/2.0 ) { pointSize -= 0.5; f.setPointSizeF( pointSize ); fm = QFontMetricsF( f ); } } return f; } double validatePoll( double val ) { int siz = sizeof(pollIntervals)/sizeof(double); for ( int i = 0; i < siz; i++ ) { if ( val <= pollIntervals[i] ) { val = pollIntervals[i]; return val; } } return GeneralSettings().pollInterval; } void migrateKde4Conf() { // Kdelibs4Migration QStringList configFiles; configFiles << QLatin1String("knemorc") << QLatin1String("knemo.notifyrc"); Kdelibs4ConfigMigrator migrator(QLatin1String("knemo")); // the same name defined in the aboutData migrator.setConfigFiles(configFiles); if (migrator.migrate()) { // look in knemorc; find configured stats path (or KDE4 default); migrate stats. KConfigGroup generalGroup( KSharedConfig::openConfig(), confg_general ); Kdelibs4Migration dataMigrator; QString sourceBasePath = generalGroup.readEntry( QLatin1String("StatisticsDir"), dataMigrator.saveLocation("data", QLatin1String("knemo")) ); QUrl testUrl(sourceBasePath); if ( testUrl.isLocalFile() ) sourceBasePath = testUrl.toLocalFile(); const QString targetBasePath = GeneralSettings().statisticsDir.absolutePath() + QLatin1Char('/'); QDir sourceDir(sourceBasePath); if(sourceDir.exists()) { QStringList fileNames = sourceDir.entryList(QDir::Files); if (QDir().mkpath(targetBasePath)) { foreach (const QString &fileName, fileNames) { QFile::copy(sourceBasePath + fileName, targetBasePath + fileName); } } } } } diff --git a/src/knemod/trayicon.cpp b/src/knemod/trayicon.cpp index 8c3d6f2..95ae383 100644 --- a/src/knemod/trayicon.cpp +++ b/src/knemod/trayicon.cpp @@ -1,564 +1,565 @@ /* 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 #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"