2018-08-14 16:28:36 +02:00
|
|
|
use cursive::utils::Counter;
|
|
|
|
use failure::Error;
|
|
|
|
use std::collections::HashSet;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use walkdir::{DirEntry, WalkDir};
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Registry {
|
|
|
|
pub device: String,
|
|
|
|
pub base_path: PathBuf,
|
|
|
|
pub albums_fs: HashSet<PathBuf>,
|
|
|
|
pub albums_list: HashSet<PathBuf>,
|
|
|
|
pub selected_albums: HashSet<PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Registry {
|
|
|
|
pub fn load_albums_fs(&mut self, counter: &Counter) -> Result<(), Error> {
|
|
|
|
let dir_walker = WalkDir::new(self.base_path.clone())
|
|
|
|
.sort_by(|a, b| a.path().cmp(b.path()))
|
|
|
|
.min_depth(2)
|
|
|
|
.max_depth(2);
|
|
|
|
let dir_filter = |entry: &DirEntry| {
|
|
|
|
// The entry should be a directory and its name should not start with "extra"
|
|
|
|
entry.metadata().map(|e| e.is_dir()).unwrap_or(false) && !entry
|
|
|
|
.file_name()
|
|
|
|
.to_str()
|
|
|
|
.map(|s| s.starts_with("extra"))
|
|
|
|
.unwrap_or(true)
|
|
|
|
};
|
|
|
|
|
|
|
|
for entry in dir_walker.into_iter().filter_entry(dir_filter) {
|
|
|
|
self.albums_fs.insert(PathBuf::from(
|
|
|
|
entry?
|
|
|
|
.path()
|
|
|
|
.strip_prefix(self.base_path.clone())?
|
|
|
|
.to_str()
|
|
|
|
.unwrap(),
|
|
|
|
));
|
|
|
|
counter.tick(1);
|
|
|
|
}
|
2018-08-14 17:08:43 +02:00
|
|
|
counter.set(self.albums_fs.len());
|
2018-08-14 16:28:36 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn load_albums_file(&mut self) -> Result<(), Error> {
|
|
|
|
let mut file = File::open(format!("{}.list", self.device))?;
|
|
|
|
let mut contents = String::new();
|
|
|
|
file.read_to_string(&mut contents)?;
|
|
|
|
let line_filter = |line: &&str| line.ends_with("***");
|
|
|
|
|
|
|
|
for line in contents.lines().filter(line_filter) {
|
|
|
|
let path = line.trim_left_matches('#').trim_right_matches("/***");
|
|
|
|
if !line.starts_with('#') {
|
|
|
|
self.selected_albums.insert(PathBuf::from(path));
|
|
|
|
}
|
|
|
|
self.albums_list.insert(PathBuf::from(path));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn save_albums_file(&self) -> Result<(), Error> {
|
|
|
|
let mut file = File::create(format!("{}.list.new", self.device))?;
|
|
|
|
let mut cur_parent = PathBuf::new();
|
|
|
|
|
|
|
|
let mut albums: Vec<&PathBuf> = self.albums_fs.iter().collect();
|
|
|
|
albums.sort();
|
|
|
|
for album in albums {
|
|
|
|
let parent = album.parent().unwrap();
|
|
|
|
if parent != cur_parent {
|
|
|
|
writeln!(file, "{}/", parent.to_str().unwrap());
|
|
|
|
cur_parent = parent.to_path_buf();
|
|
|
|
}
|
|
|
|
if self.selected_albums.contains(album) {
|
|
|
|
writeln!(file, "{}/***", album.to_str().unwrap());
|
|
|
|
} else {
|
|
|
|
writeln!(file, "#{}/***", album.to_str().unwrap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn added_albums(&self) -> Vec<&PathBuf> {
|
|
|
|
let mut result: Vec<&PathBuf> = self.albums_fs.difference(&self.albums_list).collect();
|
|
|
|
result.sort();
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn existing_albums(&self) -> Vec<&PathBuf> {
|
|
|
|
let mut result: Vec<&PathBuf> = self.albums_fs.intersection(&self.albums_list).collect();
|
|
|
|
result.sort();
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn removed_albums(&self) -> Vec<&PathBuf> {
|
|
|
|
let mut result: Vec<&PathBuf> = self.albums_list.difference(&self.albums_fs).collect();
|
|
|
|
result.sort();
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn select_album(&mut self, album_path: &PathBuf, result: bool) {
|
|
|
|
if result {
|
|
|
|
self.selected_albums.insert(album_path.clone());
|
|
|
|
} else {
|
|
|
|
self.selected_albums.remove(album_path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|