feat(system/about): display all system information required

This commit is contained in:
Michael Aaron Murphy 2023-02-01 00:47:01 +01:00
parent 0a267c027d
commit 89a251f2ba
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
6 changed files with 585 additions and 43 deletions

62
Cargo.lock generated
View file

@ -416,6 +416,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "concat-in-place"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b80dba65d26e0c4b692ad0312b837f1177e8175031af57fd1de4f3bc36b430"
[[package]]
name = "concurrent-queue"
version = "2.1.0"
@ -425,6 +431,26 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "const_format"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "const_panic"
version = "0.2.7"
@ -492,6 +518,7 @@ dependencies = [
"async-channel",
"bytecheck",
"color-eyre",
"cosmic-settings-system",
"derive_setters",
"dirs",
"generator",
@ -506,6 +533,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "cosmic-settings-system"
version = "0.1.0"
dependencies = [
"bumpalo",
"concat-in-place",
"const_format",
"memchr",
"sysinfo",
]
[[package]]
name = "cosmic-text"
version = "0.6.0"
@ -2228,6 +2266,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "ntapi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
dependencies = [
"winapi",
]
[[package]]
name = "num"
version = "0.4.0"
@ -3406,6 +3453,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "sysinfo"
version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.2.0"

View file

@ -21,6 +21,9 @@ rust-embed = "6.4.2"
slotmap = "1.0.6"
tokio = "1.25.0"
[dependencies.cosmic-settings-system]
path = "pages/system"
[dependencies.i18n-embed]
version = "0.13.8"
features = ["fluent-system", "desktop-requester"]
@ -32,7 +35,7 @@ default-features = false
features = ["debug", "winit", "dyrend", "tokio"]
[profile.dev]
opt-level = 2
opt-level = "s"
incremental = true
[profile.release]

263
pages/system/Cargo.lock generated Normal file
View file

@ -0,0 +1,263 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "concat-in-place"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b80dba65d26e0c4b692ad0312b837f1177e8175031af57fd1de4f3bc36b430"
[[package]]
name = "const_format"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cosmic-settings-system"
version = "0.1.0"
dependencies = [
"bumpalo",
"concat-in-place",
"const_format",
"memchr",
"sysinfo",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "ntapi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
dependencies = [
"winapi",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "proc-macro2"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sysinfo"
version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

17
pages/system/Cargo.toml Normal file
View file

@ -0,0 +1,17 @@
[package]
name = "cosmic-settings-system"
version = "0.1.0"
edition = "2021"
license = "MPL-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
const_format = "0.2.30"
concat-in-place = "1.1.0"
sysinfo = "0.27.7"
memchr = "2.5.0"
[dependencies.bumpalo]
version = "3.12.0"
features = ["collections"]

202
pages/system/src/lib.rs Normal file
View file

@ -0,0 +1,202 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0
use bumpalo::Bump;
use std::{ffi::OsStr, io::Read};
use sysinfo::{DiskExt, SystemExt};
use concat_in_place::strcat;
use const_format::concatcp;
const DMI_DIR: &str = "/sys/devices/virtual/dmi/id/";
const BOARD_NAME: &str = concatcp!(DMI_DIR, "board_name");
const BOARD_VERSION: &str = concatcp!(DMI_DIR, "board_version");
const SYS_VENDOR: &str = concatcp!(DMI_DIR, "sys_vendor");
#[derive(Clone, Debug, Default)]
pub struct Info {
pub desktop_environment: String,
pub device_name: String,
pub disk_capacity: String,
pub graphics: Vec<String>,
pub hardware_model: String,
pub memory: String,
pub operating_system: String,
pub os_architecture: String,
pub processor: String,
pub windowing_system: String,
}
impl Info {
pub fn load() -> Info {
let mut info = Info::default();
let mut bump = Bump::with_capacity(8 * 1024);
architecture(&bump, &mut info.os_architecture);
bump.reset();
hardware_model(&bump, &mut info.hardware_model);
bump.reset();
operating_system(&bump, &mut info.operating_system);
bump.reset();
processor_name(&bump, &mut info.processor);
bump.reset();
let mut sys = sysinfo::System::new();
sys.refresh_disks_list();
sys.refresh_disks();
sys.refresh_memory();
let mut total_capacity = 0;
for disk in sys.disks() {
total_capacity += disk.total_space();
}
info.disk_capacity = format!("{} GB", (total_capacity / 1_000_000_000));
if let Some(name) = sys.host_name() {
info.device_name = name;
}
info.memory = format!("{} GB", (sys.total_memory() / 1_000_000_000 + 1));
if let Ok(mut session) = std::env::var("XDG_SESSION_TYPE") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.windowing_system = session;
}
if let Ok(mut session) = std::env::var("DESKTOP_SESSION") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.desktop_environment = session;
}
if let Ok(output) = std::process::Command::new("lspci").output() {
if let Ok(stdout) = std::str::from_utf8(&output.stdout) {
for line in stdout.lines() {
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b"VGA") {
let line = &line[pos + 3..];
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b": ") {
info.graphics.push(String::from(&line[pos + 2..]));
}
}
}
}
}
info
}
}
pub fn architecture(bump: &Bump, arch: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(value) = read_to_string("/proc/sys/kernel/arch", buffer) {
arch.push_str(value.trim());
}
}
pub fn hardware_model(bump: &Bump, hardware_model: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut sys_vendor) = read_to_string(SYS_VENDOR, buffer) {
sys_vendor = sys_vendor.trim();
hardware_model.push_str(sys_vendor);
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut name) = read_to_string(BOARD_NAME, buffer) {
name = name.trim();
if !name.is_empty() && name != sys_vendor {
// Ensure that the name does not contain the vendor.
name = match name.strip_prefix(sys_vendor) {
Some(stripped) => stripped.trim(),
None => name,
};
strcat!(&mut *hardware_model, " " name);
}
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut version) = read_to_string(BOARD_VERSION, buffer) {
version = version.trim();
// These have bogus values for their version.
const IGNORE_PRODUCTS: &[&str] = &["Dev One"];
if !version.is_empty() && !IGNORE_PRODUCTS.contains(&name) {
strcat!(hardware_model, " (" version.trim() ")");
}
}
}
}
}
pub fn operating_system(bump: &Bump, operating_system: &mut String) {
let mut buffer = bumpalo::collections::Vec::new_in(bump);
let Some(os_release) = read_to_string("/etc/os-release", &mut buffer) else {
return;
};
for line in os_release.lines() {
if let Some(mut value) = line.strip_prefix("PRETTY_NAME=") {
if let Some(v) = value.strip_prefix('"') {
value = v;
}
if let Some(v) = value.strip_suffix('"') {
value = v;
}
operating_system.push_str(value.trim());
break;
}
}
}
pub fn processor_name(bump: &Bump, name: &mut String) {
if let Some(cpuinfo) = read_to_string(
"/proc/cpuinfo",
&mut bumpalo::collections::Vec::new_in(bump),
) {
for line in cpuinfo.lines() {
if let Some(info) = line.strip_prefix("model name") {
if let Some(info) = info.trim_start().strip_prefix(":") {
name.push_str(info.trim());
}
break;
}
}
}
}
pub fn read_to_string<'a, P: AsRef<OsStr>>(
path: P,
buffer: &'a mut bumpalo::collections::Vec<u8>,
) -> Option<&'a str> {
let mut file = std::fs::File::open(path.as_ref()).ok()?;
if let Ok(metadata) = file.metadata() {
buffer.reserve_exact(metadata.len() as usize);
}
let mut buf = [0; 16 * 1024];
loop {
match file.read(&mut buf) {
Ok(0) => break,
Ok(read) => buffer.extend_from_slice(&buf[..read]),
Err(_) => return None,
}
}
std::str::from_utf8(buffer.as_slice()).ok()
}

View file

@ -1,9 +1,10 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use std::future::Future;
use crate::page::{self, Content, Section};
use crate::{
page::{self, desktop::wallpaper::settings, Content, Section},
SettingsApp,
};
use cosmic::{
iced::{
widget::{horizontal_space, row},
@ -11,6 +12,7 @@ use cosmic::{
},
widget::{icon, list_column, settings, text},
};
use cosmic_settings_system::Info;
use slotmap::SlotMap;
#[derive(Clone, Debug)]
@ -24,19 +26,6 @@ pub struct Model {
support_page: page::Entity,
}
#[derive(Clone, Debug, Default)]
pub struct Info {
hardware_model: String,
memory: String,
processor: String,
graphics: String,
disk_capacity: String,
operating_system: String,
os_architecture: String,
desktop_environment: String,
windowing_system: String,
}
impl Model {
pub fn update(&mut self, message: Message) {
match message {
@ -67,28 +56,20 @@ impl page::Page for Page {
}
fn load(_page: page::Entity) -> crate::page::PageTask {
Box::pin(async move {
let info = Info {
windowing_system: std::env::var("XDG_SESSION_TYPE")
.ok()
.unwrap_or_else(|| fl!("unknown")),
..Info::default()
};
crate::Message::About(Message::Info(info))
})
Box::pin(async move { crate::Message::About(Message::Info(Info::load())) })
}
}
fn device() -> Section {
Section::new()
.descriptions(vec![fl!("about-device"), fl!("about-device", "desc")])
.view_fn(|_app, section| {
.view_fn(|app, section| {
let desc = &section.descriptions;
let model = model(app);
let device_name = settings::item::builder(&desc[0])
.description(&desc[1])
.control(text("TODO"));
.control(text(&model.info.device_name));
list_column().add(device_name).into()
})
@ -117,14 +98,22 @@ fn hardware() -> Section {
fl!("about-hardware", "graphics"),
fl!("about-hardware", "disk-capacity"),
])
.view_fn(|_app, section| {
.view_fn(|app, section| {
let desc = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(&desc[0], text("TODO")))
.add(settings::item(&desc[1], text("TODO")))
.add(settings::item(&desc[2], text("TODO")))
.add(settings::item(&desc[3], text("TODO")))
.add(settings::item(&desc[4], text("TODO")))
let model = model(app);
let mut sections = settings::view_section(&section.title)
.add(settings::item(&desc[0], text(&model.info.hardware_model)))
.add(settings::item(&desc[1], text(&model.info.memory)))
.add(settings::item(&desc[2], text(&model.info.processor)));
for card in &model.info.graphics {
sections = sections.add(settings::item(&desc[3], text(card.as_str())));
}
// .add(settings::item(&desc[3], text(&model.info.graphics)))
sections
.add(settings::item(&desc[4], text(&model.info.disk_capacity)))
.into()
})
}
@ -139,16 +128,16 @@ fn os() -> Section {
fl!("about-os", "windowing-system"),
])
.view_fn(|app, section| {
let model = app
.pages
.resource::<Model>()
.expect("missing system->about model");
let model = model(app);
let desc = &section.descriptions;
settings::view_section(&section.title)
.add(settings::item(&desc[0], text("TODO")))
.add(settings::item(&desc[1], text("TODO")))
.add(settings::item(&desc[2], text("TODO")))
.add(settings::item(&desc[0], text(&model.info.operating_system)))
.add(settings::item(&desc[1], text(&model.info.os_architecture)))
.add(settings::item(
&desc[2],
text(&model.info.desktop_environment),
))
.add(settings::item(&desc[3], text(&model.info.windowing_system)))
.into()
})
@ -164,3 +153,9 @@ fn related() -> Section {
.into()
})
}
fn model(app: &SettingsApp) -> &Model {
app.pages
.resource::<Model>()
.expect("missing system->about model")
}