M2: terminal UI (ratatui)
- layout: header, top menu (quicklook, cpu, mem, swap, load), left sidebar, process list and alert footer - decorations/colors, bars, per-plugin render implementations - hotkeys: quit, help, modes, sorting, cursor, nice, kill, filters, toggles - TestBackend layout test
This commit is contained in:
@@ -163,6 +163,110 @@ impl Plugin for QuicklookPlugin {
|
||||
fn display_curse(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn render(&mut self, ctx: &glances_core::RenderContext) -> Vec<glances_core::StatLine> {
|
||||
let mut ret = Vec::new();
|
||||
let s = &self.model.stats;
|
||||
if !s.is_object() || ctx.max_width == 0 {
|
||||
return ret;
|
||||
}
|
||||
// System information: CPU name + frequency.
|
||||
let freq = match (s.get("cpu_hz_current").and_then(Value::as_f64), s.get("cpu_hz").and_then(Value::as_f64)) {
|
||||
(Some(current), Some(max)) => format!(" {:.2}/{:.2}GHz", current / 1e9, max / 1e9),
|
||||
(Some(current), None) => format!(" {:.2}GHz", current / 1e9),
|
||||
_ => String::new(),
|
||||
};
|
||||
let cpu_name = s.get("cpu_name").and_then(Value::as_str).unwrap_or("");
|
||||
let name = if (ctx.max_width as i64 - freq.len() as i64 + 7) > 0 {
|
||||
format!("{:<width$}", cpu_name, width = ctx.max_width - freq.len() + 7)
|
||||
} else if freq.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
"Frequency".to_string()
|
||||
};
|
||||
ret.push(self.model.curse_add_line(name.clone(), glances_core::Decoration::Default, false, false, false));
|
||||
ret.push(self.model.curse_add_line(freq.clone(), glances_core::Decoration::Default, false, false, false));
|
||||
ret.push(self.model.curse_new_line());
|
||||
|
||||
let bar_size = std::cmp::max(
|
||||
name.len().saturating_add(freq.len()).saturating_sub(7),
|
||||
(ctx.max_width as usize).saturating_sub(9),
|
||||
)
|
||||
.max(10);
|
||||
let bar_char = self
|
||||
.model
|
||||
.get_conf_value("bar_char", "")
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "|".to_string());
|
||||
|
||||
let mut lines: Vec<Vec<glances_core::StatLine>> = Vec::new();
|
||||
let mut push_line = |msg: String, bar_key: &str, percent: f64, decoration: glances_core::Decoration| {
|
||||
let bar = glances_core::units::bar_percent(percent, bar_size, &bar_char, true);
|
||||
lines.push(vec![
|
||||
self.model.curse_add_line(msg, glances_core::Decoration::Default, false, false, false),
|
||||
self.model.curse_add_line("[", glances_core::Decoration::Bold, false, false, false),
|
||||
self.model.curse_add_line(bar, decoration, false, false, false),
|
||||
self.model.curse_add_line("]", glances_core::Decoration::Bold, false, false, false),
|
||||
self.model.curse_add_line(" ", glances_core::Decoration::Default, false, false, false),
|
||||
]);
|
||||
let _ = bar_key;
|
||||
};
|
||||
|
||||
let stats_list = self.stats_list.clone();
|
||||
for key in &stats_list {
|
||||
if key == "cpu" && ctx.runtime.percpu {
|
||||
if let Some(percpu) = s.get("percpu").and_then(Value::as_array) {
|
||||
let mut sorted = percpu.clone();
|
||||
if sorted.len() > self.max_cpu_display {
|
||||
sorted.sort_by(|a, b| {
|
||||
b.get("total")
|
||||
.and_then(Value::as_f64)
|
||||
.unwrap_or(0.0)
|
||||
.partial_cmp(&a.get("total").and_then(Value::as_f64).unwrap_or(0.0))
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
});
|
||||
}
|
||||
for cpu in sorted.iter().take(self.max_cpu_display) {
|
||||
let cpu_id = cpu.get("cpu_number").and_then(Value::as_i64).unwrap_or(0);
|
||||
let total = cpu.get("total").and_then(Value::as_f64).unwrap_or(0.0);
|
||||
let msg = if cpu_id < 10 { format!("{:<3}{cpu_id} ", key.to_uppercase()) } else { format!("{cpu_id:4} ") };
|
||||
let decoration = self.decoration_for_percpu(cpu_id);
|
||||
push_line(msg, key, total, decoration);
|
||||
}
|
||||
if percpu.len() > self.max_cpu_display {
|
||||
let hidden: Vec<f64> = sorted
|
||||
.iter()
|
||||
.skip(self.max_cpu_display)
|
||||
.filter_map(|cpu| cpu.get("total").and_then(Value::as_f64))
|
||||
.collect();
|
||||
let mean = if hidden.is_empty() { 0.0 } else { hidden.iter().sum::<f64>() / hidden.len() as f64 };
|
||||
let decoration = self.decoration_for_percpu(-1);
|
||||
push_line(format!("{:<3}* ", key.to_uppercase()), key, mean, decoration);
|
||||
}
|
||||
}
|
||||
} else if let Some(value) = s.get(key).and_then(Value::as_f64) {
|
||||
let decoration = self.model.view_decoration(None, key);
|
||||
push_line(format!("{:<4} ", key.to_uppercase()), key, value, decoration);
|
||||
}
|
||||
}
|
||||
for line in lines {
|
||||
ret.extend(line);
|
||||
ret.push(self.model.curse_new_line());
|
||||
}
|
||||
ret.pop();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl QuicklookPlugin {
|
||||
fn decoration_for_percpu(&self, cpu_id: i64) -> glances_core::Decoration {
|
||||
let key = if cpu_id < 0 { "other".to_string() } else { cpu_id.to_string() };
|
||||
match self.model.get_view(None, "percpu_decoration", &key) {
|
||||
Value::String(name) => glances_core::Decoration::from_name(&name),
|
||||
_ => glances_core::Decoration::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the style for a CPU percentage without the get_alert side effects.
|
||||
|
||||
Reference in New Issue
Block a user