The idea was simple: the computer is busy, and we would like to know whether it is doing a lot of work or merely sounding important. Our JM CPU RAM NET plugin puts a CPU graph, memory and network readings in the panel, with a system monitor one click away. Here is how it fits together. A portable source release is waiting at the bottom.
1. Decide what earns a place in the panel
The original widget fits into 118 pixels: a CPU label, a sixteen-segment gauge, R for memory and N for network activity. Not much room, but we are building a panel widget, not a cinema. Hover for details and left-click to open a system monitor. These are facts from the existing source code, not measurements of its own CPU overhead.
2. Separate data collection from drawing
The original project contains a C++ file with the widget and plugin classes, a .desktop file describing it to the panel, and a helper script for memory and network data. The widget derives from QWidget, the plugin from ILXQtPanelPlugin, and its factory implements ILXQtPanelPluginLibrary. Qt metadata identifies the library to the panel.
Start with a widget that shows fixed text. Even “it works” will do — at this stage, that is genuinely useful news. Once the panel loads it, add the readings. That way you will not confuse a registration problem with a calculation that has gone wandering.
3. Calculate CPU load between two readings
The first line of /proc/stat contains CPU time counters since startup. It is not a ready-made current-load percentage. Take two readings: remember the first, then calculate the change at the next update. Now you can tell what happened between those two glances.
quint64 idleAll = idle + iowait;
quint64 nonIdle = user + nice + system + irq + softirq + steal;
quint64 total = idleAll + nonIdle;
// Compare these counters with the previous reading.
// CPU% = 100 * (deltaTotal - deltaIdle) / deltaTotal;This convention treats idle plus iowait as idle time and calculates aggregate load, rather than separate CPU cores. The first sample establishes a baseline. Do not add guest and guest_nice again: those times are already included in user and nice. The kernel documentation explains the limits of iowait accounting; it is not a precise waiting-time measurement for an individual process.
4. Memory: use MemAvailable, not just MemFree
RAM can look busy because Linux also uses it for cache. We read MemTotal and MemAvailable from /proc/meminfo and calculate 100 × (MemTotal − MemAvailable) / MemTotal. MemAvailable estimates what applications can use without swapping. No need to sound the alarm just because the system is keeping something useful handy.
Handle missing fields and division by zero. If a reading fails, show “unavailable”. A made-up 0% looks reassuring, but our computer does not need creative accounting.
5. Network throughput is not a link percentage
Read received and transmitted byte counters from /proc/net/dev, calculate their change and divide by the elapsed time. That gives B/s: bytes per second. Need bits per second instead? Multiply by eight. One small letter, one rather noticeable difference.
The original helper sums active interfaces, excluding lo and selected virtual interfaces. IFACE names the first match, which may not describe the whole total. Add a VPN and several adapters and you can end up asking where all that traffic came from. The downloadable release reads one interface and lets you select it explicitly.
N is a custom activity scale, not a percentage of the connection’s available bandwidth. For example, 50 to less than 100 KiB/s maps to N62. That does not mean 62% of the link is busy. This is not a tiny Internet speedometer; the downloadable version puts actual RX and TX rates in KiB/s in its tooltip.
6. Refresh without holding up the panel
The original plugin updates once per second: frequent enough for a quick glance, without turning the panel into a nervous light show.
QTimer *timer = new QTimer(mWidget);
QObject::connect(timer, &QTimer::timeout, mWidget, [this]() {
if (mWidget) mWidget->updateStats();
});
timer->start(1000);The original C++ version launches a helper with QProcess and waits up to 800 ms. The panel should not have to wait for it like a late bus: a long wait in the interface thread can make things sluggish. Asynchronous QProcess signals are one option. In release 1.0.0, we read the small /proc files directly instead. If you use a helper process, do not start another measurement while the previous one is still running.
7. Add colours, a tooltip and a click action
QPainter draws the CPU gauge, changing colour as load rises. Memory has its own thresholds. Keep letters and numbers too: colour should help, not turn the widget into a shade-recognition exam. Use the tooltip to explain the readings.
A click tries installed system monitors, starting with qps. No administrator privileges needed: we want to look at the numbers, not take command of the machine. If you use a helper, resolve its path from the home directory or settings. Hard-code your own folder and “works on my machine” becomes a little too literal.
8. Build for your version of the panel
You need a C++ compiler, Qt tools including moc, headers for the installed panel and matching LXQt libraries. The .desktop file supplies the displayed name and an X-LXQt-Module value matching the library name. Use the interface appropriate for your installed LXQt version. A compiled .so file is not a universal plugin for every installation.
Back up the panel configuration before making changes. Build and install your library, then add the widget in the panel settings. Do not replace a working plugin with a library built for a different Qt version. A backup makes for a much nicer evening than “where has my panel gone?”.
What should you check before daily use?
- Idle readings and readings during application activity.
- Disconnected networking, adapter changes, VPNs and counters resetting.
- Helper failures or unexpectedly long execution.
- A different panel height or display scaling.
- Whether clicking opens an installed system monitor.
This is a real project, but we are not inventing impressive performance numbers for it. We have not measured its overhead or verified installation on every distribution. The source release’s checks are listed below. Give your own build a proper try in everyday use before awarding it a permanent spot beside the clock.
Documentation
LXQt panel · Plugin interface · The /proc filesystem. Example: our JM CPU RAM NET project.
Download the source project
MIERZWA Panel Monitor 1.0.0 is a portable version derived from the original described above. It has its own module name and a 190-pixel widget. It reads system counters directly, without the original helper process or its wait. N remains an activity scale; RX/TX rates are available in the tooltip.
Download source ZIP · 1.0.0 · 14.7 KiB ↗Includes C++ sources, Makefile, checks, MIT license and English/Polish build, installation and removal instructions. Tested on Arch Linux with LXQt Panel 2.4.1 and Qt 6.11.2. No binaries are included. Existing panel modules are not overwritten. Other distributions need separate verification.
Build and check
clear
make -j2
make checkInstallation in the checked Arch Linux layout
clear
sudo make install LIBDIR=/usr/lib DATADIR=/usr/shareRemoval after removing the widget from the panel
clear
sudo python3 uninstall.py --libdir /usr/lib --datadir /usr/shareRun these commands from the extracted project directory. Read README first and back up panel.conf. The build and offscreen checks passed; extended daily use in a live panel has not been measured.
SHA-256ec47bf34555256f9bcffaaf8520d399491684bb313e2b36bdd3cf58ed3219251