docs: Added some code documentation
This commit is contained in:
parent
ba7bc67b6c
commit
4c2ddde26f
5 changed files with 70 additions and 20 deletions
|
|
@ -2,10 +2,13 @@ use std::{collections::HashMap, hash::{DefaultHasher, Hash, Hasher}};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use slint::Color;
|
use slint::Color;
|
||||||
|
|
||||||
|
/// Enum that is either an color or an alias
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum ConfigColor {
|
pub enum ConfigColor {
|
||||||
|
/// ARGB color
|
||||||
Raw(u32),
|
Raw(u32),
|
||||||
|
/// Alias to a color defined in [Colors::aliases]
|
||||||
Alias(String),
|
Alias(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -15,11 +18,16 @@ impl Default for ConfigColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Struct used for events colors
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct EventColor {
|
pub struct EventColor {
|
||||||
|
/// Base color of the event
|
||||||
pub background: ConfigColor,
|
pub background: ConfigColor,
|
||||||
|
/// Color of the text inside the event
|
||||||
|
/// If none, color defaults to [Colors::text]
|
||||||
pub text: Option<ConfigColor>,
|
pub text: Option<ConfigColor>,
|
||||||
|
/// How often this color will be chosen for the event
|
||||||
pub priority: u64,
|
pub priority: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,16 +41,23 @@ impl Default for EventColor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Colors used by Aliveline
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Colors {
|
pub struct Colors {
|
||||||
|
/// Maps aliases to actual colors
|
||||||
pub aliases: HashMap<String, u32>,
|
pub aliases: HashMap<String, u32>,
|
||||||
|
/// Color behind the timeline
|
||||||
pub background: ConfigColor,
|
pub background: ConfigColor,
|
||||||
|
/// Color of the timeline itself
|
||||||
pub timeline: ConfigColor,
|
pub timeline: ConfigColor,
|
||||||
|
/// Color of the text on the timeline background
|
||||||
pub text: ConfigColor,
|
pub text: ConfigColor,
|
||||||
|
/// Color used to replace ill-defined aliases
|
||||||
|
/// If it is ill-defined itself, uses black color
|
||||||
pub fallback: ConfigColor,
|
pub fallback: ConfigColor,
|
||||||
|
/// List of event colors
|
||||||
|
/// Colors are chosen pseudorandomly by their priority
|
||||||
pub events: Vec<EventColor>,
|
pub events: Vec<EventColor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,11 +73,15 @@ fn argb(value: u32) -> Color {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Colors {
|
impl Colors {
|
||||||
|
/// Get [Colors::fallback] or the default color if it is also ill-defined
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn fallback_color(&self) -> Color {
|
pub fn fallback_color(&self) -> Color {
|
||||||
self.try_get_color(&self.fallback).unwrap_or_default()
|
self.try_get_color(&self.fallback).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to get actual color from [ConfigColor].
|
||||||
|
/// Returns None if it is [ConfigColor::Alias] and alias was not found in [Colors::aliases]
|
||||||
|
#[inline(always)]
|
||||||
pub fn try_get_color(&self, color: &ConfigColor) -> Option<Color> {
|
pub fn try_get_color(&self, color: &ConfigColor) -> Option<Color> {
|
||||||
match color {
|
match color {
|
||||||
ConfigColor::Raw(color) => Some(argb(*color)),
|
ConfigColor::Raw(color) => Some(argb(*color)),
|
||||||
|
|
@ -70,10 +89,14 @@ impl Colors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get either the color or fallback color
|
||||||
|
#[inline(always)]
|
||||||
pub fn get_color(&self, color: &ConfigColor) -> Color {
|
pub fn get_color(&self, color: &ConfigColor) -> Color {
|
||||||
self.try_get_color(color).unwrap_or_else(|| self.fallback_color())
|
self.try_get_color(color).unwrap_or_else(|| self.fallback_color())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute hash and choose a color for the given event string
|
||||||
|
/// This way same strings will get same colors but it still feels randomly
|
||||||
pub fn event_color_for(&self, text: &str) -> &EventColor {
|
pub fn event_color_for(&self, text: &str) -> &EventColor {
|
||||||
let priority_sum: u64 = self.events.iter().map(|e| e.priority).sum();
|
let priority_sum: u64 = self.events.iter().map(|e| e.priority).sum();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,15 @@ pub(super) struct DefaultConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DefaultColors {
|
pub(super) struct DefaultColors {
|
||||||
pub aliases: HashMap<String, u32>,
|
pub(super) aliases: HashMap<String, u32>,
|
||||||
|
|
||||||
pub background: ConfigColor,
|
pub(super) background: ConfigColor,
|
||||||
pub timeline: ConfigColor,
|
pub(super) timeline: ConfigColor,
|
||||||
pub text: ConfigColor,
|
pub(super) text: ConfigColor,
|
||||||
pub fallback: ConfigColor,
|
pub(super) fallback: ConfigColor,
|
||||||
|
|
||||||
pub events: Vec<EventColor>,
|
pub(super) events: Vec<EventColor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DefaultColors> for Colors {
|
impl From<DefaultColors> for Colors {
|
||||||
|
|
@ -38,8 +38,8 @@ impl From<DefaultColors> for Colors {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DefaultPaths {
|
pub(super) struct DefaultPaths {
|
||||||
pub logs: PathBuf,
|
pub(super) logs: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DefaultPaths> for Paths {
|
impl From<DefaultPaths> for Paths {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,16 @@ use std::path::PathBuf;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use color::Colors;
|
use color::Colors;
|
||||||
|
|
||||||
|
/// Color-related structs and methods
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
// Not very optimal, but needed to avoid recursion in Config::default
|
||||||
mod default;
|
mod default;
|
||||||
|
|
||||||
|
/// Paths which are used by Aliveline
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Paths {
|
pub struct Paths {
|
||||||
|
/// Path to logs folder
|
||||||
pub logs: PathBuf,
|
pub logs: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,17 +21,21 @@ impl Default for Paths {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configuration struct
|
||||||
#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq, Debug)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// directory, where config is located
|
/// Directory, where config is located
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub conf_path: PathBuf,
|
pub conf_path: PathBuf,
|
||||||
|
/// Config colors
|
||||||
pub colors: Colors,
|
pub colors: Colors,
|
||||||
|
/// Config paths
|
||||||
pub paths: Paths,
|
pub paths: Paths,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
/// Get the default config and make it think it is in the given [PathBuf]
|
||||||
pub fn new(conf_path: PathBuf) -> Self {
|
pub fn new(conf_path: PathBuf) -> Self {
|
||||||
let conf_dir: PathBuf = conf_path.parent().unwrap().into();
|
let conf_dir: PathBuf = conf_path.parent().unwrap().into();
|
||||||
Config {
|
Config {
|
||||||
|
|
@ -36,6 +44,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replace fields that are not filled from deserializing
|
||||||
fn replace_missing_fields(&mut self) {
|
fn replace_missing_fields(&mut self) {
|
||||||
let default = Config::default();
|
let default = Config::default();
|
||||||
|
|
||||||
|
|
@ -44,6 +53,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to load [Config] from given [PathBuf]
|
||||||
pub fn load(path: PathBuf) -> Option<Self> {
|
pub fn load(path: PathBuf) -> Option<Self> {
|
||||||
if let Ok(toml_string) = std::fs::read_to_string(path.clone()) {
|
if let Ok(toml_string) = std::fs::read_to_string(path.clone()) {
|
||||||
if let Ok(mut conf) = toml::from_str::<Config>(&toml_string) {
|
if let Ok(mut conf) = toml::from_str::<Config>(&toml_string) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
/// Configuration module
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
/// Event tracking module
|
||||||
pub mod log;
|
pub mod log;
|
||||||
|
|
||||||
fn try_config_path(var: &'static str, path: &[&'static str]) -> Option<Config> {
|
fn try_config_path(var: &'static str, path: &[&'static str]) -> Option<Config> {
|
||||||
|
|
|
||||||
15
src/log.rs
15
src/log.rs
|
|
@ -6,17 +6,22 @@ use serde::{Deserialize, Serialize};
|
||||||
use toml::value::{Date, Time};
|
use toml::value::{Date, Time};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
/// Contains all activity tracked in one day
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Log {
|
pub struct Log {
|
||||||
|
/// Logging date, should match its filename
|
||||||
pub date: Date,
|
pub date: Date,
|
||||||
|
/// Recorded events
|
||||||
pub events: Vec<Event>,
|
pub events: Vec<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Log {
|
impl Log {
|
||||||
|
/// Construct new empty log for given date
|
||||||
pub fn new(date: Date) -> Self {
|
pub fn new(date: Date) -> Self {
|
||||||
Log { date, events: Vec::new() }
|
Log { date, events: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load log from [Paths::logs](crate::config::Paths::logs) or get empty log
|
||||||
pub fn load_from(config: &Config, date: Date) -> Self {
|
pub fn load_from(config: &Config, date: Date) -> Self {
|
||||||
let path = Log::get_filepath(&date, config);
|
let path = Log::get_filepath(&date, config);
|
||||||
if let Ok(log_string) = std::fs::read_to_string(path) {
|
if let Ok(log_string) = std::fs::read_to_string(path) {
|
||||||
|
|
@ -26,6 +31,7 @@ impl Log {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Save log in [Paths::logs](crate::config::Paths::logs)
|
||||||
pub fn save(&self, config: &Config) -> std::io::Result<()> {
|
pub fn save(&self, config: &Config) -> std::io::Result<()> {
|
||||||
Log::try_create_log_dir(config)?;
|
Log::try_create_log_dir(config)?;
|
||||||
let path = Log::get_filepath(&self.date, config);
|
let path = Log::get_filepath(&self.date, config);
|
||||||
|
|
@ -37,6 +43,7 @@ impl Log {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get filepath based on log date
|
||||||
fn get_filepath(date: &Date, config: &Config) -> PathBuf {
|
fn get_filepath(date: &Date, config: &Config) -> PathBuf {
|
||||||
let mut path = Log::get_log_dir(&config);
|
let mut path = Log::get_log_dir(&config);
|
||||||
let filename = format!("{}-{}-{}", date.day, date.month, date.year);
|
let filename = format!("{}-{}-{}", date.day, date.month, date.year);
|
||||||
|
|
@ -45,6 +52,7 @@ impl Log {
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get logging directory based on relativeness in the config
|
||||||
fn get_log_dir(config: &Config) -> PathBuf {
|
fn get_log_dir(config: &Config) -> PathBuf {
|
||||||
if config.paths.logs.is_relative() {
|
if config.paths.logs.is_relative() {
|
||||||
let mut path = config.conf_path.clone();
|
let mut path = config.conf_path.clone();
|
||||||
|
|
@ -55,6 +63,7 @@ impl Log {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create logging directory if it does not exist
|
||||||
fn try_create_log_dir(config: &Config) -> std::io::Result<()> {
|
fn try_create_log_dir(config: &Config) -> std::io::Result<()> {
|
||||||
let path = Log::get_log_dir(config);
|
let path = Log::get_log_dir(config);
|
||||||
if !std::fs::exists(&path)? {
|
if !std::fs::exists(&path)? {
|
||||||
|
|
@ -64,15 +73,21 @@ impl Log {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Single event with duration and a name
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Event {
|
pub struct Event {
|
||||||
|
/// Event name string
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// When the event began
|
||||||
pub start: Time,
|
pub start: Time,
|
||||||
|
/// When the event finished (if it is)
|
||||||
pub end: Time,
|
pub end: Time,
|
||||||
|
/// Is the event finished or it continues
|
||||||
pub finished: bool,
|
pub finished: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Event {
|
impl Event {
|
||||||
|
/// Construct new event from time seconds
|
||||||
pub fn new(name: String, start: i32, end: i32, finished: bool) -> Self {
|
pub fn new(name: String, start: i32, end: i32, finished: bool) -> Self {
|
||||||
let start = Time {
|
let start = Time {
|
||||||
hour: (start / 3600) as u8,
|
hour: (start / 3600) as u8,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue