musicus/src/library.rs

129 lines
3.1 KiB
Rust
Raw Normal View History

2023-09-30 18:26:11 +02:00
use gtk::{glib, glib::Properties, prelude::*, subclass::prelude::*};
2023-10-07 22:49:20 +02:00
use rusqlite::{Connection, Row};
2023-09-30 18:26:11 +02:00
use std::{
2023-10-07 22:49:20 +02:00
cell::OnceCell,
path::{Path, PathBuf},
2023-09-30 18:26:11 +02:00
};
mod imp {
use super::*;
#[derive(Properties, Default)]
#[properties(wrapper_type = super::MusicusLibrary)]
pub struct MusicusLibrary {
2023-10-07 22:49:20 +02:00
#[property(get, construct_only)]
pub folder: OnceCell<String>,
pub connection: OnceCell<Connection>,
2023-09-30 18:26:11 +02:00
}
#[glib::object_subclass]
impl ObjectSubclass for MusicusLibrary {
const NAME: &'static str = "MusicusLibrary";
type Type = super::MusicusLibrary;
}
#[glib::derived_properties]
2023-10-07 22:49:20 +02:00
impl ObjectImpl for MusicusLibrary {
fn constructed(&self) {
self.parent_constructed();
let db_path = PathBuf::from(self.folder.get().unwrap()).join("musicus.db");
self.connection
.set(Connection::open(db_path).unwrap())
.unwrap();
}
}
2023-09-30 18:26:11 +02:00
}
glib::wrapper! {
pub struct MusicusLibrary(ObjectSubclass<imp::MusicusLibrary>);
}
impl MusicusLibrary {
pub fn new(path: impl AsRef<Path>) -> Self {
2023-10-07 22:49:20 +02:00
glib::Object::builder()
.property("folder", path.as_ref().to_str().unwrap())
.build()
}
2023-09-30 18:26:11 +02:00
2023-10-07 22:49:20 +02:00
pub fn query(&self, query: &LibraryQuery) -> LibraryResults {
let search = format!("%{}%", query.search);
2023-09-30 18:26:11 +02:00
2023-10-07 22:49:20 +02:00
match query {
LibraryQuery {
person: None,
ensemble: None,
work: None,
..
} => {
let persons = self.con()
.prepare("SELECT first_name, last_name FROM persons WHERE first_name LIKE ?1 OR last_name LIKE ?1 LIMIT 9")
.unwrap()
.query_map([&search], Person::from_row)
.unwrap()
.collect::<rusqlite::Result<Vec<Person>>>()
.unwrap();
2023-09-30 18:26:11 +02:00
2023-10-07 22:49:20 +02:00
LibraryResults {
persons,
..Default::default()
}
}
_ => LibraryResults::default(),
}
2023-09-30 18:26:11 +02:00
}
2023-10-07 22:49:20 +02:00
fn con(&self) -> &Connection {
2023-09-30 18:26:11 +02:00
self.imp().connection.get().unwrap()
}
}
2023-10-07 22:49:20 +02:00
#[derive(Default)]
pub struct LibraryQuery {
pub person: Option<Person>,
pub ensemble: Option<Ensemble>,
pub work: Option<Work>,
pub search: String,
}
#[derive(Default)]
pub struct LibraryResults {
pub persons: Vec<Person>,
pub ensembles: Vec<Ensemble>,
pub works: Vec<Work>,
pub recordings: Vec<Recording>,
}
impl LibraryResults {
pub fn is_empty(&self) -> bool {
self.persons.is_empty() && self.ensembles.is_empty() && self.works.is_empty()
}
}
pub struct Person {
pub first_name: String,
pub last_name: String,
}
impl Person {
pub fn from_row(row: &Row) -> rusqlite::Result<Self> {
Ok(Self {
first_name: row.get(0)?,
last_name: row.get(1)?,
})
}
pub fn name_fl(&self) -> String {
format!("{} {}", self.first_name, self.last_name)
}
}
pub struct Ensemble {
pub name: String,
}
pub struct Work {
pub title: String,
}
pub struct Recording {}