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 {}
|