pika-kernel-manager/src/content/mod.rs

412 lines
12 KiB
Rust
Raw Normal View History

2024-06-18 05:09:40 +02:00
use crate::{KernelBranch, RunningKernelInfo};
2024-06-17 21:13:02 +02:00
use adw::prelude::*;
2024-06-18 05:09:40 +02:00
use adw::ExpanderRow;
use duct::cmd;
use glib::*;
2024-06-17 21:13:02 +02:00
use gtk::prelude::*;
2024-06-18 05:09:40 +02:00
use gtk::*;
2024-06-17 19:11:51 +02:00
use std::fs;
use std::path::Path;
2024-06-18 05:09:40 +02:00
use std::process::{Command, Stdio};
2024-06-17 19:11:51 +02:00
use version_compare::Version;
2024-06-18 05:09:40 +02:00
use Vec;
2024-06-17 00:03:37 +02:00
2024-06-18 04:23:22 +02:00
pub fn content(content_stack: &gtk::Stack) -> gtk::Box {
2024-06-17 05:48:56 +02:00
let running_kernel_info = get_running_kernel_info();
2024-06-17 00:03:37 +02:00
let content_box = gtk::Box::builder()
.hexpand(true)
.vexpand(true)
.orientation(Orientation::Vertical)
2024-06-17 00:03:37 +02:00
.build();
let tux_icon = gtk::Image::builder()
.pixel_size(128)
.halign(Align::Center)
.hexpand(true)
.margin_start(10)
.margin_end(10)
.margin_bottom(20)
.margin_top(20)
2024-06-17 00:03:37 +02:00
.build();
tux_icon.set_icon_name(Some("tux-symbolic"));
2024-06-17 00:06:45 +02:00
tux_icon.add_css_class("symbolic-accent-bg");
2024-06-17 00:03:37 +02:00
2024-06-17 07:36:38 +02:00
let kernel_badge_box = gtk::Box::builder()
.hexpand(true)
.vexpand(true)
.orientation(Orientation::Vertical)
.build();
2024-06-17 07:59:10 +02:00
let kernel_branch_expander_row = adw::ExpanderRow::builder()
2024-06-18 00:42:47 +02:00
.subtitle("Kernel Branch")
2024-06-17 07:59:10 +02:00
.build();
2024-06-17 21:13:02 +02:00
kernel_branch_expander_row.add_row(&kernel_branch_expandable(&kernel_branch_expander_row));
2024-06-17 07:59:10 +02:00
let kernel_branch_expander_row_boxedlist = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
.hexpand(true)
.vexpand(true)
.halign(Align::Center)
.margin_start(10)
.margin_end(10)
.margin_bottom(20)
.margin_top(20)
.build();
2024-06-18 01:06:32 +02:00
let button_box = gtk::Box::builder()
.orientation(Orientation::Horizontal)
.margin_start(10)
.margin_end(10)
.margin_bottom(20)
.margin_top(20)
.hexpand(true)
.halign(Align::Center)
.build();
let browse_kernels_button = gtk::Button::builder()
.icon_name("web")
.halign(Align::Start)
.margin_start(10)
.margin_end(10)
.height_request(50)
.width_request(50)
.tooltip_text("Browse Kernel for select branch")
.hexpand(true)
.build();
browse_kernels_button.add_css_class("circular");
2024-06-18 14:45:10 +02:00
browse_kernels_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("kernel_pkg_page")
}));
2024-06-18 01:06:32 +02:00
let config_kernel_button = gtk::Button::builder()
.icon_name("settings")
.halign(Align::End)
.margin_start(10)
.margin_end(10)
.height_request(50)
.width_request(50)
.tooltip_text("Configure Sched_EXT settings")
.hexpand(true)
.build();
config_kernel_button.add_css_class("circular");
2024-06-18 04:23:22 +02:00
config_kernel_button.connect_clicked(clone!(@weak content_stack => move |_| {
content_stack.set_visible_child_name("sched_ext_page")
}));
2024-06-18 01:06:32 +02:00
button_box.append(&browse_kernels_button);
button_box.append(&config_kernel_button);
2024-06-17 07:59:10 +02:00
kernel_branch_expander_row_boxedlist.add_css_class("boxed-list");
kernel_branch_expander_row_boxedlist.append(&kernel_branch_expander_row);
2024-06-17 07:36:38 +02:00
create_kernel_badges(&kernel_badge_box, &running_kernel_info);
2024-06-17 07:36:38 +02:00
content_box.append(&kernel_badge_box);
2024-06-17 00:03:37 +02:00
content_box.append(&tux_icon);
2024-06-17 07:59:10 +02:00
content_box.append(&kernel_branch_expander_row_boxedlist);
2024-06-18 01:06:32 +02:00
content_box.append(&button_box);
2024-06-17 00:03:37 +02:00
2024-06-18 03:44:03 +02:00
let window_bottombar = gtk::Box::builder()
.hexpand(true)
.homogeneous(true)
.margin_bottom(15)
.margin_start(15)
.margin_end(15)
.margin_start(15)
.build();
let apply_button = gtk::Button::builder()
.halign(Align::End)
.label("Apply Changes")
.build();
apply_button.add_css_class("pill");
apply_button.add_css_class("destructive-action");
let cancel_button = gtk::Button::builder()
.halign(Align::Start)
.label("Cancel Changes")
.build();
cancel_button.add_css_class("pill");
window_bottombar.append(&cancel_button);
window_bottombar.append(&apply_button);
content_box.append(&window_bottombar);
2024-06-17 00:03:37 +02:00
content_box
}
2024-06-17 21:13:02 +02:00
fn kernel_branch_expandable(expander_row: &adw::ExpanderRow) -> gtk::ListBox {
2024-06-18 05:09:40 +02:00
let searchbar = gtk::SearchEntry::builder().search_delay(500).build();
2024-06-18 00:42:47 +02:00
searchbar.add_css_class("round-border-only-top");
2024-06-17 21:13:02 +02:00
let boxedlist = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
.build();
boxedlist.append(&searchbar);
let branch_container = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
.build();
branch_container.add_css_class("boxed-list");
let null_checkbutton = gtk::CheckButton::builder()
.label("No branch selected")
.build();
for branch in get_kernel_branches() {
let branch_checkbutton = gtk::CheckButton::builder()
.valign(Align::Center)
.can_focus(false)
.build();
let branch_row = adw::ActionRow::builder()
.activatable_widget(&branch_checkbutton)
.title(branch.name)
.build();
branch_row.add_prefix(&branch_checkbutton);
branch_checkbutton.set_group(Some(&null_checkbutton));
branch_container.append(&branch_row);
2024-06-18 05:09:40 +02:00
branch_checkbutton.connect_toggled(
clone!(@weak branch_checkbutton, @weak expander_row => move |_| {
if branch_checkbutton.is_active() == true {
expander_row.set_title(&branch_row.title());
}
}),
);
2024-06-17 21:13:02 +02:00
//if current_keyboard.contains(&(keyboard_layout_clone)) {
// keyboard_layout_checkbutton.set_active(true);
//}
}
let branch_container_viewport = gtk::ScrolledWindow::builder()
.child(&branch_container)
2024-06-18 00:42:47 +02:00
.hscrollbar_policy(PolicyType::Never)
2024-06-17 21:13:02 +02:00
.build();
2024-06-18 00:42:47 +02:00
branch_container.add_css_class("round-border-only-bottom");
2024-06-17 21:13:02 +02:00
boxedlist.append(&branch_container_viewport);
searchbar.connect_search_changed(clone!(@weak searchbar, @weak branch_container => move |_| {
let mut counter = branch_container.first_child();
while let Some(row) = counter {
if row.widget_name() == "AdwActionRow" {
if !searchbar.text().is_empty() {
if row.property::<String>("subtitle").to_lowercase().contains(&searchbar.text().to_string().to_lowercase()) || row.property::<String>("title").to_lowercase().contains(&searchbar.text().to_string().to_lowercase()) {
//row.grab_focus();
//row.add_css_class("highlight-widget");
row.set_property("visible", true);
searchbar.grab_focus();
} else {
row.set_property("visible", false);
}
} else {
row.set_property("visible", true);
}
}
counter = row.next_sibling();
}
}));
boxedlist
}
2024-06-18 05:09:40 +02:00
pub fn create_kernel_badge(
label0_text: &str,
label1_text: &str,
css_style: &str,
group_size: &gtk::SizeGroup,
group_size0: &gtk::SizeGroup,
group_size1: &gtk::SizeGroup,
) -> gtk::ListBox {
let badge_box = gtk::Box::builder().build();
let label0 = gtk::Label::builder()
.label(label0_text)
.margin_start(5)
.margin_end(5)
.margin_bottom(1)
.margin_top(1)
.hexpand(true)
.vexpand(true)
.build();
2024-06-17 05:48:56 +02:00
group_size0.add_widget(&label0);
2024-06-18 05:09:40 +02:00
let label_seprator = gtk::Separator::builder().build();
let label1 = gtk::Label::builder()
.label(label1_text)
.margin_start(3)
.margin_end(0)
.margin_bottom(1)
.margin_top(1)
.hexpand(true)
.vexpand(true)
.build();
2024-06-17 05:48:56 +02:00
group_size1.add_widget(&label1);
label1.add_css_class(css_style);
badge_box.append(&label0);
badge_box.append(&label_seprator);
badge_box.append(&label1);
let boxedlist = gtk::ListBox::builder()
.selection_mode(SelectionMode::None)
.halign(Align::Center)
.valign(Align::End)
.margin_start(5)
.margin_end(5)
.margin_bottom(5)
.margin_top(5)
.build();
boxedlist.add_css_class("boxed-list");
boxedlist.append(&badge_box);
group_size.add_widget(&boxedlist);
boxedlist
2024-06-17 05:48:56 +02:00
}
2024-06-17 07:59:10 +02:00
fn get_kernel_branches() -> Vec<KernelBranch> {
let test_branch = KernelBranch {
name: "kernel-cachy".to_string(),
2024-06-17 08:02:13 +02:00
db: "https://raw.githubusercontent.com/CosmicFusion/fedora-kernel-manager/main/data/db-kernel-cachy.json".to_string()
2024-06-17 07:59:10 +02:00
};
2024-06-17 08:02:13 +02:00
2024-06-18 00:42:47 +02:00
let test_branch2 = KernelBranch {
name: "kernel-cachy".to_string(),
db: "https://raw.githubusercontent.com/CosmicFusion/fedora-kernel-manager/main/data/db-kernel-cachy.json".to_string()
};
vec![test_branch, test_branch2]
2024-06-17 07:59:10 +02:00
}
2024-06-18 04:23:22 +02:00
pub fn get_running_kernel_info() -> RunningKernelInfo {
2024-06-18 05:09:40 +02:00
let kernel = match Command::new("uname")
.arg("-r")
.stdout(Stdio::piped())
.output()
{
Ok(t) => String::from_utf8(t.stdout).unwrap().trim().to_owned(),
Err(_) => "Unknown".to_string(),
2024-06-17 05:48:56 +02:00
};
2024-06-17 07:36:38 +02:00
let version = match linux_version::linux_kernel_version() {
2024-06-17 19:11:51 +02:00
Ok(t) => {
if t.patch == 0 {
format!("{}.{}", t.major, t.minor)
} else {
format!("{}.{}.{}", t.major, t.minor, t.patch)
}
}
2024-06-18 05:09:40 +02:00
Err(_) => "Unknown".to_string(),
2024-06-17 07:36:38 +02:00
};
2024-06-17 05:48:56 +02:00
let info = RunningKernelInfo {
2024-06-17 07:36:38 +02:00
kernel: kernel,
2024-06-17 19:11:51 +02:00
version: version.clone(),
2024-06-17 07:36:38 +02:00
// didn't find a way to accurately get this, outside of sched-ext (https://github.com/CachyOS/kernel-manager/blob/develop/src/schedext-window.cpp)
2024-06-18 05:09:40 +02:00
sched: get_current_scheduler(version),
2024-06-17 05:48:56 +02:00
};
info
2024-06-17 07:36:38 +02:00
}
2024-06-18 04:23:22 +02:00
pub fn get_current_scheduler(version: String) -> String {
2024-06-17 19:11:51 +02:00
if Path::new("/sys/kernel/sched_ext/root/ops").exists() {
println!("sched_ext is detected, getting scx scheduler");
2024-06-17 19:18:06 +02:00
let scx_sched = match fs::read_to_string("/sys/kernel/sched_ext/root/ops") {
Ok(t) => t,
2024-06-18 05:09:40 +02:00
Err(_) => "unknown!".to_string(),
2024-06-17 19:18:06 +02:00
};
"sched_ext: ".to_owned() + &scx_sched
2024-06-17 19:11:51 +02:00
} else if bore_check() {
"BORE".to_string()
2024-06-18 05:09:40 +02:00
} else if Version::from(&version) >= Version::from("6.6") {
2024-06-17 19:11:51 +02:00
"EEVDF?".to_string()
} else {
"CFS?".to_string()
}
}
fn bore_check() -> bool {
2024-06-18 05:09:40 +02:00
let is_bore = match cmd!("sysctl", "-n", "kernel.sched_bore").read() {
Ok(t) => {
if t == "1" {
true
} else {
false
}
}
Err(_) => false,
};
2024-06-17 19:11:51 +02:00
is_bore
}
2024-06-17 07:36:38 +02:00
fn create_kernel_badges(badge_box: &gtk::Box, running_kernel_info: &RunningKernelInfo) {
let kernel_badges_size_group = gtk::SizeGroup::new(SizeGroupMode::Both);
let kernel_badges_size_group0 = gtk::SizeGroup::new(SizeGroupMode::Both);
let kernel_badges_size_group1 = gtk::SizeGroup::new(SizeGroupMode::Both);
let kernel_version = "6.9";
let version_css_style = if &running_kernel_info.version.as_str() == &kernel_version {
"background-green-bg"
2024-06-18 05:09:40 +02:00
} else {
2024-06-17 07:36:38 +02:00
"background-red-bg"
};
2024-06-17 21:13:02 +02:00
while let Some(widget) = badge_box.last_child() {
badge_box.remove(&widget);
}
2024-06-18 05:09:40 +02:00
badge_box.append(&create_kernel_badge(
"Kernel Branch",
"cachy",
"background-accent-bg",
&kernel_badges_size_group,
&kernel_badges_size_group0,
&kernel_badges_size_group1,
));
badge_box.append(&create_kernel_badge(
"Latest Version",
"6.9",
"background-accent-bg",
&kernel_badges_size_group,
&kernel_badges_size_group0,
&kernel_badges_size_group1,
));
badge_box.append(&create_kernel_badge(
"Running Version",
&running_kernel_info.version,
&version_css_style,
&kernel_badges_size_group,
&kernel_badges_size_group0,
&kernel_badges_size_group1,
));
badge_box.append(&create_kernel_badge(
"Running Kernel",
&running_kernel_info.kernel,
&version_css_style,
&kernel_badges_size_group,
&kernel_badges_size_group0,
&kernel_badges_size_group1,
));
badge_box.append(&create_kernel_badge(
"Running Sched",
&running_kernel_info.sched,
"background-accent-bg",
&kernel_badges_size_group,
&kernel_badges_size_group0,
&kernel_badges_size_group1,
));
}