Move datetime to widgets subdir and import i3monkit network.

This commit is contained in:
2019-09-21 20:49:27 -07:00
parent 1a2ad57826
commit f09145eccd
3 changed files with 140 additions and 0 deletions

44
src/widgets/datetime.rs Normal file
View File

@@ -0,0 +1,44 @@
use chrono_tz::Tz;
use i3monkit::Block;
use i3monkit::{Widget, WidgetUpdate};
/// The widget that shows local time
pub struct DateTimeWidget {
/// fmt to format the datetime, see
/// https://docs.rs/chrono/*/chrono/format/strftime/index.html for documentation.
fmt: String,
/// tz string, values from https://docs.rs/chrono-tz/*/chrono_tz/
/// None will use local time.
tz: Option<String>,
}
impl DateTimeWidget {
// Create a new time widget
pub fn new(fmt: String) -> Self {
DateTimeWidget { fmt, tz: None }
}
pub fn tz(fmt: String, tz: String) -> Self {
DateTimeWidget { fmt, tz: Some(tz) }
}
}
impl Widget for DateTimeWidget {
fn update(&mut self) -> Option<WidgetUpdate> {
let now = chrono::Local::now();
let time_string = match &self.tz {
Some(tz) => {
let tz: Tz = tz.parse().unwrap();
let now = now.with_timezone(&tz);
//TODO(wathiede): convert to timezone.
now.format(&self.fmt).to_string()
}
None => now.format(&self.fmt).to_string(),
};
Some(WidgetUpdate {
refresh_interval: std::time::Duration::new(1, 0),
data: Some(Block::new().append_full_text(&time_string).clone()),
})
}
}

2
src/widgets/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod datetime;
pub mod network;

138
src/widgets/network.rs Normal file
View File

@@ -0,0 +1,138 @@
use i3monkit::Block;
use i3monkit::{Widget, WidgetUpdate};
use std::path::PathBuf;
use std::fs::File;
use std::io::{BufRead, BufReader, Error, ErrorKind, Result};
use std::time::SystemTime;
const NETWORK_PATH_PREFIX: &'static str = "/sys/class/net";
const NETWORK_STAT_SUFFIX: &'static str = "statistics/dummy";
struct TransferStat {
rx: u64,
tx: u64,
ts: SystemTime,
}
impl TransferStat {
fn read_stat(interface: &str) -> Result<Self> {
let mut path = PathBuf::new();
path.push(format!(
"{}/{}/{}",
NETWORK_PATH_PREFIX, interface, NETWORK_STAT_SUFFIX
));
let mut read_stat_file = move |what: &str| {
path.set_file_name(what);
let reader = BufReader::new(File::open(path.as_path())?);
if let Some(line) = reader.lines().next() {
return line;
}
return Err(Error::new(ErrorKind::Other, "Empty file"));
};
let rx = u64::from_str_radix(&(read_stat_file("rx_bytes")?), 10).unwrap();
let tx = u64::from_str_radix(&(read_stat_file("tx_bytes")?), 10).unwrap();
let ts = SystemTime::now();
return Ok(Self { rx, tx, ts });
}
fn duration(&self, earlier: &Self) -> f64 {
let duration = self.ts.duration_since(earlier.ts).unwrap();
let secs = duration.as_secs() as f64 + duration.subsec_nanos() as f64 / 1_000_000_000.0;
return secs;
}
fn rx_rate(&self, earlier: &Self) -> f64 {
let duration = self.duration(earlier);
if duration < 1e-5 {
return std::f64::NAN;
}
return (self.rx - earlier.rx) as f64 / duration;
}
fn tx_rate(&self, earlier: &Self) -> f64 {
let duration = self.duration(earlier);
if duration < 1e-5 {
return std::f64::NAN;
}
return (self.tx - earlier.tx) as f64 / duration;
}
}
/// A widget that shows the network speed realtimely
pub struct NetworkSpeedWidget {
interface: String,
last_stat: TransferStat,
}
impl NetworkSpeedWidget {
/// Create the widget, for given interface.
///
/// **interface** The interface to monitor
pub fn new(interface: &str) -> Self {
let last_stat = TransferStat::read_stat(interface).unwrap();
let interface = interface.to_string();
Self {
last_stat,
interface,
}
}
fn format_rate(rate: f64) -> String {
if rate.is_nan() {
return "N/A".to_string();
}
const UNIT_NAME: [&'static str; 6] = [" B/s", "KB/s", "MB/s", "GB/s", "TB/s", "PB/s"];
let mut best_unit = UNIT_NAME[0];
let mut best_multiplier = 1.0;
for unit in UNIT_NAME[1..].iter() {
if best_multiplier > rate / 1024.0 {
break;
}
best_unit = unit;
best_multiplier *= 1024.0
}
let ret = format!("{:6.1}{}", rate / best_multiplier, best_unit);
return ret;
}
fn get_human_readable_stat(&mut self) -> Result<(String, String)> {
let cur_stat = TransferStat::read_stat(&self.interface)?;
let rx_rate = cur_stat.rx_rate(&self.last_stat);
let tx_rate = cur_stat.tx_rate(&self.last_stat);
self.last_stat = cur_stat;
return Ok((Self::format_rate(rx_rate), Self::format_rate(tx_rate)));
}
}
impl Widget for NetworkSpeedWidget {
fn update(&mut self) -> Option<WidgetUpdate> {
if let Ok((rx, tx)) = self.get_human_readable_stat() {
let mut data = Block::new();
data.use_pango();
data.append_full_text(&format!("Rx:<tt>{}</tt> Tx:<tt>{}</tt>", rx, tx));
return Some(WidgetUpdate {
refresh_interval: std::time::Duration::new(1, 0),
data: Some(data),
});
}
None
}
}