-
Notifications
You must be signed in to change notification settings - Fork 638
CPU/GPU/RAM Viewer new applet #8261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c188f04
ed6ff53
9eb8030
6216e15
3cb3446
408ba8b
3b36b92
eaf5e4c
1ebbc97
bd8a1a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # CPU/GPU/RAM Viewer | ||
|
|
||
| A minimalist, text-based system resource monitor for the Cinnamon Desktop Environment. | ||
|
|
||
| This applet displays real-time usage percentages for CPU, GPU, and RAM directly on your panel. It is designed to be lightweight, unobtrusive, and dynamic. | ||
|
|
||
| ## Features | ||
|
|
||
| * **Minimalist Design:** Text-only display (e.g., `CPU %15 • GPU %30 • RAM %40`). | ||
| * **Dynamic Resizing:** The applet grows or shrinks based on the text length (no fixed width). | ||
| * **Auto-Detect GPU:** | ||
| * **NVIDIA:** Uses `nvidia-smi` automatically if installed. | ||
| * **AMD:** Reads directly from system files (`/sys/class/drm/...`). | ||
| * **Intel/No GPU:** Automatically hides the GPU section if no dedicated GPU is detected. | ||
| * **One-Click Monitor:** Left-clicking the applet opens `gnome-system-monitor` directly to the **Resources** tab. | ||
| * **Native Behavior:** Fully supports right-click context menus and panel edit mode (drag & drop). | ||
|
|
||
| ## Requirements | ||
|
|
||
| * **Cinnamon Desktop Environment** | ||
| * `gnome-system-monitor` (For the click action) | ||
| * `nvidia-smi` (Optional: Only required for NVIDIA GPU monitoring) | ||
|
|
||
| ## Installation | ||
|
|
||
| 1. Download or clone this repository. | ||
| 2. Copy the folder to your local Cinnamon applets directory: | ||
| ```bash | ||
| cp -r cpugpuram-viewer@lyk4s5 ~/.local/share/cinnamon/applets/ | ||
| ``` | ||
| 3. Right-click on your Cinnamon panel -> **Applets**. | ||
| 4. Find **CPU/GPU/RAM Viewer** in the *Manage* tab and add it to your panel. | ||
|
|
||
| ## Usage | ||
|
|
||
| * **Left Click:** Opens System Monitor (Resources tab). | ||
| * **Right Click:** Opens the standard applet context menu (About, Remove, etc.). | ||
|
|
||
| ## License | ||
|
|
||
| 1. Distributed under the MIT License. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,157 @@ | ||||||||||||||||||||
| const Applet = imports.ui.applet; | ||||||||||||||||||||
| const GLib = imports.gi.GLib; | ||||||||||||||||||||
| const Util = imports.misc.util; | ||||||||||||||||||||
| const Mainloop = imports.mainloop; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| class CinnamonApplet extends Applet.TextApplet { | ||||||||||||||||||||
| constructor(metadata, orientation, panel_height, instance_id) { | ||||||||||||||||||||
| super(orientation, panel_height, instance_id); | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
|
||||||||||||||||||||
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The metadata parameter is passed to the constructor but never used. While it's part of the standard Cinnamon applet signature, consider either using it (e.g., for setting the icon path like in rssdock@lyk4s5) or documenting why it's not needed. If the applet grows and needs to access metadata.path or other properties, they won't be available without storing the metadata parameter.
| // Store metadata for potential future use (e.g., icon paths, configuration). | |
| this._metadata = metadata; |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's trailing whitespace on this empty line that should be removed for code cleanliness.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The applet launches gnome-system-monitor with the -r flag, but this flag may not be recognized by all versions of gnome-system-monitor. Some versions may not support this flag or it might have been deprecated. Consider checking if the program exists before launching it, and handle potential errors gracefully. Look at cpu-monitor-text@gnemonix/files/cpu-monitor-text@gnemonix/applet.js:105-116 for a more robust approach using Cinnamon.AppSystem to launch the system monitor.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is in Turkish ("2 saniyede bir güncelle" means "update every 2 seconds"). All code comments should be in English for consistency with the rest of the codebase and to ensure maintainability for international contributors.
| // 2 saniyede bir güncelle | |
| // Update every 2 seconds |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updateLoop recursively calls itself, creating a new function context each time. While this works, it's less efficient than using a repeating timeout pattern. Consider changing line 54 to return true at the end of updateMetrics(), and modify updateLoop to use: this._updateLoopID = Mainloop.timeout_add_seconds(2, Lang.bind(this, this.updateMetrics)); This approach is more memory-efficient and is the pattern used in other applets like cpu-monitor-text@gnemonix.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updateLoop method creates an infinite recursion pattern that doesn't properly manage the timeout ID. This can lead to memory leaks because there's no way to clean up the timeout when the applet is removed from the panel. The timeout ID should be stored (e.g., this._updateLoopID) and removed in an on_applet_removed_from_panel callback using Mainloop.source_remove(). Look at cpu-monitor-text@gnemonix/files/cpu-monitor-text@gnemonix/applet.js:64-66 for an example of proper cleanup.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message label "Hata" is in Turkish. Error messages should be in English for consistency with the rest of the codebase and to ensure accessibility for international users. Consider changing this to "Error" or using a more descriptive error message.
| this.set_applet_label("Hata"); | |
| this.set_applet_label("Error"); |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getGpuUsage method spawns a synchronous command (nvidia-smi) which can block the UI thread if the command takes time to execute. While this is typically fast, consider that on some systems or under heavy load, this could cause UI stuttering. The current implementation is acceptable for a 2-second update interval, but if users want faster updates, this could become problematic. Consider documenting this limitation or using async command execution if performance becomes an issue.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getCpuUsage function will return 0 on the first call because prevIdle and prevTotal are initialized to 0. When diffTotal is calculated on the first run, it will be non-zero, but the usage calculation will be based on the delta from 0, which may give an inaccurate initial reading. Consider either initializing these values properly in the constructor by reading /proc/stat once, or handling the first call specially to avoid showing misleading data.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing cleanup callback for applet removal. The applet should implement on_applet_removed_from_panel to properly clean up the update loop timeout and prevent memory leaks when the applet is removed from the panel. This is a standard pattern in Cinnamon applets as seen in cpu-monitor-text@gnemonix/files/cpu-monitor-text@gnemonix/applet.js:63-68.
| } | |
| } | |
| on_applet_removed_from_panel() { | |
| if (this._updateLoopTimeoutId) { | |
| Mainloop.source_remove(this._updateLoopTimeoutId); | |
| this._updateLoopTimeoutId = null; | |
| } | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,6 @@ | ||||||||||||||||||
| { | ||||||||||||||||||
| "uuid": "cpugpuram-viewer@lyk4s5", | ||||||||||||||||||
| "name": "CPU/GPU/RAM Viewer", | ||||||||||||||||||
| "description": "Minimalist system monitor for CPU, GPU, and RAM usage.", | ||||||||||||||||||
| "version": "1.0" | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+5
to
+6
|
||||||||||||||||||
| "version": "1.0" | |
| } | |
| "version": "1.0", | |
| "max-instances": -1, | |
| "icon": "icon" | |
| } |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's trailing whitespace at the end of this line. This should be removed for code cleanliness and consistency.
| } | |
| } |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,5 @@ | ||||
|
|
||||
|
||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -39,8 +39,8 @@ MyApplet.prototype = { | |||||||||||||||
| this._tickerLoop(); | ||||||||||||||||
| this._setWidth(); | ||||||||||||||||
|
|
||||||||||||||||
| // refresh every X seconds | ||||||||||||||||
| this._refreshLoop = Mainloop.timeout_add_seconds(this.update_interval * 60, Lang.bind(this, this._updateFeed)); | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
|
Comment on lines
+42
to
+43
|
||||||||||||||||
| }, | ||||||||||||||||
|
|
||||||||||||||||
| _setupSettings: function () { | ||||||||||||||||
|
|
@@ -80,11 +80,13 @@ MyApplet.prototype = { | |||||||||||||||
|
|
||||||||||||||||
| _updateFeed: function () { | ||||||||||||||||
| // Collect news from all sources | ||||||||||||||||
| if (this._refreshLoop) Mainloop.source_remove(this._refreshLoop); | ||||||||||||||||
| this._allNews = []; | ||||||||||||||||
| let sources = this.news_sources || []; | ||||||||||||||||
| if (!sources.length) { | ||||||||||||||||
| this._tickerText = _("No RSS source configured"); | ||||||||||||||||
| this._buildMenu(); | ||||||||||||||||
| this._refreshLoop = Mainloop.timeout_add_seconds(60, Lang.bind(this, this._updateFeed)); | ||||||||||||||||
|
||||||||||||||||
| this._refreshLoop = Mainloop.timeout_add_seconds(60, Lang.bind(this, this._updateFeed)); | |
| this._refreshLoop = Mainloop.timeout_add_seconds(Math.max(1, this.update_interval) * 60, Lang.bind(this, this._updateFeed)); |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's trailing whitespace on this line that should be removed for code cleanliness.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When _updateFeed is called asynchronously (e.g., when settings change via bindProperty or from a timeout callback), multiple instances of the async fetch operations could overlap. The code now removes the previous timeout at the start (line 83), but if _updateFeed is called before the previous async operations complete, there could be multiple concurrent fetch operations running. This could lead to race conditions where the _allNews array is overwritten or _buildMenu is called multiple times. Consider adding a flag to prevent concurrent updates or ensuring only one update can run at a time.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's inconsistent indentation here. The line uses spaces for indentation while the rest of the code appears to use consistent spacing. This should match the indentation style of the surrounding code.
| let interval = Math.max(1, this.update_interval) * 60; | |
| let interval = Math.max(1, this.update_interval) * 60; |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Math.max(1, this.update_interval) ensures a minimum interval of 1 minute, which is good defensive programming. However, the original code at line 42-43 that was removed didn't have this protection. Consider documenting this change in the commit message or adding a comment explaining why the minimum is necessary to prevent excessive API calls or resource usage.
| // refresh every X seconds | |
| let interval = Math.max(1, this.update_interval) * 60; | |
| // refresh every X seconds; enforce a minimum of 1 minute between updates | |
| // to avoid excessive polling / API calls even if update_interval is misconfigured | |
| let interval = Math.max(1, this.update_interval) * 60; |
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR is titled "CPU/GPU/RAM Viewer new applet" and described as adding "A minimalist and high-performance applet to monitor CPU, GPU, and RAM usage". However, this PR also includes unrelated changes to the rssdock@lyk4s5 applet (RSS feed refresh loop modifications). These changes should either be in a separate PR or the PR description should mention both changes. This makes it harder to review and understand the scope of changes.
Copilot
AI
Feb 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The added code removes any existing refresh loop at the start of _updateFeed. However, this removal happens before checking if there are any news sources configured. If _updateFeed is called when there are no sources, it schedules a new refresh loop (line 89) but the old one was already removed (line 83). This is correct behavior, but consider that if _updateFeed fails or throws an exception before line 136, there will be no refresh loop scheduled. Add error handling to ensure the refresh loop is always rescheduled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the README, there's inconsistent indentation and formatting in the numbered list. Line 41 uses a tab character for indentation while other list items use consistent spacing. This should be standardized to use consistent indentation (either spaces or tabs, but not mixed).