You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
461 lines
16 KiB
461 lines
16 KiB
|
|
/***************************************************************************
|
|
* *
|
|
* KNetLoad is copyright (c) 1999-2000, Markus Gustavsson *
|
|
* (c) 2002, Ben Burton *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "devicedialog.h"
|
|
#include "knetdock.h"
|
|
#include "knetload.h"
|
|
#include "knetproc.h"
|
|
#include "scaledialog.h"
|
|
|
|
#include <kaction.h>
|
|
#include <tdeconfig.h>
|
|
#include <kiconloader.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kpopupmenu.h>
|
|
#include <tqdir.h>
|
|
|
|
#define DEFAULT_SCALE 128000
|
|
#define MAX_NET_DEV_LINE 512
|
|
|
|
KNetLoad::KNetLoad(TQWidget *parent, const char *name) :
|
|
StatPopup(false, parent, name) {
|
|
// Create the raw network data reader.
|
|
proc = new KNetProc();
|
|
|
|
// Stock device names are not i18n()ed since they're literal
|
|
// interface names.
|
|
#ifndef Q_OS_LINUX
|
|
stockDevice.push_back("lo"); stockDeviceIconOff.push_back("devlo"); stockDeviceIconOn.push_back("devloon");
|
|
stockDevice.push_back("eth0"); stockDeviceIconOff.push_back("deveth0"); stockDeviceIconOn.push_back("deveth0on");
|
|
stockDevice.push_back("ppp0"); stockDeviceIconOff.push_back("devppp0"); stockDeviceIconOn.push_back("devppp0on");
|
|
stockDevice.push_back("ippp0"); stockDeviceIconOff.push_back("devippp0"); stockDeviceIconOn.push_back("devippp0on");
|
|
#else
|
|
if ( TQDir::root().exists("/sys/class/net") )
|
|
{ // Exists /sys, 2.6 series kernel
|
|
TQDir sys("/sys/class/net");
|
|
TQStringList l = sys.entryList();
|
|
for(TQStringList::iterator it = l.begin(); it != l.end(); it++)
|
|
{
|
|
if ( (*it)[0] == '.' )
|
|
continue;
|
|
|
|
stockDevice.push_back( *it );
|
|
if ( *it == "lo" ) {
|
|
stockDeviceIconOn.push_back("devloon");
|
|
stockDeviceIconOff.push_back("devlo");
|
|
} else if ( (*it).find("eth") == 0 ) {
|
|
stockDeviceIconOn.push_back("deveth0on");
|
|
stockDeviceIconOff.push_back("deveth0");
|
|
} else if ( (*it).find("ppp") == 0 ) {
|
|
stockDeviceIconOn.push_back("devppp0on");
|
|
stockDeviceIconOff.push_back("devppp0");
|
|
} else if ( (*it).find("ippp") == 0 ) {
|
|
stockDeviceIconOn.push_back("devippp0on");
|
|
stockDeviceIconOff.push_back("devippp0");
|
|
} else {
|
|
stockDeviceIconOn.push_back("devotheron");
|
|
stockDeviceIconOff.push_back("devother");
|
|
}
|
|
}
|
|
} else { // Doesn't exists, kernel 2.4 or earlier
|
|
static FILE* fd;
|
|
static char line[MAX_NET_DEV_LINE];
|
|
static char* pos;
|
|
static char* iface;
|
|
|
|
|
|
if ((fd = fopen("/proc/net/dev", "r")) == 0)
|
|
return;
|
|
|
|
// Read the unwanted header lines.
|
|
fgets(line, MAX_NET_DEV_LINE, fd);
|
|
fgets(line, MAX_NET_DEV_LINE, fd);
|
|
|
|
// Read through the remaining lines until we find all devices
|
|
while (! feof(fd)) {
|
|
fgets(line, MAX_NET_DEV_LINE, fd);
|
|
|
|
// Find the interface name for this line.
|
|
for (iface = line; *iface == ' '; iface++)
|
|
; // (skip initial spaces)
|
|
for (pos = iface; *pos != ':' && *pos != 0; pos++)
|
|
; // (move to next ':' or end of string)
|
|
if (*pos == 0)
|
|
continue; // (was not ':')
|
|
*pos = 0;
|
|
|
|
// Now iface points to a null-terminated string containing the
|
|
// interface name for this particular line.
|
|
stockDevice.push_back( iface );
|
|
if ( strncmp(iface, "lo", 2) == 0 ) {
|
|
stockDeviceIconOn.push_back("devloon");
|
|
stockDeviceIconOff.push_back("devlo");
|
|
} else if ( strncmp(iface, "eth", 3) == 0 ) {
|
|
stockDeviceIconOn.push_back("deveth0on");
|
|
stockDeviceIconOff.push_back("deveth0");
|
|
} else if ( strncmp(iface, "ppp", 3) == 0 ) {
|
|
stockDeviceIconOn.push_back("devppp0on");
|
|
stockDeviceIconOff.push_back("devppp0");
|
|
} else if ( strncmp(iface, "ippp", 4) == 0 ) {
|
|
stockDeviceIconOn.push_back("devippp0on");
|
|
stockDeviceIconOff.push_back("devippp0");
|
|
} else {
|
|
stockDeviceIconOn.push_back("devotheron");
|
|
stockDeviceIconOff.push_back("devother");
|
|
}
|
|
}
|
|
fclose(fd);
|
|
}
|
|
#endif
|
|
|
|
// Set up actions and read the config file.
|
|
setupActions();
|
|
|
|
// Create system tray windows.
|
|
dock[0] = new KNetDock(0, true, this); // In
|
|
dock[1] = new KNetDock(1, false, this); // Out
|
|
|
|
// Initialise the pop-up window.
|
|
readPopupState();
|
|
|
|
// Off we go!
|
|
requestResize();
|
|
if (isActive())
|
|
startUpdates();
|
|
}
|
|
|
|
KNetLoad::~KNetLoad() {
|
|
delete proc;
|
|
}
|
|
|
|
void KNetLoad::setDevice(const TQString& newDevice) {
|
|
proc->setDevice(newDevice);
|
|
clearHistory();
|
|
updateDeviceMenus();
|
|
|
|
requestResize();
|
|
|
|
config->setGroup("General Options");
|
|
config->writeEntry("Device", newDevice);
|
|
config->sync();
|
|
}
|
|
|
|
void KNetLoad::setDevice(int deviceIndex) {
|
|
// Is it one of the stock devices?
|
|
if ((deviceIndex >= 0) && !stockDevice[deviceIndex].isEmpty()) {
|
|
setDevice(stockDevice[deviceIndex]);
|
|
return;
|
|
}
|
|
|
|
// It's a custom device. Open a dialog.
|
|
DeviceDialog dlg(proc->getDevice(), firstDock());
|
|
if (dlg.exec()) {
|
|
TQString newDevice = dlg.getDevice().stripWhiteSpace();
|
|
if (newDevice.isEmpty())
|
|
KMessageBox::error(firstDock(),
|
|
i18n("The device name cannot be empty."));
|
|
else {
|
|
setDevice(newDevice);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If we fell through, update the menus anyway in case we
|
|
// inadvertently changed a checked state.
|
|
updateDeviceMenus();
|
|
}
|
|
|
|
void KNetLoad::setScaleIn(int scale) {
|
|
if (scale <= 0) {
|
|
// Select a non-standard scale.
|
|
ScaleDialog dlg(scaleIn / 1000,
|
|
i18n("Select Scale (In)"), firstDock());
|
|
if (dlg.exec()) {
|
|
scale = dlg.getScale();
|
|
if (scale <= 0)
|
|
return;
|
|
// Convert to bits per second and fall through.
|
|
scale *= 1000;
|
|
} else
|
|
return;
|
|
}
|
|
|
|
scaleIn = scale;
|
|
updateScaleInMenus();
|
|
|
|
config->setGroup("General Options");
|
|
config->writeEntry("ScaleIn", scale);
|
|
config->sync();
|
|
}
|
|
|
|
void KNetLoad::setScaleOut(int scale) {
|
|
// Note that, for scale (out), scale == 0 means to use the same as
|
|
// scale (in).
|
|
if (scale < 0) {
|
|
// Select a non-standard scale.
|
|
ScaleDialog dlg(scaleOut ? scaleOut / 1000 : scaleIn / 1000,
|
|
i18n("Select Scale (Out)"), firstDock());
|
|
if (dlg.exec()) {
|
|
scale = dlg.getScale();
|
|
if (scale <= 0)
|
|
return;
|
|
// Convert to bits per second and fall through.
|
|
scale *= 1000;
|
|
} else
|
|
return;
|
|
}
|
|
|
|
scaleOut = scale;
|
|
updateScaleOutMenus();
|
|
|
|
config->setGroup("General Options");
|
|
config->writeEntry("ScaleOut", scale);
|
|
config->sync();
|
|
}
|
|
|
|
TQString KNetLoad::dockName(int which) const {
|
|
return (which == 0 ? i18n("In") : i18n("Out"));
|
|
}
|
|
|
|
TQColor KNetLoad::defaultDockColor(int which) const {
|
|
return (which == 0 ? TQColor(0, 0, 255) : TQColor(255, 0, 255));
|
|
}
|
|
|
|
void KNetLoad::setupCustomActions() {
|
|
// There are no device actions; instead menu items are used
|
|
// directly.
|
|
proc->setDevice(config->readEntry("Device", "eth0"));
|
|
|
|
// There are no scaling actions; instead menu items are used
|
|
// directly.
|
|
scaleIn = config->readNumEntry("ScaleIn", DEFAULT_SCALE);
|
|
scaleOut = config->readNumEntry("ScaleOut", 0 /* same as in */);
|
|
}
|
|
|
|
void KNetLoad::insertCustomItems(TDEPopupMenu* menu) {
|
|
// Device menu. The menu item IDs are indices into the
|
|
// stockDevice[] array.
|
|
TDEPopupMenu* deviceMenu = new TDEPopupMenu(menu);
|
|
deviceMenus.append(deviceMenu);
|
|
deviceMenu->setCheckable(true);
|
|
for (int i = 0; i < stockDevice.count(); i++)
|
|
deviceMenu->insertItem(SmallIcon(stockDeviceIconOff[i]),
|
|
stockDevice[i], i);
|
|
deviceMenu->insertItem(SmallIcon("devother"), i18n("Other..."));
|
|
updateDeviceMenu(deviceMenu);
|
|
connect(deviceMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setDevice(int)));
|
|
menu->insertItem(SmallIcon("devselect"), i18n("&Device"), deviceMenu);
|
|
|
|
// Scale menus. The menu item IDs are the scales themselves (in bits
|
|
// per second), to make event handling sane.
|
|
TDEPopupMenu* scaleInMenu = new TDEPopupMenu(menu);
|
|
scaleInMenus.append(scaleInMenu);
|
|
scaleInMenu->setCheckable(true);
|
|
scaleInMenu->insertItem(i18n("28.8KBit/s"), 28800);
|
|
scaleInMenu->insertItem(i18n("33.6KBit/s"), 33600);
|
|
scaleInMenu->insertItem(i18n("56KBit/s"), 56000);
|
|
scaleInMenu->insertItem(i18n("64KBit/s"), 64000);
|
|
scaleInMenu->insertItem(i18n("128KBit/s"), 128000);
|
|
scaleInMenu->insertItem(i18n("256KBit/s"), 256000);
|
|
scaleInMenu->insertItem(i18n("512KBit/s"), 512000);
|
|
scaleInMenu->insertItem(i18n("1MBit/s"), 1000000);
|
|
scaleInMenu->insertItem(i18n("2MBit/s"), 2000000);
|
|
scaleInMenu->insertItem(i18n("10MBit/s"), 10000000);
|
|
scaleInMenu->insertItem(i18n("Other..."));
|
|
updateScaleInMenu(scaleInMenu);
|
|
connect(scaleInMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setScaleIn(int)));
|
|
menu->insertItem(SmallIcon("scalein"), i18n("&Scale (In)"), scaleInMenu);
|
|
|
|
TDEPopupMenu* scaleOutMenu = new TDEPopupMenu(menu);
|
|
scaleOutMenus.append(scaleOutMenu);
|
|
scaleOutMenu->setCheckable(true);
|
|
scaleOutMenu->insertItem(i18n("28.8KBit/s"), 28800);
|
|
scaleOutMenu->insertItem(i18n("33.6KBit/s"), 33600);
|
|
scaleOutMenu->insertItem(i18n("56KBit/s"), 56000);
|
|
scaleOutMenu->insertItem(i18n("64KBit/s"), 64000);
|
|
scaleOutMenu->insertItem(i18n("128KBit/s"), 128000);
|
|
scaleOutMenu->insertItem(i18n("256KBit/s"), 256000);
|
|
scaleOutMenu->insertItem(i18n("512KBit/s"), 512000);
|
|
scaleOutMenu->insertItem(i18n("1MBit/s"), 1000000);
|
|
scaleOutMenu->insertItem(i18n("2MBit/s"), 2000000);
|
|
scaleOutMenu->insertItem(i18n("10MBit/s"), 10000000);
|
|
scaleOutMenu->insertItem(i18n("Other..."));
|
|
scaleOutMenu->insertSeparator();
|
|
scaleOutMenu->insertItem(i18n("Same as for in"), 0);
|
|
updateScaleOutMenu(scaleOutMenu);
|
|
connect(scaleOutMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setScaleOut(int)));
|
|
menu->insertItem(SmallIcon("scaleout"), i18n("&Scale (Out)"), scaleOutMenu);
|
|
|
|
// The final separator.
|
|
menu->insertSeparator();
|
|
}
|
|
|
|
void KNetLoad::takeReadingInternal() {
|
|
proc->readLoad();
|
|
|
|
// Rates in bits per second.
|
|
bitRateIn = proc->recentBytesIn() * 8.0 /
|
|
(((float) getSpeed()) / 1000.0);
|
|
bitRateOut = proc->recentBytesOut() * 8.0 /
|
|
(((float) getSpeed()) / 1000.0);
|
|
|
|
// Convert to percentages.
|
|
upper[0] = (int) (100.0 * bitRateIn / ((float) scaleIn));
|
|
upper[1] = (int) (100.0 * bitRateOut /
|
|
((float) (scaleOut ? scaleOut : scaleIn)));
|
|
|
|
if (upper[0] < 0)
|
|
upper[0] = 0;
|
|
if (upper[1] < 0)
|
|
upper[1] = 0;
|
|
if (upper[0] > 100)
|
|
upper[0] = 100;
|
|
if (upper[1] > 100)
|
|
upper[1] = 100;
|
|
|
|
if (isVisible())
|
|
fullReading = i18n(
|
|
"Current In: %1 KBit/s, Total In: %2 MB.\n"
|
|
"Current Out: %3 KBit/s, Total Out: %4 MB.")
|
|
.arg(TDEGlobal::locale()->formatNumber((int)((bitRateIn + 50) / 100) / 10.0)).arg(TDEGlobal::locale()->formatNumber(proc->totalMbIn()))
|
|
.arg(TDEGlobal::locale()->formatNumber((int)((bitRateOut + 50) / 100) / 10.0)).arg(TDEGlobal::locale()->formatNumber(proc->totalMbOut()));
|
|
}
|
|
|
|
void KNetLoad::updateDeviceMenu(TDEPopupMenu* menu) {
|
|
const TQString& dev = proc->getDevice();
|
|
|
|
// Update the checked/unchecked states of menu items.
|
|
bool found = false;
|
|
int id;
|
|
int otherId = -1;
|
|
for (unsigned index = 0; index < menu->count(); index++) {
|
|
id = menu->idAt(index);
|
|
|
|
if (id >= 0 && dev == menu->text(id)) {
|
|
// This is our device.
|
|
found = true;
|
|
if (! menu->isItemChecked(id)) {
|
|
menu->setItemChecked(id, true);
|
|
menu->changeItem(id, SmallIcon(stockDeviceIconOn[id]),
|
|
stockDevice[id]);
|
|
}
|
|
} else {
|
|
// This is not our device.
|
|
if (menu->isItemChecked(id)) {
|
|
menu->setItemChecked(id, false);
|
|
menu->changeItem(id, SmallIcon(stockDeviceIconOff[id]),
|
|
stockDevice[id]);
|
|
}
|
|
if (id < 0)
|
|
if (! menu->text(id).isEmpty())
|
|
otherId = id;
|
|
}
|
|
}
|
|
|
|
// Update the "other" item text and checked state.
|
|
if (found) {
|
|
menu->changeItem(otherId, SmallIcon("devother"), i18n("Other..."));
|
|
menu->setItemChecked(otherId, false);
|
|
} else {
|
|
menu->changeItem(otherId, SmallIcon("devotheron"),
|
|
TQString(i18n("Other (%1)...")).arg(dev));
|
|
menu->setItemChecked(otherId, true);
|
|
}
|
|
}
|
|
|
|
void KNetLoad::updateDeviceMenus() {
|
|
for (TDEPopupMenu* menu = deviceMenus.first(); menu;
|
|
menu = deviceMenus.next())
|
|
updateDeviceMenu(menu);
|
|
}
|
|
|
|
void KNetLoad::updateScaleInMenu(TDEPopupMenu* menu) {
|
|
// Update the checked/unchecked states of menu items.
|
|
bool found = false;
|
|
int id;
|
|
int otherId = -1;
|
|
for (unsigned index = 0; index < menu->count(); index++) {
|
|
id = menu->idAt(index);
|
|
|
|
if (id == scaleIn) {
|
|
menu->setItemChecked(id, true);
|
|
found = true;
|
|
} else {
|
|
menu->setItemChecked(id, false);
|
|
if (id < 0)
|
|
if (! menu->text(id).isEmpty())
|
|
otherId = id;
|
|
}
|
|
}
|
|
|
|
// Update the "other" item text.
|
|
if (found)
|
|
menu->changeItem(otherId, i18n("Other..."));
|
|
else {
|
|
TQString text = i18n("Other (%1KBit/s)...").arg(int(((float) scaleIn) / 1000));
|
|
menu->changeItem(otherId, text);
|
|
}
|
|
|
|
// Check the "other" item if necessary.
|
|
if (! found)
|
|
menu->setItemChecked(otherId, true);
|
|
}
|
|
|
|
void KNetLoad::updateScaleInMenus() {
|
|
for (TDEPopupMenu* menu = scaleInMenus.first(); menu;
|
|
menu = scaleInMenus.next())
|
|
updateScaleInMenu(menu);
|
|
}
|
|
|
|
void KNetLoad::updateScaleOutMenu(TDEPopupMenu* menu) {
|
|
// Update the checked/unchecked states of menu items.
|
|
bool found = false;
|
|
int id;
|
|
int otherId = -1;
|
|
for (unsigned index = 0; index < menu->count(); index++) {
|
|
id = menu->idAt(index);
|
|
|
|
if (id == scaleOut) {
|
|
menu->setItemChecked(id, true);
|
|
found = true;
|
|
} else {
|
|
menu->setItemChecked(id, false);
|
|
if (id < 0)
|
|
if (! menu->text(id).isEmpty())
|
|
otherId = id;
|
|
}
|
|
}
|
|
|
|
// Update the "other" item text.
|
|
if (found)
|
|
menu->changeItem(otherId, i18n("Other..."));
|
|
else {
|
|
TQString text = i18n("Other (%1KBit/s)...").arg(int(((float) scaleOut) / 1000));
|
|
menu->changeItem(otherId, text);
|
|
}
|
|
|
|
// Check the "other" item if necessary.
|
|
if (! found)
|
|
menu->setItemChecked(otherId, true);
|
|
}
|
|
|
|
void KNetLoad::updateScaleOutMenus() {
|
|
for (TDEPopupMenu* menu = scaleOutMenus.first(); menu;
|
|
menu = scaleOutMenus.next())
|
|
updateScaleOutMenu(menu);
|
|
}
|
|
|
|
|
|
#include "knetload.moc"
|