editor: Add basic work structure

This commit is contained in:
Elias Projahn 2024-06-01 13:49:13 +02:00
parent bdf8ed989d
commit 3eed04d04b
3 changed files with 51 additions and 6 deletions

View file

@ -38,6 +38,11 @@ pub fn connect(file_name: &str) -> Result<SqliteConnection> {
Ok(connection) Ok(connection)
} }
/// Generate a random string suitable as an item ID.
pub fn generate_id() -> String {
uuid::Uuid::new_v4().simple().to_string()
}
/// A single translated string value. /// A single translated string value.
#[derive(Serialize, Deserialize, AsExpression, FromSqlRow, Clone, Default, Debug)] #[derive(Serialize, Deserialize, AsExpression, FromSqlRow, Clone, Default, Debug)]
#[diesel(sql_type = Text)] #[diesel(sql_type = Text)]

View file

@ -21,7 +21,7 @@ pub struct Work {
} }
// TODO: Handle part composers. // TODO: Handle part composers.
#[derive(Clone, Debug)] #[derive(Default, Clone, Debug)]
pub struct WorkPart { pub struct WorkPart {
pub work_id: String, pub work_id: String,
pub level: u8, pub level: u8,
@ -113,6 +113,13 @@ impl PartialEq for Composer {
} }
} }
impl Eq for WorkPart {}
impl PartialEq for WorkPart {
fn eq(&self, other: &Self) -> bool {
self.work_id == other.work_id
}
}
impl Work { impl Work {
pub fn from_table(data: tables::Work, connection: &mut SqliteConnection) -> Result<Self> { pub fn from_table(data: tables::Work, connection: &mut SqliteConnection) -> Result<Self> {
fn visit_children( fn visit_children(

View file

@ -1,5 +1,8 @@
use crate::{ use crate::{
db::models::{Composer, Instrument, Person}, db::{
self,
models::{Composer, Instrument, Person, WorkPart},
},
editor::{ editor::{
instrument_selector_popover::MusicusInstrumentSelectorPopover, instrument_selector_popover::MusicusInstrumentSelectorPopover,
person_selector_popover::MusicusPersonSelectorPopover, person_selector_popover::MusicusPersonSelectorPopover,
@ -10,6 +13,7 @@ use crate::{
}; };
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::glib::{self, clone, Properties}; use gtk::glib::{self, clone, Properties};
use std::cell::{OnceCell, RefCell}; use std::cell::{OnceCell, RefCell};
@ -28,6 +32,7 @@ mod imp {
// results when finishing the process of editing the work. The composer rows // results when finishing the process of editing the work. The composer rows
// handle all state related to the composer. // handle all state related to the composer.
pub composer_rows: RefCell<Vec<MusicusWorkEditorComposerRow>>, pub composer_rows: RefCell<Vec<MusicusWorkEditorComposerRow>>,
pub parts: RefCell<Vec<WorkPart>>,
pub instruments: RefCell<Vec<Instrument>>, pub instruments: RefCell<Vec<Instrument>>,
pub persons_popover: OnceCell<MusicusPersonSelectorPopover>, pub persons_popover: OnceCell<MusicusPersonSelectorPopover>,
@ -38,6 +43,8 @@ mod imp {
#[template_child] #[template_child]
pub select_person_box: TemplateChild<gtk::Box>, pub select_person_box: TemplateChild<gtk::Box>,
#[template_child] #[template_child]
pub part_list: TemplateChild<gtk::ListBox>,
#[template_child]
pub instrument_list: TemplateChild<gtk::ListBox>, pub instrument_list: TemplateChild<gtk::ListBox>,
#[template_child] #[template_child]
pub select_instrument_box: TemplateChild<gtk::Box>, pub select_instrument_box: TemplateChild<gtk::Box>,
@ -109,9 +116,7 @@ mod imp {
remove_button.connect_clicked( remove_button.connect_clicked(
clone!(@weak obj, @weak row, @strong instrument => move |_| { clone!(@weak obj, @weak row, @strong instrument => move |_| {
obj.imp().instrument_list.remove(&row); obj.imp().instrument_list.remove(&row);
let mut instruments = obj.imp().instruments.borrow_mut(); obj.imp().instruments.borrow_mut().retain(|i| *i != instrument);
let index = instruments.iter().position(|i| *i == instrument).unwrap();
instruments.remove(index);
}), }),
); );
@ -152,7 +157,35 @@ impl MusicusWorkEditor {
#[template_callback] #[template_callback]
fn add_part(&self, _: &adw::ActionRow) { fn add_part(&self, _: &adw::ActionRow) {
todo!(); let part = WorkPart {
work_id: db::generate_id(),
..Default::default()
};
let row = adw::EntryRow::builder().title(gettext("Name")).build();
let remove_button = gtk::Button::builder()
.icon_name("user-trash-symbolic")
.valign(gtk::Align::Center)
.css_classes(["flat"])
.build();
remove_button.connect_clicked(
clone!(@weak self as obj, @weak row, @strong part => move |_| {
obj.imp().part_list.remove(&row);
obj.imp().parts.borrow_mut().retain(|p| *p != part);
}),
);
row.add_suffix(&remove_button);
self.imp()
.part_list
.insert(&row, self.imp().parts.borrow().len() as i32);
row.grab_focus();
self.imp().parts.borrow_mut().push(part);
} }
#[template_callback] #[template_callback]