diff --git a/panels/.gitkeep b/panels/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/panels/cpu/cpu_collector.gd b/panels/cpu/cpu_collector.gd new file mode 100644 index 0000000..e9fd2df --- /dev/null +++ b/panels/cpu/cpu_collector.gd @@ -0,0 +1,51 @@ +extends RefCounted +class_name CpuCollector + + +var _previous_total: int = 0 +var _previous_idle: int = 0 +var _has_previous: bool = false + + +func collect() -> float: + var stats: PackedStringArray = _read_stats() + if stats.is_empty(): + return 0.0 + + var total: int = 0 + var idle: int = 0 + + for i in range(1, stats.size()): + var val: int = stats[i].to_int() + total += val + if i == 4: # idle is the 4th token (index 4) + idle = val + + if not _has_previous: + _previous_total = total + _previous_idle = idle + _has_previous = true + return 0.0 + + var total_delta: int = total - _previous_total + var idle_delta: int = idle - _previous_idle + + _previous_total = total + _previous_idle = idle + + if total_delta == 0: + return 0.0 + + return 100.0 * (1.0 - float(idle_delta) / float(total_delta)) + + +func _read_stats() -> PackedStringArray: + var file := FileAccess.open("/proc/stat", FileAccess.READ) + if file == null: + return PackedStringArray() + + var line: String = file.get_line() + if not line.begins_with("cpu "): + return PackedStringArray() + + return line.split(" ", false) diff --git a/panels/cpu/cpu_module.gd b/panels/cpu/cpu_module.gd new file mode 100644 index 0000000..d9ca0fa --- /dev/null +++ b/panels/cpu/cpu_module.gd @@ -0,0 +1,49 @@ +extends ModuleBase +class_name CpuModule + + +@onready var title_label: Label = %Title +@onready var label: Label = %Label +@onready var progress: ProgressBar = %ProgressBar + +var _collector: CpuCollector + + +func initialize() -> void: + module_title = "CPU" + _collector = CpuCollector.new() + _style() + + +func refresh(data: Dictionary) -> void: + var usage: float = _collector.collect() + if usage < 0.0: + return + + var pct: int = roundi(usage) + label.text = "%d%%" % pct + progress.value = pct + + +func _style() -> void: + title_label.add_theme_color_override("font_color", Color(0.7, 0.7, 0.8, 1.0)) + + label.add_theme_color_override("font_color", Color(0.9, 0.9, 1.0, 1.0)) + label.add_theme_font_size_override("font_size", 48) + + var fg := StyleBoxFlat.new() + fg.bg_color = Color(0.2, 0.5, 0.8, 1.0) + fg.corner_radius_top_left = 4 + fg.corner_radius_top_right = 4 + fg.corner_radius_bottom_right = 4 + fg.corner_radius_bottom_left = 4 + + var bg := StyleBoxFlat.new() + bg.bg_color = Color(0.1, 0.1, 0.14, 1.0) + bg.corner_radius_top_left = 4 + bg.corner_radius_top_right = 4 + bg.corner_radius_bottom_right = 4 + bg.corner_radius_bottom_left = 4 + + progress.add_theme_stylebox_override("fill", fg) + progress.add_theme_stylebox_override("background", bg) diff --git a/panels/cpu/cpu_module.tscn b/panels/cpu/cpu_module.tscn new file mode 100644 index 0000000..53ed348 --- /dev/null +++ b/panels/cpu/cpu_module.tscn @@ -0,0 +1,40 @@ +[gd_scene format=3 uid="uid://bq3bs2hb4r7fb"] + +[ext_resource type="Script" path="res://panels/cpu/cpu_module.gd" id="1"] + +[node name="CpuModule" type="PanelContainer"] +anchors_preset = 0 +script = ExtResource("1") + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +theme_constant_overrides/margin_left = 12 +theme_constant_overrides/margin_top = 12 +theme_constant_overrides/margin_right = 12 +theme_constant_overrides/margin_bottom = 12 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true +text = "CPU" + +[node name="Spacer" type="Control" parent="MarginContainer/VBoxContainer"] +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true +horizontal_alignment = 1 +size_flags_horizontal = 4 + +[node name="ProgressBar" type="ProgressBar" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true +size_flags_horizontal = 4 +max_value = 100.0 +value = 0.0 +show_percentage = false diff --git a/scenes/dashboard.gd b/scenes/dashboard.gd index 9688bc0..86d0ae3 100644 --- a/scenes/dashboard.gd +++ b/scenes/dashboard.gd @@ -3,6 +3,36 @@ extends Control @onready var grid: DashboardGrid = %DashboardGrid +var _modules: Array = [] + func _ready() -> void: get_window().mode = Window.MODE_FULLSCREEN + _set_background() + _add_modules() + + +func _set_background() -> void: + var bg := StyleBoxFlat.new() + bg.bg_color = Color(0.08, 0.08, 0.12, 1.0) + add_theme_stylebox_override("panel", bg) + + +func _add_modules() -> void: + var cpu := preload("res://panels/cpu/cpu_module.tscn").instantiate() + grid.place_module(cpu, 0, 0) + _modules.append(cpu) + + # Start a timer to refresh all modules every second + var timer := Timer.new() + timer.timeout.connect(_refresh_modules) + timer.autostart = true + timer.wait_time = 1.0 + add_child(timer) + + +func _refresh_modules() -> void: + var data: Dictionary = {} + for mod in _modules: + if is_instance_valid(mod) and mod.has_method("refresh"): + mod.refresh(data) diff --git a/scripts/dashboard_grid.gd b/scripts/dashboard_grid.gd index d6487c0..a7fa1db 100644 --- a/scripts/dashboard_grid.gd +++ b/scripts/dashboard_grid.gd @@ -91,10 +91,27 @@ func _build_cells() -> void: var cell := PanelContainer.new() cell.name = "Cell_%d_%d" % [col, row] cell.mouse_filter = Control.MOUSE_FILTER_PASS + _style_cell(cell) add_child(cell) _cells[row].append(cell) +func _style_cell(cell: PanelContainer) -> void: + var style := StyleBoxFlat.new() + style.bg_color = Color(0.14, 0.14, 0.18, 1.0) + style.border_width_left = 1 + style.border_width_top = 1 + style.border_width_right = 1 + style.border_width_bottom = 1 + style.border_color = Color(0.25, 0.25, 0.35, 1.0) + style.corner_radius_top_left = 6 + style.corner_radius_top_right = 6 + style.corner_radius_bottom_right = 6 + style.corner_radius_bottom_left = 6 + cell.add_theme_stylebox_override("panel", style) + cell.add_theme_stylebox_override("panel_focused", style) + + func _teardown_cells() -> void: for child in get_children(): remove_child(child) @@ -138,8 +155,8 @@ func _save_modules() -> void: func _restore_modules() -> void: for key in _module_positions: - var parts := key.split(",") - var col := int(parts[0]) + var parts: PackedStringArray = key.split(",") + var col: int = int(parts[0]) var row := int(parts[1]) var module: Control = _module_positions[key] @@ -149,7 +166,7 @@ func _restore_modules() -> void: # Place in the last available cell if original position no longer exists if _cells.size() > 0 and _cells[0].size() > 0: var last_row := _cells.size() - 1 - var last_col := _cells[last_row].size() - 1 + var last_col: int = _cells[last_row].size() - 1 _set_cell_child(_cells[last_row][last_col], module) else: module.queue_free()