Skip to content

Commit 6c5958a

Browse files
systemTemperature@KopfdesDaemons: Version 1.1.0 (#1782)
* refactor * async file loading * refactor set style functions * settings clean up * scale size setting, decoration toggle setting * organize settings in tabs and sections * translation * revert changes in wrong desklet folders * update version order in `CHANGELOG.md`
1 parent b812a53 commit 6c5958a

16 files changed

Lines changed: 660 additions & 387 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Changelog
2+
3+
## [1.1.0] 04.04.2026
4+
5+
- Features
6+
- Added scaling setting based on system font size
7+
- Added decoration toggle setting
8+
- Refactoring
9+
- Async file loading by `load_contents_async`
10+
- Removed hard-coded locale path
11+
- Removed `settings.getValue()`function in constructor (use binding)
12+
- Renamed properties and functions
13+
- Switched desklet entry to `on_desklet_added_to_desktop`
14+
- Removed `stylesheet.css`
15+
- Removed unused imports
16+
- Added settings cleanup
17+
- Kebab-case for setting names
18+
- Organize setting in tabs and sections
19+
20+
## [1.0.0] 09.11.2024
21+
22+
- Initial release
Lines changed: 195 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,195 @@
1-
const Desklet = imports.ui.desklet;
2-
const Lang = imports.lang;
3-
const St = imports.gi.St;
4-
const Mainloop = imports.mainloop;
5-
const GLib = imports.gi.GLib;
6-
const Settings = imports.ui.settings;
7-
const Gettext = imports.gettext;
8-
9-
const UUID = "systemTemperature@KopfDesDaemons";
10-
11-
Gettext.bindtextdomain(UUID, GLib.get_home_dir() + "/.local/share/locale");
12-
13-
function _(str) {
14-
return Gettext.dgettext(UUID, str);
15-
}
16-
17-
function MyDesklet(metadata, deskletId) {
18-
this._init(metadata, deskletId);
19-
}
20-
21-
MyDesklet.prototype = {
22-
__proto__: Desklet.Desklet.prototype,
23-
24-
_init: function (metadata, deskletId) {
25-
Desklet.Desklet.prototype._init.call(this, metadata, deskletId);
26-
27-
this.setHeader(_("System Temperature"));
28-
29-
// Initialize settings
30-
this.settings = new Settings.DeskletSettings(this, this.metadata["uuid"], deskletId);
31-
32-
// Get settings
33-
this.initialLabelText = this.settings.getValue("labelText") || "CPU temperature:";
34-
this.tempFilePath = this.settings.getValue("tempFilePath") || "/sys/class/thermal/thermal_zone2/temp";
35-
this.fontSizeLabel = this.settings.getValue("fontSizeLabel") || 12;
36-
this.fontSizeTemperature = this.settings.getValue("fontSizeTemperature") || 20;
37-
this.dynamicColorEnabled = this.settings.getValue("dynamicColorEnabled") || true;
38-
this.temperatureUnit = this.settings.getValue("temperatureUnit") || "C";
39-
this.updateInterval = this.settings.getValue("updateInterval") || 1;
40-
41-
// Bind settings properties
42-
const boundSettings = [
43-
"tempFilePath",
44-
"labelText",
45-
"temperatureUnit",
46-
"updateInterval",
47-
"fontSizeLabel",
48-
"fontSizeTemperature",
49-
"dynamicColorEnabled"
50-
];
51-
boundSettings.forEach(setting => {
52-
this.settings.bindProperty(Settings.BindingDirection.IN, setting, setting, this.on_settings_changed, null);
53-
});
54-
55-
// Create label for the static text
56-
this.label = new St.Label({ text: this.initialLabelText, y_align: St.Align.START, style_class: "label-text" });
57-
this.label.set_style(`font-size: ${this.fontSizeLabel}px;`);
58-
59-
// Create label for the temperature value
60-
this.temperatureLabel = new St.Label({ text: "Loading...", style_class: "temperature-label" });
61-
this.temperatureLabel.set_style(`font-size: ${this.fontSizeTemperature}px;`);
62-
63-
// Set up the layout
64-
this.box = new St.BoxLayout({ vertical: true });
65-
this.box.add_child(this.label);
66-
this.box.add_child(this.temperatureLabel);
67-
this.setContent(this.box);
68-
69-
this._timeout = null;
70-
71-
// Start the temperature update loop
72-
this.updateTemperature();
73-
},
74-
75-
updateTemperature: function () {
76-
try {
77-
// Get CPU temperature
78-
const [result, out] = GLib.spawn_command_line_sync(`cat ${this.tempFilePath}`);
79-
80-
if (!result || out === null) {
81-
throw new Error("Could not retrieve CPU temperature.");
82-
}
83-
84-
// Convert temperature from millidegree Celsius to degree Celsius
85-
let temperature = parseFloat(out.toString().trim()) / 1000.0;
86-
if (this.temperatureUnit === "F") {
87-
temperature = (temperature * 9 / 5) + 32;
88-
}
89-
90-
// Update temperature text with the chosen unit
91-
const temperatureText = `${temperature.toFixed(1)}°${this.temperatureUnit}`;
92-
this.temperatureLabel.set_text(temperatureText);
93-
94-
// Set color based on temperature if dynamic color is enabled, else set default color
95-
if (this.dynamicColorEnabled) {
96-
this.updateLabelColor(temperature);
97-
} else {
98-
this.temperatureLabel.set_style(`color: #ffffff; font-size: ${this.fontSizeTemperature}px;`);
99-
}
100-
101-
} catch (e) {
102-
this.temperatureLabel.set_text("Error");
103-
global.logError(`Error in updateTemperature: ${e.message}`);
104-
}
105-
106-
// Reset and set up the interval timeout
107-
if (this._timeout) Mainloop.source_remove(this._timeout);
108-
this._timeout = Mainloop.timeout_add_seconds(this.updateInterval, () => this.updateTemperature());
109-
},
110-
111-
updateLabelColor: function (temperature) {
112-
// Define min and max temperature thresholds based on the unit
113-
let minTemp = 20, maxTemp = 90;
114-
115-
// Convert min and max temperature from degree Celsius to degree Fahrenheit
116-
if (this.temperatureUnit === "F") {
117-
minTemp = (minTemp * 9 / 5) + 32;
118-
maxTemp = (maxTemp * 9 / 5) + 32;
119-
}
120-
121-
// Calculate color based on temperature
122-
temperature = Math.min(maxTemp, Math.max(minTemp, temperature));
123-
const ratio = (temperature - minTemp) / (maxTemp - minTemp);
124-
let color = `rgb(${Math.floor(ratio * 255)}, ${Math.floor((1 - ratio) * 255)}, 0)`;
125-
126-
// Set the color
127-
this.temperatureLabel.set_style(`color: ${color}; font-size: ${this.fontSizeTemperature}px;`);
128-
},
129-
130-
on_settings_changed: function () {
131-
// Update the label text and styles when the settings change
132-
if (this.label && this.labelText) {
133-
this.label.set_text(this.labelText);
134-
this.label.set_style(`font-size: ${this.fontSizeLabel}px;`);
135-
}
136-
137-
if (this.temperatureLabel) {
138-
this.temperatureLabel.set_style(`font-size: ${this.fontSizeTemperature}px;`);
139-
}
140-
},
141-
142-
on_desklet_removed: function () {
143-
if (this._timeout) Mainloop.source_remove(this._timeout);
144-
if (this.label) this.box.remove_child(this.label);
145-
if (this.temperatureLabel) this.box.remove_child(this.temperatureLabel);
146-
147-
this.label = this.temperatureLabel = this._timeout = null;
148-
}
149-
};
150-
151-
function main(metadata, deskletId) {
152-
return new MyDesklet(metadata, deskletId);
153-
}
1+
const Desklet = imports.ui.desklet;
2+
const St = imports.gi.St;
3+
const Mainloop = imports.mainloop;
4+
const GLib = imports.gi.GLib;
5+
const Settings = imports.ui.settings;
6+
const Gettext = imports.gettext;
7+
const Gio = imports.gi.Gio;
8+
9+
const UUID = "systemTemperature@KopfDesDaemons";
10+
11+
Gettext.bindtextdomain(UUID, GLib.get_user_data_dir() + "/locale");
12+
13+
function _(str) {
14+
return Gettext.dgettext(UUID, str);
15+
}
16+
17+
class MyDesklet extends Desklet.Desklet {
18+
constructor(metadata, deskletId) {
19+
super(metadata, deskletId);
20+
this.setHeader(_("System Temperature"));
21+
22+
this._mainContainer = null;
23+
this._textLabel = null;
24+
this._refreshTimeoutId = null;
25+
this._temperatureLabel = null;
26+
this._colorString = null;
27+
this._isReloading = false;
28+
29+
// Default settings
30+
this.scaleSize = 1;
31+
this.hideDecorations = false;
32+
this.labelText = "CPU temperature:";
33+
this.tempFilePath = "/sys/class/thermal/thermal_zone2/temp";
34+
this.textLabelFontSize = 12;
35+
this.temperatureLabelFontSize = 20;
36+
this.dynamicColorEnabled = true;
37+
this.temperatureUnit = "C";
38+
this.updateInterval = 1;
39+
40+
// Bind settings properties
41+
this.settings = new Settings.DeskletSettings(this, this.metadata["uuid"], deskletId);
42+
this.settings.bindProperty(Settings.BindingDirection.IN, "scale-size", "scaleSize", this._on_settings_changed);
43+
this.settings.bindProperty(Settings.BindingDirection.IN, "hide-decorations", "hideDecorations", this._onDecorationChanged);
44+
this.settings.bindProperty(Settings.BindingDirection.IN, "temp-file-path", "tempFilePath", this._on_settings_changed);
45+
this.settings.bindProperty(Settings.BindingDirection.IN, "label-text", "labelText", this._on_settings_changed);
46+
this.settings.bindProperty(Settings.BindingDirection.IN, "temperature-unit", "temperatureUnit", this._on_settings_changed);
47+
this.settings.bindProperty(Settings.BindingDirection.IN, "update-interval", "updateInterval", this._setRefreshTimeout);
48+
this.settings.bindProperty(Settings.BindingDirection.IN, "font-size-label", "textLabelFontSize", this._on_settings_changed);
49+
this.settings.bindProperty(Settings.BindingDirection.IN, "font-size-temperature", "temperatureLabelFontSize", this._on_settings_changed);
50+
this.settings.bindProperty(Settings.BindingDirection.IN, "dynamic-color-enabled", "dynamicColorEnabled", this._on_settings_changed);
51+
}
52+
53+
on_desklet_added_to_desktop() {
54+
this._setupLayout();
55+
this._onDecorationChanged();
56+
this._updateTemperature();
57+
this._setRefreshTimeout();
58+
}
59+
60+
on_desklet_removed() {
61+
if (this._refreshTimeoutId) {
62+
Mainloop.source_remove(this._refreshTimeoutId);
63+
this._refreshTimeoutId = null;
64+
}
65+
if (this.settings && !this._isReloading) {
66+
this.settings.finalize();
67+
}
68+
}
69+
70+
on_desklet_reloaded() {
71+
this._isReloading = true;
72+
}
73+
74+
_updateStyles() {
75+
const fontSize = size => `${(size * this.scaleSize) / 10}em`;
76+
this._textLabel.set_style(`font-size: ${fontSize(this.textLabelFontSize)};`);
77+
78+
let tempLabelStyle = `font-size: ${fontSize(this.temperatureLabelFontSize)}; font-weight: bold;`;
79+
if (this._colorString) tempLabelStyle += ` color: ${this._colorString};`;
80+
this._temperatureLabel.set_style(tempLabelStyle);
81+
}
82+
83+
_onDecorationChanged() {
84+
this.metadata["prevent-decorations"] = this.hideDecorations;
85+
this._updateDecoration();
86+
}
87+
88+
_setupLayout() {
89+
// Text label
90+
this._textLabel = new St.Label({ text: this.labelText });
91+
92+
// Temperature label
93+
this._temperatureLabel = new St.Label({ text: "Loading..." });
94+
95+
this._updateStyles();
96+
97+
// Set up the layout
98+
this._mainContainer = new St.BoxLayout({ vertical: true });
99+
this._mainContainer.add_child(this._textLabel);
100+
this._mainContainer.add_child(this._temperatureLabel);
101+
102+
this.setContent(this._mainContainer);
103+
}
104+
105+
_setRefreshTimeout() {
106+
if (this._refreshTimeoutId) {
107+
Mainloop.source_remove(this._refreshTimeoutId);
108+
this._refreshTimeoutId = null;
109+
}
110+
111+
this._refreshTimeoutId = Mainloop.timeout_add_seconds(this.updateInterval, () => {
112+
this._updateTemperature();
113+
return true;
114+
});
115+
}
116+
117+
getFileContent(path) {
118+
return new Promise((resolve, reject) => {
119+
const file = Gio.File.new_for_path(path);
120+
file.load_contents_async(null, (obj, res) => {
121+
try {
122+
const [success, content] = obj.load_contents_finish(res);
123+
if (success) {
124+
resolve(content);
125+
} else {
126+
reject(new Error(`Could not read ${path}`));
127+
}
128+
} catch (e) {
129+
reject(e);
130+
}
131+
});
132+
});
133+
}
134+
135+
async _updateTemperature() {
136+
try {
137+
// Get CPU temperature
138+
const fileContent = await this.getFileContent(this.tempFilePath);
139+
140+
// Convert temperature from millidegree Celsius to degree Celsius
141+
let temperature = parseFloat(fileContent.toString().trim()) / 1000.0;
142+
143+
// Convert to Fahrenheit when the user has selected that unit
144+
if (this.temperatureUnit === "F") {
145+
temperature = (temperature * 9) / 5 + 32;
146+
}
147+
148+
// Update temperature text with the chosen unit
149+
const temperatureText = `${temperature.toFixed(1)}°${this.temperatureUnit}`;
150+
this._temperatureLabel.set_text(temperatureText);
151+
152+
// Set color based on temperature if dynamic color is enabled, else set default color
153+
if (this.dynamicColorEnabled) {
154+
this._updateLabelColor(temperature);
155+
} else {
156+
this._colorString = "#ffffff";
157+
this._updateStyles();
158+
}
159+
} catch (e) {
160+
this._temperatureLabel.set_text("Error");
161+
global.logError(`${UUID}: Error while reading temperature: ${e.message}`);
162+
}
163+
}
164+
165+
_updateLabelColor(temperature) {
166+
// Define min and max temperature thresholds based on the unit
167+
let minTemp = 20;
168+
let maxTemp = 90;
169+
170+
// Convert min and max temperature from degree Celsius to degree Fahrenheit
171+
if (this.temperatureUnit === "F") {
172+
minTemp = (minTemp * 9) / 5 + 32;
173+
maxTemp = (maxTemp * 9) / 5 + 32;
174+
}
175+
176+
// Calculate color based on temperature
177+
temperature = Math.min(maxTemp, Math.max(minTemp, temperature));
178+
const ratio = (temperature - minTemp) / (maxTemp - minTemp);
179+
this._colorString = `rgb(${Math.floor(ratio * 255)}, ${Math.floor((1 - ratio) * 255)}, 0)`;
180+
181+
// Set the color
182+
this._updateStyles();
183+
}
184+
185+
_on_settings_changed() {
186+
this._textLabel.set_text(this.labelText);
187+
if (!this.dynamicColorEnabled) this._colorString = "#ffffff";
188+
this._updateStyles();
189+
this._updateTemperature();
190+
}
191+
}
192+
193+
function main(metadata, deskletId) {
194+
return new MyDesklet(metadata, deskletId);
195+
}
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
{
2-
"uuid": "systemTemperature@KopfDesDaemons",
3-
"name": "System Temperature",
4-
"description": "Displays the temperature of a thermal zone in the system.",
5-
"version": "1.0",
6-
"max-instances": "10"
7-
}
1+
{
2+
"uuid": "systemTemperature@KopfDesDaemons",
3+
"name": "System Temperature",
4+
"description": "Displays the temperature of a thermal zone in the system.",
5+
"version": "1.1.0",
6+
"max-instances": "50"
7+
}

0 commit comments

Comments
 (0)