EpisodeWidget: Add a Date state machine.
This commit is contained in:
parent
a88a1c5f1f
commit
c856b88008
@ -1,11 +1,9 @@
|
||||
use glib;
|
||||
use gtk;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
|
||||
use failure::Error;
|
||||
use humansize::{file_size_opts as size_opts, FileSize};
|
||||
use humansize::FileSize;
|
||||
use open;
|
||||
use take_mut;
|
||||
|
||||
@ -22,30 +20,10 @@ use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {
|
||||
// Declare a custom humansize option struct
|
||||
// See: https://docs.rs/humansize/1.0.2/humansize/file_size_opts/struct.FileSizeOpts.html
|
||||
Arc::new(size_opts::FileSizeOpts {
|
||||
divider: size_opts::Kilo::Binary,
|
||||
units: size_opts::Kilo::Decimal,
|
||||
decimal_places: 0,
|
||||
decimal_zeroes: 0,
|
||||
fixed_at: size_opts::FixedAt::No,
|
||||
long_units: false,
|
||||
space: true,
|
||||
suffix: "",
|
||||
allow_negative: false,
|
||||
})
|
||||
};
|
||||
|
||||
static ref NOW: DateTime<Utc> = Utc::now();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EpisodeWidget {
|
||||
pub container: gtk::Box,
|
||||
date: gtk::Label,
|
||||
date: Arc<Mutex<DateMachine>>,
|
||||
title: Arc<Mutex<TitleMachine>>,
|
||||
duration: Arc<Mutex<DurationMachine>>,
|
||||
media: Arc<Mutex<MediaMachine>>,
|
||||
@ -73,6 +51,7 @@ impl Default for EpisodeWidget {
|
||||
let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap();
|
||||
|
||||
let title_machine = Arc::new(Mutex::new(TitleMachine::new(title, false)));
|
||||
let date_machine = Arc::new(Mutex::new(DateMachine::new(date, 0)));
|
||||
let dur = DurationMachine::new(duration, separator1, None);
|
||||
let duration_machine = Arc::new(Mutex::new(dur));
|
||||
let _media = MediaMachine::new(
|
||||
@ -91,7 +70,7 @@ impl Default for EpisodeWidget {
|
||||
container,
|
||||
title: title_machine,
|
||||
duration: duration_machine,
|
||||
date,
|
||||
date: date_machine,
|
||||
media: media_machine,
|
||||
}
|
||||
}
|
||||
@ -108,11 +87,13 @@ impl EpisodeWidget {
|
||||
WidgetExt::set_name(&self.container, &episode.rowid().to_string());
|
||||
|
||||
// Set the date label.
|
||||
self.set_date(episode.epoch());
|
||||
if let Err(err) = self.set_date(episode.epoch()) {
|
||||
error!("Failed to determine date state: {}", err);
|
||||
}
|
||||
|
||||
// Set the title label state.
|
||||
if let Err(err) = self.set_title(&episode) {
|
||||
error!("Failed to set title state: {}", err);
|
||||
error!("Failed to determine title state: {}", err);
|
||||
}
|
||||
|
||||
// Set the duaration label.
|
||||
@ -166,14 +147,12 @@ impl EpisodeWidget {
|
||||
}
|
||||
|
||||
/// Set the date label depending on the current time.
|
||||
fn set_date(&self, epoch: i32) {
|
||||
let date = Utc.timestamp(i64::from(epoch), 0);
|
||||
if NOW.year() == date.year() {
|
||||
self.date.set_text(date.format("%e %b").to_string().trim());
|
||||
} else {
|
||||
self.date
|
||||
.set_text(date.format("%e %b %Y").to_string().trim());
|
||||
};
|
||||
fn set_date(&self, epoch: i32) -> Result<(), Error> {
|
||||
let mut lock = self.date.lock().map_err(|err| format_err!("{}", err))?;
|
||||
take_mut::take(lock.deref_mut(), |date| {
|
||||
date.determine_state(i64::from(epoch))
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the duration label.
|
||||
|
||||
@ -8,13 +8,34 @@
|
||||
use chrono;
|
||||
use glib;
|
||||
use gtk;
|
||||
|
||||
use chrono::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
use humansize::FileSize;
|
||||
use humansize::{file_size_opts as size_opts, FileSize};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use manager::Progress as OtherProgress;
|
||||
use widgets::episode::SIZE_OPTS;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref SIZE_OPTS: Arc<size_opts::FileSizeOpts> = {
|
||||
// Declare a custom humansize option struct
|
||||
// See: https://docs.rs/humansize/1.0.2/humansize/file_size_opts/struct.FileSizeOpts.html
|
||||
Arc::new(size_opts::FileSizeOpts {
|
||||
divider: size_opts::Kilo::Binary,
|
||||
units: size_opts::Kilo::Decimal,
|
||||
decimal_places: 0,
|
||||
decimal_zeroes: 0,
|
||||
fixed_at: size_opts::FixedAt::No,
|
||||
long_units: false,
|
||||
space: true,
|
||||
suffix: "",
|
||||
allow_negative: false,
|
||||
})
|
||||
};
|
||||
|
||||
static ref NOW: DateTime<Utc> = Utc::now();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UnInitialized;
|
||||
@ -153,6 +174,96 @@ impl TitleMachine {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Usual;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct YearShown;
|
||||
|
||||
impl From<Usual> for YearShown {
|
||||
fn from(_: Usual) -> Self {
|
||||
YearShown {}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<YearShown> for Usual {
|
||||
fn from(_: YearShown) -> Self {
|
||||
Usual {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Date<S> {
|
||||
date: gtk::Label,
|
||||
epoch: i64,
|
||||
state: S,
|
||||
}
|
||||
|
||||
impl Date<Usual> {
|
||||
fn new(date: gtk::Label, epoch: i64) -> Self {
|
||||
let ts = Utc.timestamp(i64::from(epoch), 0);
|
||||
date.set_text(ts.format("%e %b").to_string().trim());
|
||||
|
||||
Date {
|
||||
date,
|
||||
epoch,
|
||||
state: Usual {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date<Usual>> for Date<YearShown> {
|
||||
fn from(f: Date<Usual>) -> Self {
|
||||
let ts = Utc.timestamp(f.epoch, 0);
|
||||
f.date.set_text(ts.format("%e %b %Y").to_string().trim());
|
||||
|
||||
Date {
|
||||
date: f.date,
|
||||
epoch: f.epoch,
|
||||
state: YearShown {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Date<YearShown>> for Date<Usual> {
|
||||
fn from(f: Date<YearShown>) -> Self {
|
||||
let ts = Utc.timestamp(f.epoch, 0);
|
||||
f.date.set_text(ts.format("%e %b").to_string().trim());
|
||||
|
||||
Date {
|
||||
date: f.date,
|
||||
epoch: f.epoch,
|
||||
state: Usual {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DateMachine {
|
||||
Usual(Date<Usual>),
|
||||
WithYear(Date<YearShown>),
|
||||
}
|
||||
|
||||
impl DateMachine {
|
||||
pub fn new(label: gtk::Label, epoch: i64) -> Self {
|
||||
let m = DateMachine::Usual(Date::<Usual>::new(label, epoch));
|
||||
m.determine_state(epoch)
|
||||
}
|
||||
|
||||
pub fn determine_state(self, epoch: i64) -> Self {
|
||||
use self::DateMachine::*;
|
||||
|
||||
let ts = Utc.timestamp(epoch, 0);
|
||||
let is_old = NOW.year() == ts.year();
|
||||
|
||||
match (self, is_old) {
|
||||
(date @ Usual(_), false) => date,
|
||||
(date @ WithYear(_), true) => date,
|
||||
(Usual(val), true) => WithYear(val.into()),
|
||||
(WithYear(val), false) => Usual(val.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Duration<S: Visibility> {
|
||||
// TODO: make duration and separator diff types
|
||||
|
||||
Loading…
Reference in New Issue
Block a user