diff options
Diffstat (limited to 'kcontrol/info/memory.cpp')
-rw-r--r-- | kcontrol/info/memory.cpp | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/kcontrol/info/memory.cpp b/kcontrol/info/memory.cpp new file mode 100644 index 000000000..9743087dd --- /dev/null +++ b/kcontrol/info/memory.cpp @@ -0,0 +1,480 @@ +/* + * memory.cpp + * + * prints memory-information and shows a graphical display. + * + * Copyright (c) 1999-2002 Helge Deller <deller@gmx.de> + * + * 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. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + */ + +#include <sys/param.h> /* for BSD */ + +#include <qlayout.h> +#include <qpainter.h> +#include <qdrawutil.h> +#include <qtooltip.h> + +#include <kglobal.h> +#include <kdialog.h> +#include <kseparator.h> + +#include "memory.h" + +enum { /* entries for Memory_Info[] */ + TOTAL_MEM = 0, /* total physical memory (without swaps) */ + FREE_MEM, /* total free physical memory (without swaps) */ +#if !defined(__svr4__) || !defined(sun) +#if !defined(__NetBSD__) && !defined(__OpenBSD__) + SHARED_MEM, /* shared memory size */ + BUFFER_MEM, /* buffered memory size */ +#else + ACTIVE_MEM, + INACTIVE_MEM, +#endif +#endif + CACHED_MEM, /* cache memory size (located in ram) */ + SWAP_MEM, /* total size of all swap-partitions */ + FREESWAP_MEM, /* free memory in swap-partitions */ + MEM_LAST_ENTRY +}; + +/* + all update()-functions should put either + their results _OR_ the value NO_MEMORY_INFO into Memory_Info[] +*/ +static t_memsize Memory_Info[MEM_LAST_ENTRY]; + +#define MEMORY(x) ((t_memsize) (x)) /* it's easier... */ +#define NO_MEMORY_INFO MEMORY(-1) /* DO NOT CHANGE */ +#define ZERO_IF_NO_INFO(value) ((value) != NO_MEMORY_INFO ? (value) : 0) + + +/******************/ +/* Implementation */ +/******************/ + +static QLabel *MemSizeLabel[MEM_LAST_ENTRY][2]; + +enum { MEM_RAM_AND_HDD, MEM_RAM, MEM_HDD, MEM_LAST }; +static QWidget *Graph[MEM_LAST]; +static QLabel *GraphLabel[MEM_LAST]; + +#define SPACING 16 + +static QString formatted_unit(t_memsize value) +{ + if (value > (1024 * 1024)) + if (value > (1024 * 1024 * 1024)) + return i18n("%1 GB").arg(KGlobal::locale()->formatNumber(value / (1024 * 1024 * 1024.0), 2)); + else + return i18n("%1 MB").arg(KGlobal::locale()->formatNumber(value / (1024 * 1024.0), 2)); + else + return i18n("%1 KB").arg(KGlobal::locale()->formatNumber(value / 1024.0, 2)); +} + +KMemoryWidget::KMemoryWidget(QWidget * parent, const char *name) +: KCModule(parent, name) +{ + + KAboutData *about = + new KAboutData(I18N_NOOP("kcminfo"), + I18N_NOOP("KDE Panel Memory Information Control Module"), + 0, 0, KAboutData::License_GPL, + I18N_NOOP("(c) 1998 - 2002 Helge Deller")); + + about->addAuthor("Helge Deller", 0, "deller@gmx.de"); + setAboutData( about ); + + QString title, initial_str; + QLabel *Widget = 0; + int i, j; + + ram_colors_initialized = + swap_colors_initialized = + all_colors_initialized = false; + + setButtons(Help); + + /* default string for no Information... */ + Not_Available_Text = i18n("Not available."); + + QVBoxLayout *top = new QVBoxLayout(this, 0, KDialog::spacingHint()); + + QHBoxLayout *hbox = new QHBoxLayout(); + top->addLayout(hbox); + + /* stretch the left side */ + hbox->addStretch(); + + /* first create the Informationtext-Widget */ + QVBoxLayout *vbox = new QVBoxLayout(hbox, 0); + for (i = TOTAL_MEM; i < MEM_LAST_ENTRY; ++i) { + switch (i) { + case TOTAL_MEM: + title = i18n("Total physical memory:"); + break; + case FREE_MEM: + title = i18n("Free physical memory:"); + break; +#if !defined(__svr4__) || !defined(sun) +#if !defined(__NetBSD__) && !defined(__OpenBSD__) + case SHARED_MEM: + title = i18n("Shared memory:"); + break; + case BUFFER_MEM: + title = i18n("Disk buffers:"); + break; +#else + case ACTIVE_MEM: + title = i18n("Active memory:"); + break; + case INACTIVE_MEM: + title = i18n("Inactive memory:"); + break; +#endif +#endif + case CACHED_MEM: + title = i18n("Disk cache:"); + break; + case SWAP_MEM: + vbox->addSpacing(SPACING); + title = i18n("Total swap memory:"); + break; + case FREESWAP_MEM: + title = i18n("Free swap memory:"); + break; + default: + title = ""; + break; + }; + Widget = new QLabel(title, this); + Widget->setAlignment(AlignLeft); + vbox->addWidget(Widget, 1); + } + + /* then the memory-content-widgets */ + for (j = 0; j < 2; j++) { + vbox = new QVBoxLayout(hbox, 0); + for (i = TOTAL_MEM; i < MEM_LAST_ENTRY; ++i) { + if (i == SWAP_MEM) + vbox->addSpacing(SPACING); + Widget = new QLabel(this); + Widget->setAlignment(AlignRight); + MemSizeLabel[i][j] = Widget; + vbox->addWidget(Widget, 1); + } + } + + /* stretch the right side */ + hbox->addStretch(); + + KSeparator *line = new KSeparator(KSeparator::HLine, this); + top->addWidget(line); + + /* now the Graphics */ + QString hint; + hbox = new QHBoxLayout(top, 1); + for (i = MEM_RAM_AND_HDD; i < MEM_LAST; i++) { + hbox->addSpacing(SPACING); + vbox = new QVBoxLayout(hbox); + + switch (i) { + case MEM_RAM_AND_HDD: + title = i18n("Total Memory"); + hint = i18n("This graph gives you an overview of the " + "<b>total sum of physical and virtual memory</b> " + "in your system."); + break; + case MEM_RAM: + title = i18n("Physical Memory"); + hint = i18n("This graph gives you an overview of " + "the <b>usage of physical memory</b> in your system." + "<p>Most operating systems (including Linux) " + "will use as much of the available physical " + "memory as possible as disk cache, " + "to speed up the system performance. " + "<p>This means that if you have a small amount " + "of <b>Free Physical Memory</b> and a large amount of " + "<b>Disk Cache Memory</b>, your system is well " + "configured."); + break; + case MEM_HDD: + title = i18n("Swap Space"); + hint = i18n("The swap space is the <b>virtual memory</b> " + "available to the system. " + "<p>It will be used on demand and is provided " + "through one or more swap partitions and/or swap files."); + break; + default: + hint = title = QString::null; + break; + }; + + if (hint.length()) + hint = "<qt>" + hint + "</qt>"; + + Widget = new QLabel("<b>" + title + "</b>", this); + Widget->setAlignment(AlignCenter); + QToolTip::add(Widget, hint); + vbox->addWidget(Widget); + vbox->addSpacing(SPACING / 2); + + QWidget *g = new QWidget(this); + g->setMinimumWidth(2 * SPACING); + g->setMinimumHeight(3 * SPACING); + g->setBackgroundMode(NoBackground); + QToolTip::add(g, hint); // add the tooltip + Graph[i] = g; + vbox->addWidget(g, 2); + vbox->addSpacing(SPACING / 2); + + Widget = new QLabel(this); /* xx MB used. */ + Widget->setAlignment(AlignCenter); + QToolTip::add(Widget, hint); + GraphLabel[i] = Widget; + vbox->addWidget(Widget); + } + hbox->addSpacing(SPACING); + + timer = new QTimer(this); + timer->start(100); + QObject::connect(timer, SIGNAL(timeout()), this, + SLOT(update_Values())); + + update(); +} + +KMemoryWidget::~KMemoryWidget() +{ + /* stop the timer */ + timer->stop(); +} + + +QString KMemoryWidget::quickHelp() const +{ + return i18n("<h1>Memory Information</h1>" + " This display shows you the current memory usage of your system." + " The values are updated on a regular basis and give you an" + " overview of the physical and virtual used memory." ); +} + + +/* Graphical Memory Display */ +bool KMemoryWidget::Display_Graph(int widgetindex, + int count, + t_memsize total, + t_memsize * used, + QColor * color, + QString *text) +{ + QWidget *graph = Graph[widgetindex]; + int width = graph->width(); + int height = graph->height(); + QPixmap pm(width, height); + QPainter paint; + + paint.begin(&pm, this); + + QPen pen(QColor(0, 0, 0)); + + if (! ZERO_IF_NO_INFO(total)) { + paint.fillRect(1, 1, width - 2, height - 2, + QBrush(QColor(128, 128, 128))); + paint.setPen(pen); + paint.drawRect(graph->rect()); + GraphLabel[widgetindex]->setText(Not_Available_Text); + paint.end(); + bitBlt(graph, 0, 0, &pm); + return false; + } + + int startline = height-2; + int percent, localheight; + t_memsize last_used = 0; + + while (count--) { + last_used = *used; + +#ifdef HAVE_LONG_LONG + percent = (((long long)last_used) * 100) / total; +#else + /* prevent integer overflow with usage of double type */ + percent = (int) ((((double)last_used) * 100) / total); +#endif + + if (count) + localheight = ((height-2) * percent) / 100; + else + localheight = startline; + + if (localheight>0) { + paint.fillRect(1, startline, width-2, -localheight, *color); + + if (localheight >= SPACING) { + paint.drawText(0, startline-localheight, width, localheight, + AlignCenter | WordBreak, + QString("%1 %2%").arg(*text).arg(percent)); + } + } + + startline -= localheight; + + ++used; + ++color; + ++text; + } + + /* draw surrounding box */ + paint.setPen(pen); + QRect r = graph->rect(); + qDrawShadePanel(&paint, r.x(), r.y(), r.width(), r.height(), palette().active(), true, 1); + paint.end(); + bitBlt(graph, 0, 0, &pm); + + GraphLabel[widgetindex]->setText(i18n("%1 free").arg(formatted_unit(last_used))); + + return true; +} + +/* update_Values() is the main-loop for updating the Memory-Information */ +void KMemoryWidget::update_Values() +{ + int i; + bool ok1; + QLabel *label; + t_memsize used[5]; + + update(); /* get the Information from memory_linux, memory_fbsd */ + + /* update the byte-strings */ + for (i = TOTAL_MEM; i < MEM_LAST_ENTRY; i++) { + label = MemSizeLabel[i][0]; + if (Memory_Info[i] == NO_MEMORY_INFO) + label->clear(); + else + label->setText(i18n("%1 bytes ="). + arg(KGlobal::locale()-> + formatNumber(Memory_Info[i], 0))); + } + + /* update the MB-strings */ + for (i = TOTAL_MEM; i < MEM_LAST_ENTRY; i++) { + label = MemSizeLabel[i][1]; + label->setText((Memory_Info[i] != NO_MEMORY_INFO) + ? formatted_unit(Memory_Info[i]) + : Not_Available_Text); + } + + /* display graphical output (ram, hdd, at last: HDD+RAM) */ + /* be careful ! Maybe we have not all info available ! */ + + /* RAM usage: */ + /* don't rely on the SHARED_MEM value since it may refer to + * the size of the System V sharedmem in 2.4.x. Calculate instead! */ + + used[1] = 0; +#if !defined(__svr4__) || !defined(sun) +#if !defined(__NetBSD__) && !defined(__OpenBSD__) + used[1] = ZERO_IF_NO_INFO(Memory_Info[BUFFER_MEM]); +#endif +#endif + used[2] = ZERO_IF_NO_INFO(Memory_Info[CACHED_MEM]); + used[3] = ZERO_IF_NO_INFO(Memory_Info[FREE_MEM]); + used[0] = ZERO_IF_NO_INFO(Memory_Info[TOTAL_MEM]) - used[1] - used[2] - used[3]; + if (!ram_colors_initialized) { + ram_colors_initialized = true; + ram_text[0] = i18n("Application Data"); + ram_colors[0] = COLOR_USED_MEMORY; /* used+shared */ + ram_text[1] = i18n("Disk Buffers"); + ram_colors[1] = QColor(24,131,5); /* buffer */ + ram_text[2] = i18n("Disk Cache"); + ram_colors[2] = QColor(33,180,7); /* cached */ + ram_text[3] = i18n("Free Physical Memory"); + ram_colors[3] = COLOR_FREE_MEMORY; /* free */ + } + ok1 = Display_Graph(MEM_RAM, 4, Memory_Info[TOTAL_MEM], + used, ram_colors, ram_text); + + /* SWAP usage: */ + used[1] = ZERO_IF_NO_INFO(Memory_Info[FREESWAP_MEM]); + used[0] = ZERO_IF_NO_INFO(Memory_Info[SWAP_MEM]) - used[1]; + if (!swap_colors_initialized) { + swap_colors_initialized = true; + swap_text[0] = i18n("Used Swap"); + swap_colors[0] = COLOR_USED_SWAP; /* used */ + swap_text[1] = i18n("Free Swap"); + swap_colors[1] = COLOR_FREE_MEMORY; /* free */ + } + Display_Graph(MEM_HDD, 2, Memory_Info[SWAP_MEM], + used, swap_colors, swap_text); + + /* RAM + SWAP usage: */ + if (Memory_Info[SWAP_MEM] == NO_MEMORY_INFO || + Memory_Info[FREESWAP_MEM] == NO_MEMORY_INFO) + Memory_Info[SWAP_MEM] = Memory_Info[FREESWAP_MEM] = 0; + + used[1] = Memory_Info[SWAP_MEM] - Memory_Info[FREESWAP_MEM]; + used[2] = Memory_Info[FREE_MEM] + Memory_Info[FREESWAP_MEM]; + used[0] = (Memory_Info[TOTAL_MEM]+Memory_Info[SWAP_MEM])-used[1]-used[2]; + if (!all_colors_initialized) { + all_colors_initialized = true; + all_text[0] = i18n("Used Physical Memory"); + all_colors[0] = COLOR_USED_MEMORY; /* used ram */ + all_text[1] = i18n("Used Swap"); + all_colors[1] = COLOR_USED_SWAP; /* used swap */ + all_text[2] = i18n("Total Free Memory"); + all_colors[2] = COLOR_FREE_MEMORY; /* free ram+swap*/ + } + Display_Graph(MEM_RAM_AND_HDD, 3, + ok1 ? Memory_Info[TOTAL_MEM] + Memory_Info[SWAP_MEM] + : NO_MEMORY_INFO, + used, all_colors, all_text); +} + + +/* Include system-specific code */ + +#ifdef __linux__ +#include "memory_linux.cpp" +#elif defined(__APPLE__) +#include "memory_osx.cpp" +#elif defined(sgi) && sgi +#include "memory_sgi.cpp" +#elif defined(__svr4__) && defined(sun) +#include "memory_solaris.cpp" +#elif defined(__FreeBSD__) || defined(__DragonFly__) +#include "memory_fbsd.cpp" +#elif defined(__hpux) +#include "memory_hpux.cpp" +#elif defined(__NetBSD__) || defined(__OpenBSD__) +#include "memory_netbsd.cpp" +#elif __osf__ +#include "memory_tru64.cpp" +#else + +/* Default for unsupported systems */ +void KMemoryWidget::update() +{ + int i; + for (i = TOTAL_MEM; i < MEM_LAST_ENTRY; ++i) + Memory_Info[i] = NO_MEMORY_INFO; +} + +#endif +#include "memory.moc" |