mirror of
https://codeberg.org/unspeaker/perch.git
synced 2025-12-07 10:06:44 +01:00
set multiple values in table
This commit is contained in:
parent
29435bb937
commit
95aa9f8b02
1 changed files with 96 additions and 56 deletions
152
src/model.rs
152
src/model.rs
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufReader, Read};
|
use std::io::{BufReader, Read};
|
||||||
|
use std::cmp::{Eq, PartialEq, Ord, PartialOrd, Ordering};
|
||||||
use lofty::{file::TaggedFileExt, probe::Probe, tag::Accessor};
|
use lofty::{file::TaggedFileExt, probe::Probe, tag::Accessor};
|
||||||
use byte_unit::{Byte, Unit::MB};
|
use byte_unit::{Byte, Unit::MB};
|
||||||
|
|
||||||
|
|
@ -15,11 +16,28 @@ pub struct Taggart {
|
||||||
pub editing: Option<(usize, String)>,
|
pub editing: Option<(usize, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Ord, Eq, PartialEq, PartialOrd, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Entry {
|
pub struct Entry {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
pub info: EntryInfo,
|
pub info: Arc<RwLock<EntryInfo>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Entry {}
|
||||||
|
impl PartialEq for Entry {
|
||||||
|
fn eq (&self, other: &Self) -> bool {
|
||||||
|
self.path.eq(&other.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Ord for Entry {
|
||||||
|
fn cmp (&self, other: &Self) -> Ordering {
|
||||||
|
self.path.cmp(&other.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialOrd for Entry {
|
||||||
|
fn partial_cmp (&self, other: &Self) -> Option<Ordering> {
|
||||||
|
self.path.partial_cmp(&other.path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Ord, Eq, PartialEq, PartialOrd, Debug)]
|
#[derive(Ord, Eq, PartialEq, PartialOrd, Debug)]
|
||||||
|
|
@ -101,10 +119,10 @@ impl<T> Column<T> {
|
||||||
|
|
||||||
pub struct Columns<T>(pub Vec<Column<T>>);
|
pub struct Columns<T>(pub Vec<Column<T>>);
|
||||||
|
|
||||||
fn paths_under (entries: &mut [Entry], index: usize) -> Option<Vec<&mut Entry>> {
|
fn paths_under (entries: &mut [Entry], index: usize) -> Option<Vec<Arc<RwLock<EntryInfo>>>> {
|
||||||
let path = if let Some(Entry {
|
let path = if let Some(Entry { path, info, .. }) = entries.get(index)
|
||||||
path, info: EntryInfo::Directory { .. }, ..
|
&& let EntryInfo::Directory { .. } = &*info.read().unwrap()
|
||||||
}) = entries.get(index) {
|
{
|
||||||
Some(path.clone())
|
Some(path.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -113,7 +131,7 @@ fn paths_under (entries: &mut [Entry], index: usize) -> Option<Vec<&mut Entry>>
|
||||||
let mut others = vec![];
|
let mut others = vec![];
|
||||||
for other in entries.iter_mut() {
|
for other in entries.iter_mut() {
|
||||||
if other.path.starts_with(&path) && !other.is_dir() {
|
if other.path.starts_with(&path) && !other.is_dir() {
|
||||||
others.push(other);
|
others.push(other.info.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(others)
|
Some(others)
|
||||||
|
|
@ -135,7 +153,9 @@ impl Default for Columns<Entry> {
|
||||||
Column::new(&"ARTIST", 30, |entry: &Entry|entry.artist())
|
Column::new(&"ARTIST", 30, |entry: &Entry|entry.artist())
|
||||||
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
||||||
if let Some(entries) = paths_under(entries, index) {
|
if let Some(entries) = paths_under(entries, index) {
|
||||||
todo!("set artist for whole directory {:#?}", entries);
|
for entry in entries.iter() {
|
||||||
|
entry.write().unwrap().set_artist(&value);
|
||||||
|
}
|
||||||
} else if let Some(entry) = entries.get_mut(index) {
|
} else if let Some(entry) = entries.get_mut(index) {
|
||||||
entry.set_artist(&value)
|
entry.set_artist(&value)
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +164,9 @@ impl Default for Columns<Entry> {
|
||||||
Column::new(&"RELEASE", 30, |entry: &Entry|entry.album())
|
Column::new(&"RELEASE", 30, |entry: &Entry|entry.album())
|
||||||
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
||||||
if let Some(entries) = paths_under(entries, index) {
|
if let Some(entries) = paths_under(entries, index) {
|
||||||
todo!("set album for whole directory {:#?}", entries);
|
for entry in entries.iter() {
|
||||||
|
entry.write().unwrap().set_album(&value);
|
||||||
|
}
|
||||||
} else if let Some(entry) = entries.get_mut(index) {
|
} else if let Some(entry) = entries.get_mut(index) {
|
||||||
entry.set_album(&value)
|
entry.set_album(&value)
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +175,9 @@ impl Default for Columns<Entry> {
|
||||||
Column::new(&"TRACK", 5, |entry: &Entry|entry.track())
|
Column::new(&"TRACK", 5, |entry: &Entry|entry.track())
|
||||||
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
||||||
if let Some(entries) = paths_under(entries, index) {
|
if let Some(entries) = paths_under(entries, index) {
|
||||||
todo!("set track for whole directory {:#?}", entries);
|
for entry in entries.iter() {
|
||||||
|
entry.write().unwrap().set_track(&value);
|
||||||
|
}
|
||||||
} else if let Some(entry) = entries.get_mut(index) {
|
} else if let Some(entry) = entries.get_mut(index) {
|
||||||
entry.set_track(&value)
|
entry.set_track(&value)
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +186,9 @@ impl Default for Columns<Entry> {
|
||||||
Column::new(&"TITLE", 80, |entry: &Entry|entry.title())
|
Column::new(&"TITLE", 80, |entry: &Entry|entry.title())
|
||||||
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
.setter(|entries: &mut [Entry], index: usize, value: &str|{
|
||||||
if let Some(entries) = paths_under(entries, index) {
|
if let Some(entries) = paths_under(entries, index) {
|
||||||
todo!("set title for whole directory {:#?}", entries);
|
for entry in entries.iter() {
|
||||||
|
entry.write().unwrap().set_title(&value);
|
||||||
|
}
|
||||||
} else if let Some(entry) = entries.get_mut(index) {
|
} else if let Some(entry) = entries.get_mut(index) {
|
||||||
entry.set_title(&value)
|
entry.set_title(&value)
|
||||||
}
|
}
|
||||||
|
|
@ -187,96 +213,81 @@ impl Entry {
|
||||||
Ok(Some(Self {
|
Ok(Some(Self {
|
||||||
depth,
|
depth,
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
info: EntryInfo::Directory {
|
info: Arc::new(RwLock::new(EntryInfo::Directory {
|
||||||
hash_file: None,
|
hash_file: None,
|
||||||
catalog_file: None,
|
catalog_file: None,
|
||||||
artist_file: None,
|
artist_file: None,
|
||||||
release_file: None,
|
release_file: None,
|
||||||
},
|
})),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
fn new_file (_: &impl AsRef<Path>, path: &Path, depth: usize) -> Perhaps<Self> {
|
fn new_file (_: &impl AsRef<Path>, path: &Path, depth: usize) -> Perhaps<Self> {
|
||||||
Ok(Some(Self {
|
Ok(Some(Self {
|
||||||
depth,
|
depth,
|
||||||
info: EntryInfo::new(path)?,
|
info: Arc::new(RwLock::new(EntryInfo::new(path)?)),
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
pub fn is_dir (&self) -> bool {
|
pub fn is_dir (&self) -> bool {
|
||||||
matches!(self.info, EntryInfo::Directory { .. })
|
matches!(&*self.info.read().unwrap(), EntryInfo::Directory { .. })
|
||||||
}
|
}
|
||||||
pub fn is_mus (&self) -> bool {
|
pub fn is_mus (&self) -> bool {
|
||||||
matches!(self.info, EntryInfo::Music { .. })
|
matches!(&*self.info.read().unwrap(), EntryInfo::Music { .. })
|
||||||
}
|
}
|
||||||
pub fn is_img (&self) -> bool {
|
pub fn is_img (&self) -> bool {
|
||||||
matches!(self.info, EntryInfo::Image { .. })
|
matches!(&*self.info.read().unwrap(), EntryInfo::Image { .. })
|
||||||
}
|
}
|
||||||
pub fn hash (&self) -> Option<Arc<str>> {
|
pub fn hash (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Image { ref hash, .. } => Some(hash.clone()),
|
EntryInfo::Image { hash, .. } => Some(hash.clone()),
|
||||||
EntryInfo::Music { ref hash, .. } => Some(hash.clone()),
|
EntryInfo::Music { hash, .. } => Some(hash.clone()),
|
||||||
|
EntryInfo::Unknown { hash, .. } => Some(hash.clone()),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn size (&self) -> Option<Arc<str>> {
|
pub fn size (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Image { ref size, .. } => Some(size.clone()),
|
EntryInfo::Image { size, .. } => Some(size.clone()),
|
||||||
EntryInfo::Music { ref size, .. } => Some(size.clone()),
|
EntryInfo::Music { size, .. } => Some(size.clone()),
|
||||||
|
EntryInfo::Unknown { size, .. } => Some(size.clone()),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn artist (&self) -> Option<Arc<str>> {
|
pub fn artist (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Music { ref artist, .. } => artist.clone(),
|
EntryInfo::Music { artist, .. } => artist.clone(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn album (&self) -> Option<Arc<str>> {
|
pub fn album (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Music { ref album, .. } => album.clone(),
|
EntryInfo::Music { album, .. } => album.clone(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn title (&self) -> Option<Arc<str>> {
|
pub fn title (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Music { ref title, .. } => title.clone(),
|
EntryInfo::Music { title, .. } => title.clone(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn track (&self) -> Option<Arc<str>> {
|
pub fn track (&self) -> Option<Arc<str>> {
|
||||||
match self.info {
|
match &*self.info.read().unwrap() {
|
||||||
EntryInfo::Music { ref track, .. } => track.map(|t|format!("{t}").into()).clone(),
|
EntryInfo::Music { track, .. } => track.map(|t|format!("{t}").into()).clone(),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_artist (&mut self, value: &impl AsRef<str> ) {
|
pub fn set_artist (&self, value: &impl AsRef<str> ) {
|
||||||
match self.info {
|
self.info.write().unwrap().set_artist(value)
|
||||||
EntryInfo::Music { ref mut artist, .. } => *artist = Some(value.as_ref().into()),
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
pub fn set_album (&self, value: &impl AsRef<str> ) {
|
||||||
|
self.info.write().unwrap().set_album(value)
|
||||||
}
|
}
|
||||||
pub fn set_album (&mut self, value: &impl AsRef<str> ) {
|
pub fn set_title (&self, value: &impl AsRef<str> ) {
|
||||||
match self.info {
|
self.info.write().unwrap().set_title(value)
|
||||||
EntryInfo::Music { ref mut album, .. } => *album = Some(value.as_ref().into()),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn set_title (&mut self, value: &impl AsRef<str> ) {
|
|
||||||
match self.info {
|
|
||||||
EntryInfo::Music { ref mut title, .. } => *title = Some(value.as_ref().into()),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn set_track (&mut self, value: &impl AsRef<str> ) {
|
|
||||||
match self.info {
|
|
||||||
EntryInfo::Directory { .. } => todo!("set track for whole directory"),
|
|
||||||
EntryInfo::Music { ref mut track, .. } => {
|
|
||||||
if let Ok(value) = value.as_ref().trim().parse::<u32>() {
|
|
||||||
*track = Some(value)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
pub fn set_track (&self, value: &impl AsRef<str> ) {
|
||||||
|
self.info.write().unwrap().set_track(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl EntryInfo {
|
impl EntryInfo {
|
||||||
|
|
@ -352,4 +363,33 @@ impl EntryInfo {
|
||||||
hash: hex::encode(xxh3_64(&bytes).to_be_bytes()).into(),
|
hash: hex::encode(xxh3_64(&bytes).to_be_bytes()).into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn set_artist (&mut self, value: &impl AsRef<str> ) {
|
||||||
|
match self {
|
||||||
|
EntryInfo::Music { artist, .. } => *artist = Some(value.as_ref().into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_album (&mut self, value: &impl AsRef<str> ) {
|
||||||
|
match self {
|
||||||
|
EntryInfo::Music { album, .. } => *album = Some(value.as_ref().into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_title (&mut self, value: &impl AsRef<str> ) {
|
||||||
|
match self {
|
||||||
|
EntryInfo::Music { title, .. } => *title = Some(value.as_ref().into()),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_track (&mut self, value: &impl AsRef<str> ) {
|
||||||
|
match self {
|
||||||
|
EntryInfo::Directory { .. } => todo!("set track for whole directory"),
|
||||||
|
EntryInfo::Music { track, .. } => {
|
||||||
|
if let Ok(value) = value.as_ref().trim().parse::<u32>() {
|
||||||
|
*track = Some(value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue