/*************************************************************************** * * * 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 #include #include #include #include #include #include #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"