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.
knetload/knetload/knetload.cpp

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 <tdeaction.h>
#include <tdeconfig.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdepopupmenu.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, TQ_SIGNAL(activated(int)), this, TQ_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, TQ_SIGNAL(activated(int)), this, TQ_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, TQ_SIGNAL(activated(int)), this, TQ_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"