Refactor module layout

This commit is contained in:
Elias Projahn 2025-03-01 09:57:01 +01:00
parent e59052a362
commit 5956b7ff15
70 changed files with 757 additions and 841 deletions

View file

@ -1,3 +1,5 @@
use std::cell::RefCell;
use gtk::{ use gtk::{
glib::{self, clone, subclass::Signal}, glib::{self, clone, subclass::Signal},
prelude::*, prelude::*,
@ -5,25 +7,23 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::RefCell;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Default)] #[derive(Default)]
pub struct MusicusActivatableRow { pub struct ActivatableRow {
pub previous_parent: RefCell<Option<gtk::ListBox>>, pub previous_parent: RefCell<Option<gtk::ListBox>>,
pub previous_signal_handler_id: RefCell<Option<glib::SignalHandlerId>>, pub previous_signal_handler_id: RefCell<Option<glib::SignalHandlerId>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusActivatableRow { impl ObjectSubclass for ActivatableRow {
const NAME: &'static str = "MusicusActivatableRow"; const NAME: &'static str = "MusicusActivatableRow";
type Type = super::MusicusActivatableRow; type Type = super::ActivatableRow;
type ParentType = gtk::ListBoxRow; type ParentType = gtk::ListBoxRow;
} }
impl ObjectImpl for MusicusActivatableRow { impl ObjectImpl for ActivatableRow {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
@ -31,7 +31,7 @@ mod imp {
obj.connect_parent_notify(clone!( obj.connect_parent_notify(clone!(
#[weak] #[weak]
obj, obj,
move |_: &super::MusicusActivatableRow| { move |_: &super::ActivatableRow| {
let previous_parent = obj.imp().previous_parent.borrow_mut().take(); let previous_parent = obj.imp().previous_parent.borrow_mut().take();
let previous_signal_handler_id = let previous_signal_handler_id =
obj.imp().previous_signal_handler_id.borrow_mut().take(); obj.imp().previous_signal_handler_id.borrow_mut().take();
@ -69,9 +69,9 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusActivatableRow {} impl WidgetImpl for ActivatableRow {}
impl ListBoxRowImpl for MusicusActivatableRow { impl ListBoxRowImpl for ActivatableRow {
fn activate(&self) { fn activate(&self) {
self.obj().emit_by_name::<()>("activated", &[]); self.obj().emit_by_name::<()>("activated", &[]);
} }
@ -81,11 +81,11 @@ mod imp {
glib::wrapper! { glib::wrapper! {
/// A simple helper widget for connecting a signal handler to a single [`gtk::ListBoxRow`] for /// A simple helper widget for connecting a signal handler to a single [`gtk::ListBoxRow`] for
/// handling activation. /// handling activation.
pub struct MusicusActivatableRow(ObjectSubclass<imp::MusicusActivatableRow>) pub struct ActivatableRow(ObjectSubclass<imp::ActivatableRow>)
@extends gtk::Widget, gtk::ListBoxRow; @extends gtk::Widget, gtk::ListBoxRow;
} }
impl MusicusActivatableRow { impl ActivatableRow {
pub fn new<W>(child: &W) -> Self pub fn new<W>(child: &W) -> Self
where where
W: IsA<gtk::Widget>, W: IsA<gtk::Widget>,

View file

@ -1,6 +1,7 @@
use gtk::{glib, subclass::prelude::*};
use std::cell::OnceCell; use std::cell::OnceCell;
use gtk::{glib, subclass::prelude::*};
use crate::db::models::Album; use crate::db::models::Album;
mod imp { mod imp {
@ -8,7 +9,7 @@ mod imp {
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/album_tile.blp")] #[template(file = "data/ui/album_tile.blp")]
pub struct MusicusAlbumTile { pub struct AlbumTile {
pub album: OnceCell<Album>, pub album: OnceCell<Album>,
#[template_child] #[template_child]
@ -16,9 +17,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusAlbumTile { impl ObjectSubclass for AlbumTile {
const NAME: &'static str = "MusicusAlbumTile"; const NAME: &'static str = "MusicusAlbumTile";
type Type = super::MusicusAlbumTile; type Type = super::AlbumTile;
type ParentType = gtk::FlowBoxChild; type ParentType = gtk::FlowBoxChild;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -30,17 +31,17 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusAlbumTile {} impl ObjectImpl for AlbumTile {}
impl WidgetImpl for MusicusAlbumTile {} impl WidgetImpl for AlbumTile {}
impl FlowBoxChildImpl for MusicusAlbumTile {} impl FlowBoxChildImpl for AlbumTile {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusAlbumTile(ObjectSubclass<imp::MusicusAlbumTile>) pub struct AlbumTile(ObjectSubclass<imp::AlbumTile>)
@extends gtk::Widget, gtk::FlowBoxChild; @extends gtk::Widget, gtk::FlowBoxChild;
} }
impl MusicusAlbumTile { impl AlbumTile {
pub fn new(album: &Album) -> Self { pub fn new(album: &Album) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();

View file

@ -2,22 +2,22 @@ use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{gio, glib}; use gtk::{gio, glib};
use crate::{config, MusicusWindow}; use crate::{config, Window};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct MusicusApplication {} pub struct Application {}
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusApplication { impl ObjectSubclass for Application {
const NAME: &'static str = "MusicusApplication"; const NAME: &'static str = "MusicusApplication";
type Type = super::MusicusApplication; type Type = super::Application;
type ParentType = adw::Application; type ParentType = adw::Application;
} }
impl ObjectImpl for MusicusApplication { impl ObjectImpl for Application {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let obj = self.obj(); let obj = self.obj();
@ -26,14 +26,14 @@ mod imp {
} }
} }
impl ApplicationImpl for MusicusApplication { impl ApplicationImpl for Application {
fn activate(&self) { fn activate(&self) {
let application = self.obj(); let application = self.obj();
let window = if let Some(window) = application.active_window() { let window = if let Some(window) = application.active_window() {
window window
} else { } else {
let window = MusicusWindow::new(&*application); let window = Window::new(&*application);
window.upcast() window.upcast()
}; };
@ -41,17 +41,17 @@ mod imp {
} }
} }
impl GtkApplicationImpl for MusicusApplication {} impl GtkApplicationImpl for Application {}
impl AdwApplicationImpl for MusicusApplication {} impl AdwApplicationImpl for Application {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusApplication(ObjectSubclass<imp::MusicusApplication>) pub struct Application(ObjectSubclass<imp::Application>)
@extends gio::Application, gtk::Application, adw::Application, @extends gio::Application, gtk::Application, adw::Application,
@implements gio::ActionGroup, gio::ActionMap; @implements gio::ActionGroup, gio::ActionMap;
} }
impl MusicusApplication { impl Application {
pub fn new() -> Self { pub fn new() -> Self {
glib::Object::builder() glib::Object::builder()
.property("application-id", config::APP_ID) .property("application-id", config::APP_ID)

View file

@ -6,12 +6,11 @@ use std::fmt::Display;
use anyhow::Result; use anyhow::Result;
use diesel::prelude::*; use diesel::prelude::*;
use gtk::glib::{self, Boxed}; use gtk::glib::{self, Boxed};
use super::{schema::*, tables, TranslatedString};
// Re-exports for tables that don't need additional information. // Re-exports for tables that don't need additional information.
pub use tables::{Instrument, Person, Role}; pub use tables::{Instrument, Person, Role};
use super::{schema::*, tables, TranslatedString};
#[derive(Boxed, Clone, Debug)] #[derive(Boxed, Clone, Debug)]
#[boxed_type(name = "MusicusWork")] #[boxed_type(name = "MusicusWork")]
pub struct Work { pub struct Work {

View file

@ -2,8 +2,7 @@
//! tables in the database schema. //! tables in the database schema.
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use diesel::prelude::*; use diesel::{prelude::*, sqlite::Sqlite};
use diesel::sqlite::Sqlite;
use gtk::glib::{self, Boxed}; use gtk::glib::{self, Boxed};
use super::{schema::*, TranslatedString}; use super::{schema::*, TranslatedString};

View file

@ -1,34 +1,28 @@
use crate::{ use std::cell::{OnceCell, RefCell};
db::models::{Album, Recording},
editor::{
recording_editor::MusicusRecordingEditor,
recording_selector_popover::RecordingSelectorPopover,
translation_editor::MusicusTranslationEditor,
},
library::MusicusLibrary,
};
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::glib::{ use gtk::glib::{self, clone, subclass::Signal, Properties};
clone, Properties,
{self, subclass::Signal},
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{
db::models::{Album, Recording},
editor::{recording::RecordingEditor, translation::TranslationEditor},
library::Library,
selector::recording::RecordingSelectorPopover,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::AlbumEditor)] #[properties(wrapper_type = super::AlbumEditor)]
#[template(file = "data/ui/album_editor.blp")] #[template(file = "data/ui/editor/album.blp")]
pub struct AlbumEditor { pub struct AlbumEditor {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub album_id: OnceCell<String>, pub album_id: OnceCell<String>,
pub recordings: RefCell<Vec<Recording>>, pub recordings: RefCell<Vec<Recording>>,
@ -36,7 +30,7 @@ mod imp {
pub recordings_popover: OnceCell<RecordingSelectorPopover>, pub recordings_popover: OnceCell<RecordingSelectorPopover>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub recordings_list: TemplateChild<gtk::ListBox>, pub recordings_list: TemplateChild<gtk::ListBox>,
#[template_child] #[template_child]
@ -52,7 +46,7 @@ mod imp {
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -86,7 +80,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
recordings_popover.connect_create(move |_| { recordings_popover.connect_create(move |_| {
let editor = MusicusRecordingEditor::new(&obj.navigation(), &obj.library(), None); let editor = RecordingEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -115,11 +109,7 @@ glib::wrapper! {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl AlbumEditor { impl AlbumEditor {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, album: Option<&Album>) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
album: Option<&Album>,
) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
.property("navigation", navigation) .property("navigation", navigation)
.property("library", library) .property("library", library)

View file

@ -5,36 +5,33 @@ use gettextrs::gettext;
use gtk::glib::{self, subclass::Signal}; use gtk::glib::{self, subclass::Signal};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{db::models::Ensemble, editor::translation::TranslationEditor, library::Library};
db::models::Ensemble, editor::translation_editor::MusicusTranslationEditor,
library::MusicusLibrary,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/ensemble_editor.blp")] #[template(file = "data/ui/editor/ensemble.blp")]
pub struct MusicusEnsembleEditor { pub struct EnsembleEditor {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub ensemble_id: OnceCell<String>, pub ensemble_id: OnceCell<String>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub save_row: TemplateChild<adw::ButtonRow>, pub save_row: TemplateChild<adw::ButtonRow>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusEnsembleEditor { impl ObjectSubclass for EnsembleEditor {
const NAME: &'static str = "MusicusEnsembleEditor"; const NAME: &'static str = "MusicusEnsembleEditor";
type Type = super::MusicusEnsembleEditor; type Type = super::EnsembleEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -44,7 +41,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusEnsembleEditor { impl ObjectImpl for EnsembleEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -56,20 +53,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusEnsembleEditor {} impl WidgetImpl for EnsembleEditor {}
impl NavigationPageImpl for MusicusEnsembleEditor {} impl NavigationPageImpl for EnsembleEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusEnsembleEditor(ObjectSubclass<imp::MusicusEnsembleEditor>) pub struct EnsembleEditor(ObjectSubclass<imp::EnsembleEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusEnsembleEditor { impl EnsembleEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
ensemble: Option<&Ensemble>, ensemble: Option<&Ensemble>,
) -> Self { ) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();

View file

@ -5,36 +5,33 @@ use gettextrs::gettext;
use gtk::glib::{self, subclass::Signal}; use gtk::glib::{self, subclass::Signal};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{db::models::Instrument, editor::translation::TranslationEditor, library::Library};
db::models::Instrument, editor::translation_editor::MusicusTranslationEditor,
library::MusicusLibrary,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/instrument_editor.blp")] #[template(file = "data/ui/editor/instrument.blp")]
pub struct MusicusInstrumentEditor { pub struct InstrumentEditor {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub instrument_id: OnceCell<String>, pub instrument_id: OnceCell<String>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub save_row: TemplateChild<adw::ButtonRow>, pub save_row: TemplateChild<adw::ButtonRow>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusInstrumentEditor { impl ObjectSubclass for InstrumentEditor {
const NAME: &'static str = "MusicusInstrumentEditor"; const NAME: &'static str = "MusicusInstrumentEditor";
type Type = super::MusicusInstrumentEditor; type Type = super::InstrumentEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -44,7 +41,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusInstrumentEditor { impl ObjectImpl for InstrumentEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -56,20 +53,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusInstrumentEditor {} impl WidgetImpl for InstrumentEditor {}
impl NavigationPageImpl for MusicusInstrumentEditor {} impl NavigationPageImpl for InstrumentEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusInstrumentEditor(ObjectSubclass<imp::MusicusInstrumentEditor>) pub struct InstrumentEditor(ObjectSubclass<imp::InstrumentEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusInstrumentEditor { impl InstrumentEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
instrument: Option<&Instrument>, instrument: Option<&Instrument>,
) -> Self { ) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();

View file

@ -1,24 +1,10 @@
pub mod activatable_row; pub mod album;
pub mod album_editor; pub mod ensemble;
pub mod ensemble_editor; pub mod instrument;
pub mod ensemble_selector_popover; pub mod person;
pub mod instrument_editor; pub mod recording;
pub mod instrument_selector_popover; pub mod role;
pub mod performer_role_selector_popover; pub mod tracks;
pub mod person_editor; pub mod translation;
pub mod person_selector_popover;
pub mod recording_editor;
pub mod recording_editor_ensemble_row;
pub mod recording_editor_performer_row;
pub mod recording_selector_popover;
pub mod role_editor;
pub mod role_selector_popover;
pub mod tracks_editor;
pub mod tracks_editor_parts_popover;
pub mod tracks_editor_track_row;
pub mod translation_editor;
pub mod translation_entry; pub mod translation_entry;
pub mod work_editor; pub mod work;
pub mod work_editor_composer_row;
pub mod work_editor_part_row;
pub mod work_selector_popover;

View file

@ -5,36 +5,33 @@ use gettextrs::gettext;
use gtk::glib::{self, subclass::Signal}; use gtk::glib::{self, subclass::Signal};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{db::models::Person, editor::translation::TranslationEditor, library::Library};
db::models::Person, editor::translation_editor::MusicusTranslationEditor,
library::MusicusLibrary,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/person_editor.blp")] #[template(file = "data/ui/editor/person.blp")]
pub struct MusicusPersonEditor { pub struct PersonEditor {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub person_id: OnceCell<String>, pub person_id: OnceCell<String>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub save_row: TemplateChild<adw::ButtonRow>, pub save_row: TemplateChild<adw::ButtonRow>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusPersonEditor { impl ObjectSubclass for PersonEditor {
const NAME: &'static str = "MusicusPersonEditor"; const NAME: &'static str = "MusicusPersonEditor";
type Type = super::MusicusPersonEditor; type Type = super::PersonEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -44,7 +41,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusPersonEditor { impl ObjectImpl for PersonEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -56,20 +53,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusPersonEditor {} impl WidgetImpl for PersonEditor {}
impl NavigationPageImpl for MusicusPersonEditor {} impl NavigationPageImpl for PersonEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusPersonEditor(ObjectSubclass<imp::MusicusPersonEditor>) pub struct PersonEditor(ObjectSubclass<imp::PersonEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusPersonEditor { impl PersonEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
person: Option<&Person>, person: Option<&Person>,
) -> Self { ) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();

View file

@ -1,47 +1,46 @@
mod ensemble_row;
mod performer_row;
use std::cell::{OnceCell, RefCell}; use std::cell::{OnceCell, RefCell};
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use ensemble_row::RecordingEditorEnsembleRow;
use gettextrs::gettext; use gettextrs::gettext;
use gtk::glib::{self, clone, subclass::Signal, Properties}; use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use performer_row::RecordingEditorPerformerRow;
use crate::{ use crate::{
db::models::{Ensemble, EnsemblePerformer, Performer, Person, Recording, Work}, db::models::{Ensemble, EnsemblePerformer, Performer, Person, Recording, Work},
editor::{ editor::{ensemble::EnsembleEditor, person::PersonEditor, work::WorkEditor},
ensemble_editor::MusicusEnsembleEditor, library::Library,
ensemble_selector_popover::MusicusEnsembleSelectorPopover, selector::{
person_editor::MusicusPersonEditor, person_selector_popover::MusicusPersonSelectorPopover, ensemble::EnsembleSelectorPopover, person::PersonSelectorPopover, work::WorkSelectorPopover,
recording_editor_ensemble_row::MusicusRecordingEditorEnsembleRow,
recording_editor_performer_row::MusicusRecordingEditorPerformerRow,
work_selector_popover::MusicusWorkSelectorPopover,
}, },
library::MusicusLibrary,
}; };
mod imp { mod imp {
use crate::editor::work_editor::MusicusWorkEditor;
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusRecordingEditor)] #[properties(wrapper_type = super::RecordingEditor)]
#[template(file = "data/ui/recording_editor.blp")] #[template(file = "data/ui/editor/recording.blp")]
pub struct MusicusRecordingEditor { pub struct RecordingEditor {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub recording_id: OnceCell<String>, pub recording_id: OnceCell<String>,
pub work: RefCell<Option<Work>>, pub work: RefCell<Option<Work>>,
pub performer_rows: RefCell<Vec<MusicusRecordingEditorPerformerRow>>, pub performer_rows: RefCell<Vec<RecordingEditorPerformerRow>>,
pub ensemble_rows: RefCell<Vec<MusicusRecordingEditorEnsembleRow>>, pub ensemble_rows: RefCell<Vec<RecordingEditorEnsembleRow>>,
pub work_selector_popover: OnceCell<MusicusWorkSelectorPopover>, pub work_selector_popover: OnceCell<WorkSelectorPopover>,
pub persons_popover: OnceCell<MusicusPersonSelectorPopover>, pub persons_popover: OnceCell<PersonSelectorPopover>,
pub ensembles_popover: OnceCell<MusicusEnsembleSelectorPopover>, pub ensembles_popover: OnceCell<EnsembleSelectorPopover>,
#[template_child] #[template_child]
pub work_row: TemplateChild<adw::ActionRow>, pub work_row: TemplateChild<adw::ActionRow>,
@ -62,9 +61,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRecordingEditor { impl ObjectSubclass for RecordingEditor {
const NAME: &'static str = "MusicusRecordingEditor"; const NAME: &'static str = "MusicusRecordingEditor";
type Type = super::MusicusRecordingEditor; type Type = super::RecordingEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -78,7 +77,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusRecordingEditor { impl ObjectImpl for RecordingEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -92,8 +91,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let work_selector_popover = let work_selector_popover = WorkSelectorPopover::new(self.library.get().unwrap());
MusicusWorkSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone(); let obj = self.obj().clone();
work_selector_popover.connect_selected(move |_, work| { work_selector_popover.connect_selected(move |_, work| {
@ -102,7 +100,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
work_selector_popover.connect_create(move |_| { work_selector_popover.connect_create(move |_| {
let editor = MusicusWorkEditor::new(&obj.navigation(), &obj.library(), None, false); let editor = WorkEditor::new(&obj.navigation(), &obj.library(), None, false);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -120,7 +118,7 @@ mod imp {
.set(work_selector_popover) .set(work_selector_popover)
.unwrap(); .unwrap();
let persons_popover = MusicusPersonSelectorPopover::new(self.library.get().unwrap()); let persons_popover = PersonSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone(); let obj = self.obj().clone();
persons_popover.connect_person_selected(move |_, person| { persons_popover.connect_person_selected(move |_, person| {
@ -129,7 +127,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
persons_popover.connect_create(move |_| { persons_popover.connect_create(move |_| {
let editor = MusicusPersonEditor::new(&obj.navigation(), &obj.library(), None); let editor = PersonEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -145,8 +143,7 @@ mod imp {
self.select_person_box.append(&persons_popover); self.select_person_box.append(&persons_popover);
self.persons_popover.set(persons_popover).unwrap(); self.persons_popover.set(persons_popover).unwrap();
let ensembles_popover = let ensembles_popover = EnsembleSelectorPopover::new(self.library.get().unwrap());
MusicusEnsembleSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone(); let obj = self.obj().clone();
ensembles_popover.connect_ensemble_selected(move |_, ensemble| { ensembles_popover.connect_ensemble_selected(move |_, ensemble| {
@ -155,7 +152,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
ensembles_popover.connect_create(move |_| { ensembles_popover.connect_create(move |_| {
let editor = MusicusEnsembleEditor::new(&obj.navigation(), &obj.library(), None); let editor = EnsembleEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -173,20 +170,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRecordingEditor {} impl WidgetImpl for RecordingEditor {}
impl NavigationPageImpl for MusicusRecordingEditor {} impl NavigationPageImpl for RecordingEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRecordingEditor(ObjectSubclass<imp::MusicusRecordingEditor>) pub struct RecordingEditor(ObjectSubclass<imp::RecordingEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusRecordingEditor { impl RecordingEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
recording: Option<&Recording>, recording: Option<&Recording>,
) -> Self { ) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
@ -267,8 +264,7 @@ impl MusicusRecordingEditor {
} }
fn add_performer_row(&self, performer: Performer) { fn add_performer_row(&self, performer: Performer) {
let row = let row = RecordingEditorPerformerRow::new(&self.navigation(), &self.library(), performer);
MusicusRecordingEditorPerformerRow::new(&self.navigation(), &self.library(), performer);
row.connect_remove(clone!( row.connect_remove(clone!(
#[weak(rename_to = this)] #[weak(rename_to = this)]
@ -296,7 +292,7 @@ impl MusicusRecordingEditor {
} }
fn add_ensemble_row(&self, ensemble_performer: EnsemblePerformer) { fn add_ensemble_row(&self, ensemble_performer: EnsemblePerformer) {
let row = MusicusRecordingEditorEnsembleRow::new( let row = RecordingEditorEnsembleRow::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
ensemble_performer, ensemble_performer,

View file

@ -5,26 +5,25 @@ use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{
db::models::EnsemblePerformer, db::models::EnsemblePerformer, editor::role::RoleEditor, library::Library,
editor::{role_editor::MusicusRoleEditor, role_selector_popover::MusicusRoleSelectorPopover}, selector::role::RoleSelectorPopover,
library::MusicusLibrary,
}; };
mod imp { mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusRecordingEditorEnsembleRow)] #[properties(wrapper_type = super::RecordingEditorEnsembleRow)]
#[template(file = "data/ui/recording_editor_ensemble_row.blp")] #[template(file = "data/ui/editor/recording/ensemble_row.blp")]
pub struct MusicusRecordingEditorEnsembleRow { pub struct RecordingEditorEnsembleRow {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub ensemble: RefCell<Option<EnsemblePerformer>>, pub ensemble: RefCell<Option<EnsemblePerformer>>,
pub role_popover: OnceCell<MusicusRoleSelectorPopover>, pub role_popover: OnceCell<RoleSelectorPopover>,
#[template_child] #[template_child]
pub role_label: TemplateChild<gtk::Label>, pub role_label: TemplateChild<gtk::Label>,
@ -33,9 +32,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRecordingEditorEnsembleRow { impl ObjectSubclass for RecordingEditorEnsembleRow {
const NAME: &'static str = "MusicusRecordingEditorEnsembleRow"; const NAME: &'static str = "MusicusRecordingEditorEnsembleRow";
type Type = super::MusicusRecordingEditorEnsembleRow; type Type = super::RecordingEditorEnsembleRow;
type ParentType = adw::ActionRow; type ParentType = adw::ActionRow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,7 +48,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusRecordingEditorEnsembleRow { impl ObjectImpl for RecordingEditorEnsembleRow {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -60,7 +59,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let role_popover = MusicusRoleSelectorPopover::new(self.library.get().unwrap()); let role_popover = RoleSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_role_selected(move |_, role| { role_popover.connect_role_selected(move |_, role| {
@ -72,7 +71,7 @@ mod imp {
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_create(move |_| { role_popover.connect_create(move |_| {
let editor = MusicusRoleEditor::new(&obj.navigation(), &obj.library(), None); let editor = RoleEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -93,22 +92,22 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRecordingEditorEnsembleRow {} impl WidgetImpl for RecordingEditorEnsembleRow {}
impl ListBoxRowImpl for MusicusRecordingEditorEnsembleRow {} impl ListBoxRowImpl for RecordingEditorEnsembleRow {}
impl PreferencesRowImpl for MusicusRecordingEditorEnsembleRow {} impl PreferencesRowImpl for RecordingEditorEnsembleRow {}
impl ActionRowImpl for MusicusRecordingEditorEnsembleRow {} impl ActionRowImpl for RecordingEditorEnsembleRow {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRecordingEditorEnsembleRow(ObjectSubclass<imp::MusicusRecordingEditorEnsembleRow>) pub struct RecordingEditorEnsembleRow(ObjectSubclass<imp::RecordingEditorEnsembleRow>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow; @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusRecordingEditorEnsembleRow { impl RecordingEditorEnsembleRow {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
ensemble: EnsemblePerformer, ensemble: EnsemblePerformer,
) -> Self { ) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()

View file

@ -5,31 +5,26 @@ use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{
db::models::Performer, db::models::Performer, editor::role::RoleEditor, library::Library,
editor::{ selector::performer_role::PerformerRoleSelectorPopover,
performer_role_selector_popover::MusicusPerformerRoleSelectorPopover,
role_editor::MusicusRoleEditor,
},
library::MusicusLibrary,
}; };
mod imp { mod imp {
use crate::editor::instrument_editor::MusicusInstrumentEditor;
use super::*; use super::*;
use crate::editor::instrument::InstrumentEditor;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusRecordingEditorPerformerRow)] #[properties(wrapper_type = super::RecordingEditorPerformerRow)]
#[template(file = "data/ui/recording_editor_performer_row.blp")] #[template(file = "data/ui/editor/recording/performer_row.blp")]
pub struct MusicusRecordingEditorPerformerRow { pub struct RecordingEditorPerformerRow {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub performer: RefCell<Option<Performer>>, pub performer: RefCell<Option<Performer>>,
pub role_popover: OnceCell<MusicusPerformerRoleSelectorPopover>, pub role_popover: OnceCell<PerformerRoleSelectorPopover>,
#[template_child] #[template_child]
pub role_label: TemplateChild<gtk::Label>, pub role_label: TemplateChild<gtk::Label>,
@ -38,9 +33,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRecordingEditorPerformerRow { impl ObjectSubclass for RecordingEditorPerformerRow {
const NAME: &'static str = "MusicusRecordingEditorPerformerRow"; const NAME: &'static str = "MusicusRecordingEditorPerformerRow";
type Type = super::MusicusRecordingEditorPerformerRow; type Type = super::RecordingEditorPerformerRow;
type ParentType = adw::ActionRow; type ParentType = adw::ActionRow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -54,7 +49,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusRecordingEditorPerformerRow { impl ObjectImpl for RecordingEditorPerformerRow {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -65,8 +60,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let role_popover = let role_popover = PerformerRoleSelectorPopover::new(self.library.get().unwrap());
MusicusPerformerRoleSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_selected(move |_, role, instrument| { role_popover.connect_selected(move |_, role, instrument| {
@ -85,7 +79,7 @@ mod imp {
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_create_role(move |_| { role_popover.connect_create_role(move |_| {
let editor = MusicusRoleEditor::new(&obj.navigation(), &obj.library(), None); let editor = RoleEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -104,7 +98,7 @@ mod imp {
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_create_instrument(move |_| { role_popover.connect_create_instrument(move |_| {
let editor = MusicusInstrumentEditor::new(&obj.navigation(), &obj.library(), None); let editor = InstrumentEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -126,24 +120,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRecordingEditorPerformerRow {} impl WidgetImpl for RecordingEditorPerformerRow {}
impl ListBoxRowImpl for MusicusRecordingEditorPerformerRow {} impl ListBoxRowImpl for RecordingEditorPerformerRow {}
impl PreferencesRowImpl for MusicusRecordingEditorPerformerRow {} impl PreferencesRowImpl for RecordingEditorPerformerRow {}
impl ActionRowImpl for MusicusRecordingEditorPerformerRow {} impl ActionRowImpl for RecordingEditorPerformerRow {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRecordingEditorPerformerRow(ObjectSubclass<imp::MusicusRecordingEditorPerformerRow>) pub struct RecordingEditorPerformerRow(ObjectSubclass<imp::RecordingEditorPerformerRow>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow; @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusRecordingEditorPerformerRow { impl RecordingEditorPerformerRow {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, performer: Performer) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
performer: Performer,
) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
.property("navigation", navigation) .property("navigation", navigation)
.property("library", library) .property("library", library)

View file

@ -5,34 +5,32 @@ use gettextrs::gettext;
use gtk::glib::{self, subclass::Signal}; use gtk::glib::{self, subclass::Signal};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{db::models::Role, editor::translation::TranslationEditor, library::Library};
db::models::Role, editor::translation_editor::MusicusTranslationEditor, library::MusicusLibrary,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/role_editor.blp")] #[template(file = "data/ui/editor/role.blp")]
pub struct MusicusRoleEditor { pub struct RoleEditor {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub role_id: OnceCell<String>, pub role_id: OnceCell<String>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub save_row: TemplateChild<adw::ButtonRow>, pub save_row: TemplateChild<adw::ButtonRow>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRoleEditor { impl ObjectSubclass for RoleEditor {
const NAME: &'static str = "MusicusRoleEditor"; const NAME: &'static str = "MusicusRoleEditor";
type Type = super::MusicusRoleEditor; type Type = super::RoleEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -42,7 +40,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusRoleEditor { impl ObjectImpl for RoleEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -54,22 +52,18 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRoleEditor {} impl WidgetImpl for RoleEditor {}
impl NavigationPageImpl for MusicusRoleEditor {} impl NavigationPageImpl for RoleEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRoleEditor(ObjectSubclass<imp::MusicusRoleEditor>) pub struct RoleEditor(ObjectSubclass<imp::RoleEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusRoleEditor { impl RoleEditor {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, role: Option<&Role>) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
role: Option<&Role>,
) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
obj.imp().navigation.set(navigation.to_owned()).unwrap(); obj.imp().navigation.set(navigation.to_owned()).unwrap();

View file

@ -1,12 +1,9 @@
use super::tracks_editor_track_row::{TrackLocation, TracksEditorTrackData}; mod parts_popover;
use crate::{ mod track_row;
db::models::{Recording, Track, Work},
editor::{ use std::{
recording_editor::MusicusRecordingEditor, cell::{OnceCell, RefCell},
recording_selector_popover::RecordingSelectorPopover, path::PathBuf,
tracks_editor_track_row::TracksEditorTrackRow,
},
library::MusicusLibrary,
}; };
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
@ -16,10 +13,13 @@ use gtk::{
glib::{self, clone, subclass::Signal, Properties}, glib::{self, clone, subclass::Signal, Properties},
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use track_row::{TrackLocation, TracksEditorTrackData, TracksEditorTrackRow};
use std::{ use crate::{
cell::{OnceCell, RefCell}, db::models::{Recording, Track, Work},
path::PathBuf, editor::recording::RecordingEditor,
library::Library,
selector::recording::RecordingSelectorPopover,
}; };
mod imp { mod imp {
@ -27,12 +27,12 @@ mod imp {
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::TracksEditor)] #[properties(wrapper_type = super::TracksEditor)]
#[template(file = "data/ui/tracks_editor.blp")] #[template(file = "data/ui/editor/tracks.blp")]
pub struct TracksEditor { pub struct TracksEditor {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub recording: RefCell<Option<Recording>>, pub recording: RefCell<Option<Recording>>,
pub recordings_popover: OnceCell<RecordingSelectorPopover>, pub recordings_popover: OnceCell<RecordingSelectorPopover>,
@ -91,11 +91,8 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
recordings_popover.connect_create(move |_| { recordings_popover.connect_create(move |_| {
let editor = MusicusRecordingEditor::new( let editor =
obj.imp().navigation.get().unwrap(), RecordingEditor::new(obj.imp().navigation.get().unwrap(), &obj.library(), None);
&obj.library(),
None,
);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -135,7 +132,7 @@ glib::wrapper! {
impl TracksEditor { impl TracksEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
recording: Option<Recording>, recording: Option<Recording>,
) -> Self { ) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()

View file

@ -1,5 +1,4 @@
use super::activatable_row::MusicusActivatableRow; use std::cell::{OnceCell, RefCell};
use crate::db::models::Work;
use gtk::{ use gtk::{
glib::{self, subclass::Signal}, glib::{self, subclass::Signal},
@ -8,13 +7,13 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{activatable_row::ActivatableRow, db::models::Work};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/tracks_editor_parts_popover.blp")] #[template(file = "data/ui/editor/tracks/parts_popover.blp")]
pub struct TracksEditorPartsPopover { pub struct TracksEditorPartsPopover {
pub parts: OnceCell<Vec<Work>>, pub parts: OnceCell<Vec<Work>>,
pub parts_filtered: RefCell<Vec<Work>>, pub parts_filtered: RefCell<Vec<Work>>,
@ -47,8 +46,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::TracksEditorPartsPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().search_entry.set_text(""); obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus(); obj.imp().search_entry.grab_focus();
@ -143,7 +141,7 @@ impl TracksEditorPartsPopover {
imp.list_box.remove_all(); imp.list_box.remove_all();
for part in &parts_filtered { for part in &parts_filtered {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(part.to_string()) .label(part.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -154,7 +152,7 @@ impl TracksEditorPartsPopover {
let part = part.clone(); let part = part.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(part.clone()); obj.select(part.clone());
}); });

View file

@ -1,7 +1,6 @@
use crate::{ use std::{
db::models::{Recording, Track, Work}, cell::{OnceCell, RefCell},
editor::tracks_editor_parts_popover::TracksEditorPartsPopover, path::PathBuf,
library::MusicusLibrary,
}; };
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
@ -10,9 +9,10 @@ use gettextrs::gettext;
use gtk::glib::{self, clone, subclass::Signal, Properties}; use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::{ use super::parts_popover::TracksEditorPartsPopover;
cell::{OnceCell, RefCell}, use crate::{
path::PathBuf, db::models::{Recording, Track, Work},
library::Library,
}; };
mod imp { mod imp {
@ -20,12 +20,12 @@ mod imp {
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::TracksEditorTrackRow)] #[properties(wrapper_type = super::TracksEditorTrackRow)]
#[template(file = "data/ui/tracks_editor_track_row.blp")] #[template(file = "data/ui/editor/tracks/track_row.blp")]
pub struct TracksEditorTrackRow { pub struct TracksEditorTrackRow {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub recording: OnceCell<Recording>, pub recording: OnceCell<Recording>,
pub track_data: RefCell<TracksEditorTrackData>, pub track_data: RefCell<TracksEditorTrackData>,
@ -79,7 +79,7 @@ glib::wrapper! {
impl TracksEditorTrackRow { impl TracksEditorTrackRow {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
recording: Recording, recording: Recording,
track_data: TracksEditorTrackData, track_data: TracksEditorTrackData,
) -> Self { ) -> Self {

View file

@ -1,31 +1,28 @@
use std::cell::RefCell; use std::{cell::RefCell, collections::HashMap};
use std::collections::HashMap;
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gtk::glib; use gtk::glib;
use crate::db::TranslatedString; use crate::{db::TranslatedString, editor::translation_entry::TranslationEntry, util};
use crate::editor::translation_entry::MusicusTranslationEntry;
use crate::util;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/translation_editor.blp")] #[template(file = "data/ui/editor/translation.blp")]
pub struct MusicusTranslationEditor { pub struct TranslationEditor {
#[template_child] #[template_child]
pub list_box: TemplateChild<gtk::ListBox>, pub list_box: TemplateChild<gtk::ListBox>,
#[template_child] #[template_child]
pub entry_row: TemplateChild<adw::EntryRow>, pub entry_row: TemplateChild<adw::EntryRow>,
pub translation_entries: RefCell<Vec<MusicusTranslationEntry>>, pub translation_entries: RefCell<Vec<TranslationEntry>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusTranslationEditor { impl ObjectSubclass for TranslationEditor {
const NAME: &'static str = "MusicusTranslationEditor"; const NAME: &'static str = "MusicusTranslationEditor";
type Type = super::MusicusTranslationEditor; type Type = super::TranslationEditor;
type ParentType = adw::Bin; type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -38,23 +35,23 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusTranslationEditor { impl ObjectImpl for TranslationEditor {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
} }
} }
impl WidgetImpl for MusicusTranslationEditor {} impl WidgetImpl for TranslationEditor {}
impl BinImpl for MusicusTranslationEditor {} impl BinImpl for TranslationEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusTranslationEditor(ObjectSubclass<imp::MusicusTranslationEditor>) pub struct TranslationEditor(ObjectSubclass<imp::TranslationEditor>)
@extends gtk::Widget, adw::PreferencesGroup; @extends gtk::Widget, adw::PreferencesGroup;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusTranslationEditor { impl TranslationEditor {
pub fn new() -> Self { pub fn new() -> Self {
glib::Object::new() glib::Object::new()
} }
@ -89,7 +86,7 @@ impl MusicusTranslationEditor {
} }
fn add_entry(&self, lang: &str, translation: &str) { fn add_entry(&self, lang: &str, translation: &str) {
let entry = MusicusTranslationEntry::new(lang, translation); let entry = TranslationEntry::new(lang, translation);
let obj = self.clone(); let obj = self.clone();
entry.connect_remove(move |entry| { entry.connect_remove(move |entry| {

View file

@ -6,8 +6,8 @@ mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/translation_entry.blp")] #[template(file = "data/ui/editor/translation_entry.blp")]
pub struct MusicusTranslationEntry { pub struct TranslationEntry {
#[template_child] #[template_child]
pub lang_popover: TemplateChild<gtk::Popover>, pub lang_popover: TemplateChild<gtk::Popover>,
#[template_child] #[template_child]
@ -15,9 +15,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusTranslationEntry { impl ObjectSubclass for TranslationEntry {
const NAME: &'static str = "MusicusTranslationEntry"; const NAME: &'static str = "MusicusTranslationEntry";
type Type = super::MusicusTranslationEntry; type Type = super::TranslationEntry;
type ParentType = adw::EntryRow; type ParentType = adw::EntryRow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -30,7 +30,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusTranslationEntry { impl ObjectImpl for TranslationEntry {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -43,21 +43,21 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusTranslationEntry {} impl WidgetImpl for TranslationEntry {}
impl ListBoxRowImpl for MusicusTranslationEntry {} impl ListBoxRowImpl for TranslationEntry {}
impl PreferencesRowImpl for MusicusTranslationEntry {} impl PreferencesRowImpl for TranslationEntry {}
impl EntryRowImpl for MusicusTranslationEntry {} impl EntryRowImpl for TranslationEntry {}
impl EditableImpl for MusicusTranslationEntry {} impl EditableImpl for TranslationEntry {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusTranslationEntry(ObjectSubclass<imp::MusicusTranslationEntry>) pub struct TranslationEntry(ObjectSubclass<imp::TranslationEntry>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::EntryRow, @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::EntryRow,
@implements gtk::Editable; @implements gtk::Editable;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusTranslationEntry { impl TranslationEntry {
pub fn new(lang: &str, translation: &str) -> Self { pub fn new(lang: &str, translation: &str) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
obj.set_text(translation); obj.set_text(translation);

View file

@ -1,41 +1,37 @@
mod composer_row;
mod part_row;
use std::cell::{Cell, OnceCell, RefCell};
use adw::{prelude::*, subclass::prelude::*};
use composer_row::WorkEditorComposerRow;
use gettextrs::gettext;
use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy;
use part_row::WorkEditorPartRow;
use crate::{ use crate::{
db::{ db::{
self, self,
models::{Composer, Instrument, Person, Work}, models::{Composer, Instrument, Person, Work},
}, },
editor::{ editor::{instrument::InstrumentEditor, person::PersonEditor, translation::TranslationEditor},
instrument_editor::MusicusInstrumentEditor, library::Library,
instrument_selector_popover::MusicusInstrumentSelectorPopover, selector::{instrument::InstrumentSelectorPopover, person::PersonSelectorPopover},
person_editor::MusicusPersonEditor, person_selector_popover::MusicusPersonSelectorPopover,
translation_editor::MusicusTranslationEditor,
work_editor_composer_row::MusicusWorkEditorComposerRow,
work_editor_part_row::MusicusWorkEditorPartRow,
},
library::MusicusLibrary,
}; };
use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::glib::{
clone, Properties,
{self, subclass::Signal},
};
use once_cell::sync::Lazy;
use std::cell::{Cell, OnceCell, RefCell};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusWorkEditor)] #[properties(wrapper_type = super::WorkEditor)]
#[template(file = "data/ui/work_editor.blp")] #[template(file = "data/ui/editor/work.blp")]
pub struct MusicusWorkEditor { pub struct WorkEditor {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub work_id: OnceCell<String>, pub work_id: OnceCell<String>,
pub is_part_editor: Cell<bool>, pub is_part_editor: Cell<bool>,
@ -43,16 +39,16 @@ mod imp {
// Holding a reference to each composer row is the simplest way to enumerate all // Holding a reference to each composer row is the simplest way to enumerate all
// 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<WorkEditorComposerRow>>,
pub part_rows: RefCell<Vec<MusicusWorkEditorPartRow>>, pub part_rows: RefCell<Vec<WorkEditorPartRow>>,
pub instruments: RefCell<Vec<Instrument>>, pub instruments: RefCell<Vec<Instrument>>,
pub persons_popover: OnceCell<MusicusPersonSelectorPopover>, pub persons_popover: OnceCell<PersonSelectorPopover>,
pub instruments_popover: OnceCell<MusicusInstrumentSelectorPopover>, pub instruments_popover: OnceCell<InstrumentSelectorPopover>,
#[template_child] #[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>, pub name_editor: TemplateChild<TranslationEditor>,
#[template_child] #[template_child]
pub composer_list: TemplateChild<gtk::ListBox>, pub composer_list: TemplateChild<gtk::ListBox>,
#[template_child] #[template_child]
@ -68,13 +64,13 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWorkEditor { impl ObjectSubclass for WorkEditor {
const NAME: &'static str = "MusicusWorkEditor"; const NAME: &'static str = "MusicusWorkEditor";
type Type = super::MusicusWorkEditor; type Type = super::WorkEditor;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type(); TranslationEditor::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -85,7 +81,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusWorkEditor { impl ObjectImpl for WorkEditor {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created") vec![Signal::builder("created")
@ -99,7 +95,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let persons_popover = MusicusPersonSelectorPopover::new(self.library.get().unwrap()); let persons_popover = PersonSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone(); let obj = self.obj().clone();
persons_popover.connect_person_selected(move |_, person| { persons_popover.connect_person_selected(move |_, person| {
@ -108,7 +104,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
persons_popover.connect_create(move |_| { persons_popover.connect_create(move |_| {
let editor = MusicusPersonEditor::new(&obj.navigation(), &obj.library(), None); let editor = PersonEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -124,8 +120,7 @@ mod imp {
self.select_person_box.append(&persons_popover); self.select_person_box.append(&persons_popover);
self.persons_popover.set(persons_popover).unwrap(); self.persons_popover.set(persons_popover).unwrap();
let instruments_popover = let instruments_popover = InstrumentSelectorPopover::new(self.library.get().unwrap());
MusicusInstrumentSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone(); let obj = self.obj().clone();
instruments_popover.connect_instrument_selected(move |_, instrument| { instruments_popover.connect_instrument_selected(move |_, instrument| {
@ -134,7 +129,7 @@ mod imp {
let obj = self.obj().clone(); let obj = self.obj().clone();
instruments_popover.connect_create(move |_| { instruments_popover.connect_create(move |_| {
let editor = MusicusInstrumentEditor::new(&obj.navigation(), &obj.library(), None); let editor = InstrumentEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -152,20 +147,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWorkEditor {} impl WidgetImpl for WorkEditor {}
impl NavigationPageImpl for MusicusWorkEditor {} impl NavigationPageImpl for WorkEditor {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWorkEditor(ObjectSubclass<imp::MusicusWorkEditor>) pub struct WorkEditor(ObjectSubclass<imp::WorkEditor>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWorkEditor { impl WorkEditor {
pub fn new( pub fn new(
navigation: &adw::NavigationView, navigation: &adw::NavigationView,
library: &MusicusLibrary, library: &Library,
work: Option<&Work>, work: Option<&Work>,
is_part_editor: bool, is_part_editor: bool,
) -> Self { ) -> Self {
@ -218,7 +213,7 @@ impl MusicusWorkEditor {
#[template_callback] #[template_callback]
fn add_part(&self) { fn add_part(&self) {
let editor = MusicusWorkEditor::new(&self.navigation(), &self.library(), None, true); let editor = WorkEditor::new(&self.navigation(), &self.library(), None, true);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak(rename_to = this)] #[weak(rename_to = this)]
@ -243,7 +238,7 @@ impl MusicusWorkEditor {
} }
fn add_part_row(&self, part: Work) { fn add_part_row(&self, part: Work) {
let row = MusicusWorkEditorPartRow::new(&self.navigation(), &self.library(), part); let row = WorkEditorPartRow::new(&self.navigation(), &self.library(), part);
row.connect_remove(clone!( row.connect_remove(clone!(
#[weak(rename_to = this)] #[weak(rename_to = this)]
@ -262,7 +257,7 @@ impl MusicusWorkEditor {
} }
fn add_composer_row(&self, composer: Composer) { fn add_composer_row(&self, composer: Composer) {
let row = MusicusWorkEditorComposerRow::new(&self.navigation(), &self.library(), composer); let row = WorkEditorComposerRow::new(&self.navigation(), &self.library(), composer);
row.connect_remove(clone!( row.connect_remove(clone!(
#[weak(rename_to = this)] #[weak(rename_to = this)]

View file

@ -5,26 +5,25 @@ use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::{ use crate::{
db::models::Composer, db::models::Composer, editor::role::RoleEditor, library::Library,
editor::{role_editor::MusicusRoleEditor, role_selector_popover::MusicusRoleSelectorPopover}, selector::role::RoleSelectorPopover,
library::MusicusLibrary,
}; };
mod imp { mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusWorkEditorComposerRow)] #[properties(wrapper_type = super::WorkEditorComposerRow)]
#[template(file = "data/ui/work_editor_composer_row.blp")] #[template(file = "data/ui/editor/work/composer_row.blp")]
pub struct MusicusWorkEditorComposerRow { pub struct WorkEditorComposerRow {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub composer: RefCell<Option<Composer>>, pub composer: RefCell<Option<Composer>>,
pub role_popover: OnceCell<MusicusRoleSelectorPopover>, pub role_popover: OnceCell<RoleSelectorPopover>,
#[template_child] #[template_child]
pub role_label: TemplateChild<gtk::Label>, pub role_label: TemplateChild<gtk::Label>,
@ -33,9 +32,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWorkEditorComposerRow { impl ObjectSubclass for WorkEditorComposerRow {
const NAME: &'static str = "MusicusWorkEditorComposerRow"; const NAME: &'static str = "MusicusWorkEditorComposerRow";
type Type = super::MusicusWorkEditorComposerRow; type Type = super::WorkEditorComposerRow;
type ParentType = adw::ActionRow; type ParentType = adw::ActionRow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,7 +48,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusWorkEditorComposerRow { impl ObjectImpl for WorkEditorComposerRow {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -60,7 +59,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
let role_popover = MusicusRoleSelectorPopover::new(self.library.get().unwrap()); let role_popover = RoleSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_role_selected(move |_, role| { role_popover.connect_role_selected(move |_, role| {
@ -72,7 +71,7 @@ mod imp {
let obj = self.obj().to_owned(); let obj = self.obj().to_owned();
role_popover.connect_create(move |_| { role_popover.connect_create(move |_| {
let editor = MusicusRoleEditor::new(&obj.navigation(), &obj.library(), None); let editor = RoleEditor::new(&obj.navigation(), &obj.library(), None);
editor.connect_created(clone!( editor.connect_created(clone!(
#[weak] #[weak]
@ -93,24 +92,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWorkEditorComposerRow {} impl WidgetImpl for WorkEditorComposerRow {}
impl ListBoxRowImpl for MusicusWorkEditorComposerRow {} impl ListBoxRowImpl for WorkEditorComposerRow {}
impl PreferencesRowImpl for MusicusWorkEditorComposerRow {} impl PreferencesRowImpl for WorkEditorComposerRow {}
impl ActionRowImpl for MusicusWorkEditorComposerRow {} impl ActionRowImpl for WorkEditorComposerRow {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWorkEditorComposerRow(ObjectSubclass<imp::MusicusWorkEditorComposerRow>) pub struct WorkEditorComposerRow(ObjectSubclass<imp::WorkEditorComposerRow>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow; @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWorkEditorComposerRow { impl WorkEditorComposerRow {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, composer: Composer) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
composer: Composer,
) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
.property("navigation", navigation) .property("navigation", navigation)
.property("library", library) .property("library", library)

View file

@ -1,32 +1,32 @@
use crate::{db::models::Work, editor::work_editor::MusicusWorkEditor, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gtk::glib::{self, clone, subclass::Signal, Properties}; use gtk::glib::{self, clone, subclass::Signal, Properties};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{db::models::Work, editor::work::WorkEditor, library::Library};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusWorkEditorPartRow)] #[properties(wrapper_type = super::WorkEditorPartRow)]
#[template(file = "data/ui/work_editor_part_row.blp")] #[template(file = "data/ui/editor/work/part_row.blp")]
pub struct MusicusWorkEditorPartRow { pub struct WorkEditorPartRow {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub part: RefCell<Option<Work>>, pub part: RefCell<Option<Work>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWorkEditorPartRow { impl ObjectSubclass for WorkEditorPartRow {
const NAME: &'static str = "MusicusWorkEditorPartRow"; const NAME: &'static str = "MusicusWorkEditorPartRow";
type Type = super::MusicusWorkEditorPartRow; type Type = super::WorkEditorPartRow;
type ParentType = adw::ActionRow; type ParentType = adw::ActionRow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -40,7 +40,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusWorkEditorPartRow { impl ObjectImpl for WorkEditorPartRow {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -49,20 +49,20 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWorkEditorPartRow {} impl WidgetImpl for WorkEditorPartRow {}
impl ListBoxRowImpl for MusicusWorkEditorPartRow {} impl ListBoxRowImpl for WorkEditorPartRow {}
impl PreferencesRowImpl for MusicusWorkEditorPartRow {} impl PreferencesRowImpl for WorkEditorPartRow {}
impl ActionRowImpl for MusicusWorkEditorPartRow {} impl ActionRowImpl for WorkEditorPartRow {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWorkEditorPartRow(ObjectSubclass<imp::MusicusWorkEditorPartRow>) pub struct WorkEditorPartRow(ObjectSubclass<imp::WorkEditorPartRow>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow; @extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::ActionRow;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWorkEditorPartRow { impl WorkEditorPartRow {
pub fn new(navigation: &adw::NavigationView, library: &MusicusLibrary, part: Work) -> Self { pub fn new(navigation: &adw::NavigationView, library: &Library, part: Work) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
.property("navigation", navigation) .property("navigation", navigation)
.property("library", library) .property("library", library)
@ -104,7 +104,7 @@ impl MusicusWorkEditorPartRow {
#[template_callback] #[template_callback]
fn edit(&self) { fn edit(&self) {
let editor = MusicusWorkEditor::new( let editor = WorkEditor::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
self.imp().part.borrow().as_ref(), self.imp().part.borrow().as_ref(),

View file

@ -8,38 +8,35 @@ use gtk::{
}; };
use crate::{ use crate::{
album_tile::MusicusAlbumTile, album_tile::AlbumTile,
config, config,
db::models::*, db::models::*,
editor::{ editor::{ensemble::EnsembleEditor, person::PersonEditor, work::WorkEditor},
ensemble_editor::MusicusEnsembleEditor, person_editor::MusicusPersonEditor, library::{Library, LibraryQuery},
work_editor::MusicusWorkEditor, player::Player,
},
library::{LibraryQuery, MusicusLibrary},
player::MusicusPlayer,
program::Program, program::Program,
program_tile::MusicusProgramTile, program_tile::ProgramTile,
recording_tile::MusicusRecordingTile, recording_tile::RecordingTile,
search_entry::MusicusSearchEntry, search_entry::SearchEntry,
search_tag::Tag, search_tag::Tag,
tag_tile::MusicusTagTile, tag_tile::TagTile,
}; };
mod imp { mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusHomePage)] #[properties(wrapper_type = super::HomePage)]
#[template(file = "data/ui/home_page.blp")] #[template(file = "data/ui/home_page.blp")]
pub struct MusicusHomePage { pub struct HomePage {
#[property(get, construct_only)] #[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub player: OnceCell<MusicusPlayer>, pub player: OnceCell<Player>,
pub programs: RefCell<Vec<Program>>, pub programs: RefCell<Vec<Program>>,
pub composers: RefCell<Vec<Person>>, pub composers: RefCell<Vec<Person>>,
@ -50,7 +47,7 @@ mod imp {
pub albums: RefCell<Vec<Album>>, pub albums: RefCell<Vec<Album>>,
#[template_child] #[template_child]
pub search_entry: TemplateChild<MusicusSearchEntry>, pub search_entry: TemplateChild<SearchEntry>,
#[template_child] #[template_child]
pub stack: TemplateChild<gtk::Stack>, pub stack: TemplateChild<gtk::Stack>,
#[template_child] #[template_child]
@ -78,9 +75,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusHomePage { impl ObjectSubclass for HomePage {
const NAME: &'static str = "MusicusHomePage"; const NAME: &'static str = "MusicusHomePage";
type Type = super::MusicusHomePage; type Type = super::HomePage;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -94,7 +91,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusHomePage { impl ObjectImpl for HomePage {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
@ -128,7 +125,7 @@ mod imp {
for program in &programs { for program in &programs {
self.programs_flow_box self.programs_flow_box
.append(&MusicusProgramTile::new(program.to_owned())); .append(&ProgramTile::new(program.to_owned()));
} }
self.programs.replace(programs); self.programs.replace(programs);
@ -137,22 +134,18 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusHomePage {} impl WidgetImpl for HomePage {}
impl NavigationPageImpl for MusicusHomePage {} impl NavigationPageImpl for HomePage {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusHomePage(ObjectSubclass<imp::MusicusHomePage>) pub struct HomePage(ObjectSubclass<imp::HomePage>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusHomePage { impl HomePage {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, player: &Player) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
player: &MusicusPlayer,
) -> Self {
glib::Object::builder() glib::Object::builder()
.property("navigation", navigation) .property("navigation", navigation)
.property("library", library) .property("library", library)
@ -170,20 +163,20 @@ impl MusicusHomePage {
if let Some(tag) = self.imp().search_entry.tags().first() { if let Some(tag) = self.imp().search_entry.tags().first() {
match tag { match tag {
Tag::Composer(person) | Tag::Performer(person) => { Tag::Composer(person) | Tag::Performer(person) => {
self.navigation().push(&MusicusPersonEditor::new( self.navigation().push(&PersonEditor::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
Some(person), Some(person),
)); ));
} }
Tag::Ensemble(ensemble) => { Tag::Ensemble(ensemble) => {
self.navigation().push(&MusicusEnsembleEditor::new( self.navigation().push(&EnsembleEditor::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
Some(ensemble), Some(ensemble),
)); ));
} }
Tag::Work(work) => self.navigation().push(&MusicusWorkEditor::new( Tag::Work(work) => self.navigation().push(&WorkEditor::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
Some(work), Some(work),
@ -202,7 +195,7 @@ impl MusicusHomePage {
} }
#[template_callback] #[template_callback]
fn select(&self, search_entry: &MusicusSearchEntry) { fn select(&self, search_entry: &SearchEntry) {
let imp = self.imp(); let imp = self.imp();
if imp.programs_flow_box.is_visible() { if imp.programs_flow_box.is_visible() {
@ -240,28 +233,25 @@ impl MusicusHomePage {
#[template_callback] #[template_callback]
fn program_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) { fn program_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) {
self.player() self.player()
.set_program(tile.downcast_ref::<MusicusProgramTile>().unwrap().program()); .set_program(tile.downcast_ref::<ProgramTile>().unwrap().program());
} }
#[template_callback] #[template_callback]
fn tile_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) { fn tile_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) {
self.imp() self.imp()
.search_entry .search_entry
.add_tag(tile.downcast_ref::<MusicusTagTile>().unwrap().tag().clone()) .add_tag(tile.downcast_ref::<TagTile>().unwrap().tag().clone())
} }
#[template_callback] #[template_callback]
fn recording_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) { fn recording_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) {
self.player().play_recording( self.player()
tile.downcast_ref::<MusicusRecordingTile>() .play_recording(tile.downcast_ref::<RecordingTile>().unwrap().recording());
.unwrap()
.recording(),
);
} }
#[template_callback] #[template_callback]
fn album_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) { fn album_selected(&self, tile: &gtk::FlowBoxChild, _: &gtk::FlowBox) {
self.show_album(tile.downcast_ref::<MusicusAlbumTile>().unwrap().album()); self.show_album(tile.downcast_ref::<AlbumTile>().unwrap().album());
} }
fn show_album(&self, _album: &Album) { fn show_album(&self, _album: &Album) {
@ -331,26 +321,26 @@ impl MusicusHomePage {
for composer in &results.composers { for composer in &results.composers {
imp.composers_flow_box imp.composers_flow_box
.append(&MusicusTagTile::new(Tag::Composer(composer.clone()))); .append(&TagTile::new(Tag::Composer(composer.clone())));
} }
for performer in &results.performers { for performer in &results.performers {
imp.performers_flow_box imp.performers_flow_box
.append(&MusicusTagTile::new(Tag::Performer(performer.clone()))); .append(&TagTile::new(Tag::Performer(performer.clone())));
} }
for ensemble in &results.ensembles { for ensemble in &results.ensembles {
imp.ensembles_flow_box imp.ensembles_flow_box
.append(&MusicusTagTile::new(Tag::Ensemble(ensemble.clone()))); .append(&TagTile::new(Tag::Ensemble(ensemble.clone())));
} }
for work in &results.works { for work in &results.works {
imp.works_flow_box imp.works_flow_box
.append(&MusicusTagTile::new(Tag::Work(work.clone()))); .append(&TagTile::new(Tag::Work(work.clone())));
} }
for recording in &results.recordings { for recording in &results.recordings {
imp.recordings_flow_box.append(&MusicusRecordingTile::new( imp.recordings_flow_box.append(&RecordingTile::new(
&self.navigation(), &self.navigation(),
&self.library(), &self.library(),
recording, recording,
@ -358,7 +348,7 @@ impl MusicusHomePage {
} }
for album in &results.albums { for album in &results.albums {
imp.albums_flow_box.append(&MusicusAlbumTile::new(album)); imp.albums_flow_box.append(&AlbumTile::new(album));
} }
imp.composers.replace(results.composers); imp.composers.replace(results.composers);

View file

@ -1,6 +1,8 @@
use crate::{ use std::{
db::{self, models::*, schema::*, tables, TranslatedString}, cell::{OnceCell, RefCell},
program::Program, ffi::OsString,
fs,
path::{Path, PathBuf},
}; };
use adw::{ use adw::{
@ -13,11 +15,9 @@ use chrono::prelude::*;
use diesel::{dsl::exists, prelude::*, QueryDsl, SqliteConnection}; use diesel::{dsl::exists, prelude::*, QueryDsl, SqliteConnection};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::{ use crate::{
cell::{OnceCell, RefCell}, db::{self, models::*, schema::*, tables, TranslatedString},
ffi::OsString, program::Program,
fs,
path::{Path, PathBuf},
}; };
diesel::define_sql_function! { diesel::define_sql_function! {
@ -29,21 +29,21 @@ mod imp {
use super::*; use super::*;
#[derive(Properties, Default)] #[derive(Properties, Default)]
#[properties(wrapper_type = super::MusicusLibrary)] #[properties(wrapper_type = super::Library)]
pub struct MusicusLibrary { pub struct Library {
#[property(get, construct_only)] #[property(get, construct_only)]
pub folder: OnceCell<String>, pub folder: OnceCell<String>,
pub connection: RefCell<Option<SqliteConnection>>, pub connection: RefCell<Option<SqliteConnection>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusLibrary { impl ObjectSubclass for Library {
const NAME: &'static str = "MusicusLibrary"; const NAME: &'static str = "MusicusLibrary";
type Type = super::MusicusLibrary; type Type = super::Library;
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusLibrary { impl ObjectImpl for Library {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("changed").build()]); Lazy::new(|| vec![Signal::builder("changed").build()]);
@ -62,10 +62,10 @@ mod imp {
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusLibrary(ObjectSubclass<imp::MusicusLibrary>); pub struct Library(ObjectSubclass<imp::Library>);
} }
impl MusicusLibrary { impl Library {
pub fn new(path: impl AsRef<Path>) -> Self { pub fn new(path: impl AsRef<Path>) -> Self {
glib::Object::builder() glib::Object::builder()
.property("folder", path.as_ref().to_str().unwrap()) .property("folder", path.as_ref().to_str().unwrap())

View file

@ -1,10 +1,10 @@
use crate::{db::models::Album, editor::album_editor::AlbumEditor, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::glib::{self, clone}; use gtk::glib::{self, clone};
use std::cell::{OnceCell, RefCell}; use crate::{db::models::Album, editor::album::AlbumEditor, library::Library};
mod imp { mod imp {
use super::*; use super::*;
@ -13,7 +13,7 @@ mod imp {
#[template(file = "data/ui/library_manager_albums_page.blp")] #[template(file = "data/ui/library_manager_albums_page.blp")]
pub struct AlbumsPage { pub struct AlbumsPage {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub albums: RefCell<Vec<Album>>, pub albums: RefCell<Vec<Album>>,
pub albums_filtered: RefCell<Vec<Album>>, pub albums_filtered: RefCell<Vec<Album>>,
@ -57,7 +57,7 @@ glib::wrapper! {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl AlbumsPage { impl AlbumsPage {
pub fn new(navigation: &adw::NavigationView, library: &MusicusLibrary) -> Self { pub fn new(navigation: &adw::NavigationView, library: &Library) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
let imp = obj.imp(); let imp = obj.imp();

View file

@ -1,12 +1,9 @@
pub mod albums_page; pub mod albums_page;
use crate::{ use std::{
db::{ cell::{OnceCell, RefCell},
models::{Album, Ensemble, Instrument, Person, Recording, Role, Track, Work}, ffi::OsStr,
tables::Medium, path::Path,
},
library::MusicusLibrary,
window::MusicusWindow,
}; };
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
@ -14,10 +11,13 @@ use albums_page::AlbumsPage;
use gettextrs::gettext; use gettextrs::gettext;
use gtk::glib; use gtk::glib;
use std::{ use crate::{
cell::{OnceCell, RefCell}, db::{
ffi::OsStr, models::{Album, Ensemble, Instrument, Person, Recording, Role, Track, Work},
path::Path, tables::Medium,
},
library::Library,
window::Window,
}; };
mod imp { mod imp {
@ -27,7 +27,7 @@ mod imp {
#[template(file = "data/ui/library_manager.blp")] #[template(file = "data/ui/library_manager.blp")]
pub struct LibraryManager { pub struct LibraryManager {
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub persons: RefCell<Vec<Person>>, pub persons: RefCell<Vec<Person>>,
pub roles: RefCell<Vec<Role>>, pub roles: RefCell<Vec<Role>>,
@ -95,7 +95,7 @@ glib::wrapper! {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl LibraryManager { impl LibraryManager {
pub fn new(navigation: &adw::NavigationView, library: &MusicusLibrary) -> Self { pub fn new(navigation: &adw::NavigationView, library: &Library) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
let imp = obj.imp(); let imp = obj.imp();
@ -116,7 +116,7 @@ impl LibraryManager {
let window = root let window = root
.as_ref() .as_ref()
.and_then(|r| r.downcast_ref::<gtk::Window>()) .and_then(|r| r.downcast_ref::<gtk::Window>())
.and_then(|w| w.downcast_ref::<MusicusWindow>()) .and_then(|w| w.downcast_ref::<Window>())
.unwrap(); .unwrap();
match dialog.select_folder_future(Some(window)).await { match dialog.select_folder_future(Some(window)).await {

View file

@ -1,3 +1,4 @@
mod activatable_row;
mod album_tile; mod album_tile;
mod application; mod application;
mod config; mod config;
@ -16,16 +17,18 @@ mod program_tile;
mod recording_tile; mod recording_tile;
mod search_entry; mod search_entry;
mod search_tag; mod search_tag;
mod selector;
mod tag_tile; mod tag_tile;
mod util; mod util;
mod welcome_page; mod welcome_page;
mod window; mod window;
use self::{application::MusicusApplication, window::MusicusWindow};
use gettextrs::LocaleCategory; use gettextrs::LocaleCategory;
use gstreamer_play::gst; use gstreamer_play::gst;
use gtk::{gio, glib, prelude::*}; use gtk::{gio, glib, prelude::*};
use self::{application::Application, window::Window};
fn main() -> glib::ExitCode { fn main() -> glib::ExitCode {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
gtk::init().expect("Failed to initialize GTK!"); gtk::init().expect("Failed to initialize GTK!");
@ -48,5 +51,5 @@ fn main() -> glib::ExitCode {
.expect("Could not load resources"), .expect("Could not load resources"),
); );
MusicusApplication::new().run() Application::new().run()
} }

View file

@ -16,7 +16,7 @@ use once_cell::sync::Lazy;
use crate::{ use crate::{
config, config,
db::models::{Recording, Track}, db::models::{Recording, Track},
library::MusicusLibrary, library::Library,
playlist_item::PlaylistItem, playlist_item::PlaylistItem,
program::Program, program::Program,
}; };
@ -25,10 +25,10 @@ mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default)] #[derive(Properties, Debug, Default)]
#[properties(wrapper_type = super::MusicusPlayer)] #[properties(wrapper_type = super::Player)]
pub struct MusicusPlayer { pub struct Player {
#[property(get, set)] #[property(get, set)]
pub library: RefCell<Option<MusicusLibrary>>, pub library: RefCell<Option<Library>>,
#[property(get, set)] #[property(get, set)]
pub active: Cell<bool>, pub active: Cell<bool>,
#[property(get, set)] #[property(get, set)]
@ -49,7 +49,7 @@ mod imp {
pub mpris: OnceCell<mpris_server::Player>, pub mpris: OnceCell<mpris_server::Player>,
} }
impl MusicusPlayer { impl Player {
pub fn set_program(&self, program: &Program) { pub fn set_program(&self, program: &Program) {
self.program.replace(Some(program.to_owned())); self.program.replace(Some(program.to_owned()));
@ -114,13 +114,13 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusPlayer { impl ObjectSubclass for Player {
const NAME: &'static str = "MusicusPlayer"; const NAME: &'static str = "MusicusPlayer";
type Type = super::MusicusPlayer; type Type = super::Player;
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusPlayer { impl ObjectImpl for Player {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("raise").build()]); Lazy::new(|| vec![Signal::builder("raise").build()]);
@ -180,10 +180,10 @@ mod imp {
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusPlayer(ObjectSubclass<imp::MusicusPlayer>); pub struct Player(ObjectSubclass<imp::Player>);
} }
impl MusicusPlayer { impl Player {
pub fn new() -> Self { pub fn new() -> Self {
glib::Object::builder() glib::Object::builder()
.property("active", false) .property("active", false)
@ -436,7 +436,7 @@ impl MusicusPlayer {
} }
} }
impl Default for MusicusPlayer { impl Default for Player {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }

View file

@ -1,4 +1,5 @@
use crate::player::MusicusPlayer; use std::cell::{Cell, OnceCell};
use gtk::{ use gtk::{
gdk, gdk,
glib::{self, clone, subclass::Signal, Properties}, glib::{self, clone, subclass::Signal, Properties},
@ -6,7 +7,8 @@ use gtk::{
subclass::prelude::*, subclass::prelude::*,
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{Cell, OnceCell};
use crate::player::Player;
mod imp { mod imp {
use super::*; use super::*;
@ -16,7 +18,7 @@ mod imp {
#[template(file = "data/ui/player_bar.blp")] #[template(file = "data/ui/player_bar.blp")]
pub struct PlayerBar { pub struct PlayerBar {
#[property(get, construct_only)] #[property(get, construct_only)]
pub player: OnceCell<MusicusPlayer>, pub player: OnceCell<Player>,
pub seeking: Cell<bool>, pub seeking: Cell<bool>,
@ -196,7 +198,7 @@ glib::wrapper! {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl PlayerBar { impl PlayerBar {
pub fn new(player: &MusicusPlayer) -> Self { pub fn new(player: &Player) -> Self {
glib::Object::builder().property("player", player).build() glib::Object::builder().property("player", player).build()
} }

View file

@ -1,9 +1,10 @@
use gtk::{glib, glib::Properties, prelude::*, subclass::prelude::*};
use std::{ use std::{
cell::{Cell, OnceCell}, cell::{Cell, OnceCell},
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use gtk::{glib, glib::Properties, prelude::*, subclass::prelude::*};
mod imp { mod imp {
use super::*; use super::*;

View file

@ -1,29 +1,35 @@
use crate::{player::MusicusPlayer, playlist_tile::PlaylistTile};
use adw::subclass::prelude::*;
use gtk::{glib, glib::subclass::Signal, glib::Properties, prelude::*, ListScrollFlags};
use once_cell::sync::Lazy;
use std::cell::OnceCell; use std::cell::OnceCell;
use adw::subclass::prelude::*;
use gtk::{
glib,
glib::{subclass::Signal, Properties},
prelude::*,
ListScrollFlags,
};
use once_cell::sync::Lazy;
use crate::{player::Player, playlist_tile::PlaylistTile};
mod imp { mod imp {
use super::*;
use crate::playlist_item::PlaylistItem; use crate::playlist_item::PlaylistItem;
use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusPlaylistPage)] #[properties(wrapper_type = super::PlaylistPage)]
#[template(file = "data/ui/playlist_page.blp")] #[template(file = "data/ui/playlist_page.blp")]
pub struct MusicusPlaylistPage { pub struct PlaylistPage {
#[property(get, construct_only)] #[property(get, construct_only)]
pub player: OnceCell<MusicusPlayer>, pub player: OnceCell<Player>,
#[template_child] #[template_child]
pub playlist: TemplateChild<gtk::ListView>, pub playlist: TemplateChild<gtk::ListView>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusPlaylistPage { impl ObjectSubclass for PlaylistPage {
const NAME: &'static str = "MusicusPlaylistPage"; const NAME: &'static str = "MusicusPlaylistPage";
type Type = super::MusicusPlaylistPage; type Type = super::PlaylistPage;
type ParentType = adw::Bin; type ParentType = adw::Bin;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -37,7 +43,7 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusPlaylistPage { impl ObjectImpl for PlaylistPage {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("close").build()]); Lazy::new(|| vec![Signal::builder("close").build()]);
@ -76,18 +82,18 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusPlaylistPage {} impl WidgetImpl for PlaylistPage {}
impl BinImpl for MusicusPlaylistPage {} impl BinImpl for PlaylistPage {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusPlaylistPage(ObjectSubclass<imp::MusicusPlaylistPage>) pub struct PlaylistPage(ObjectSubclass<imp::PlaylistPage>)
@extends gtk::Widget, adw::Bin; @extends gtk::Widget, adw::Bin;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusPlaylistPage { impl PlaylistPage {
pub fn new(player: &MusicusPlayer) -> Self { pub fn new(player: &Player) -> Self {
glib::Object::builder().property("player", player).build() glib::Object::builder().property("player", player).build()
} }

View file

@ -1,7 +1,9 @@
use crate::playlist_item::PlaylistItem;
use gtk::{glib, prelude::*, subclass::prelude::*};
use std::cell::RefCell; use std::cell::RefCell;
use gtk::{glib, prelude::*, subclass::prelude::*};
use crate::playlist_item::PlaylistItem;
mod imp { mod imp {
use super::*; use super::*;

View file

@ -12,9 +12,9 @@ mod imp {
use super::*; use super::*;
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)] #[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::MusicusProgramTile)] #[properties(wrapper_type = super::ProgramTile)]
#[template(file = "data/ui/program_tile.blp")] #[template(file = "data/ui/program_tile.blp")]
pub struct MusicusProgramTile { pub struct ProgramTile {
#[property(get, construct_only)] #[property(get, construct_only)]
pub program: OnceCell<Program>, pub program: OnceCell<Program>,
@ -27,9 +27,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusProgramTile { impl ObjectSubclass for ProgramTile {
const NAME: &'static str = "MusicusProgramTile"; const NAME: &'static str = "MusicusProgramTile";
type Type = super::MusicusProgramTile; type Type = super::ProgramTile;
type ParentType = gtk::FlowBoxChild; type ParentType = gtk::FlowBoxChild;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -42,18 +42,18 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusProgramTile {} impl ObjectImpl for ProgramTile {}
impl WidgetImpl for MusicusProgramTile {} impl WidgetImpl for ProgramTile {}
impl FlowBoxChildImpl for MusicusProgramTile {} impl FlowBoxChildImpl for ProgramTile {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusProgramTile(ObjectSubclass<imp::MusicusProgramTile>) pub struct ProgramTile(ObjectSubclass<imp::ProgramTile>)
@extends gtk::Widget, gtk::FlowBoxChild; @extends gtk::Widget, gtk::FlowBoxChild;
} }
impl MusicusProgramTile { impl ProgramTile {
pub fn new(program: Program) -> Self { pub fn new(program: Program) -> Self {
let obj: Self = glib::Object::builder() let obj: Self = glib::Object::builder()
.property("program", &program) .property("program", &program)

View file

@ -1,20 +1,17 @@
use crate::{ use std::cell::OnceCell;
db::models::Recording, editor::recording_editor::MusicusRecordingEditor,
library::MusicusLibrary,
};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{gio, glib, prelude::*, subclass::prelude::*}; use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use std::cell::OnceCell;
use crate::{db::models::Recording, editor::recording::RecordingEditor, library::Library};
mod imp { mod imp {
use crate::editor::tracks_editor::TracksEditor;
use super::*; use super::*;
use crate::editor::tracks::TracksEditor;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/recording_tile.blp")] #[template(file = "data/ui/recording_tile.blp")]
pub struct MusicusRecordingTile { pub struct RecordingTile {
#[template_child] #[template_child]
pub composer_label: TemplateChild<gtk::Label>, pub composer_label: TemplateChild<gtk::Label>,
#[template_child] #[template_child]
@ -23,14 +20,14 @@ mod imp {
pub performances_label: TemplateChild<gtk::Label>, pub performances_label: TemplateChild<gtk::Label>,
pub navigation: OnceCell<adw::NavigationView>, pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub recording: OnceCell<Recording>, pub recording: OnceCell<Recording>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRecordingTile { impl ObjectSubclass for RecordingTile {
const NAME: &'static str = "MusicusRecordingTile"; const NAME: &'static str = "MusicusRecordingTile";
type Type = super::MusicusRecordingTile; type Type = super::RecordingTile;
type ParentType = gtk::FlowBoxChild; type ParentType = gtk::FlowBoxChild;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -42,7 +39,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusRecordingTile { impl ObjectImpl for RecordingTile {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
@ -53,7 +50,7 @@ mod imp {
.navigation .navigation
.get() .get()
.unwrap() .unwrap()
.push(&MusicusRecordingEditor::new( .push(&RecordingEditor::new(
obj.imp().navigation.get().unwrap(), obj.imp().navigation.get().unwrap(),
obj.imp().library.get().unwrap(), obj.imp().library.get().unwrap(),
Some(&obj.imp().recording.get().unwrap()), Some(&obj.imp().recording.get().unwrap()),
@ -78,21 +75,17 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRecordingTile {} impl WidgetImpl for RecordingTile {}
impl FlowBoxChildImpl for MusicusRecordingTile {} impl FlowBoxChildImpl for RecordingTile {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRecordingTile(ObjectSubclass<imp::MusicusRecordingTile>) pub struct RecordingTile(ObjectSubclass<imp::RecordingTile>)
@extends gtk::Widget, gtk::FlowBoxChild; @extends gtk::Widget, gtk::FlowBoxChild;
} }
impl MusicusRecordingTile { impl RecordingTile {
pub fn new( pub fn new(navigation: &adw::NavigationView, library: &Library, recording: &Recording) -> Self {
navigation: &adw::NavigationView,
library: &MusicusLibrary,
recording: &Recording,
) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
let imp = obj.imp(); let imp = obj.imp();

View file

@ -1,21 +1,23 @@
use crate::{ use std::{cell::RefCell, time::Duration};
library::LibraryQuery,
search_tag::{MusicusSearchTag, Tag},
};
use adw::{prelude::*, subclass::prelude::*}; use adw::{prelude::*, subclass::prelude::*};
use gtk::{ use gtk::{
gdk, gio, gdk, gio,
glib::{self, clone, subclass::Signal, Propagation}, glib::{self, clone, subclass::Signal, Propagation},
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::{cell::RefCell, time::Duration};
use crate::{
library::LibraryQuery,
search_tag::{SearchTag, Tag},
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/search_entry.blp")] #[template(file = "data/ui/search_entry.blp")]
pub struct MusicusSearchEntry { pub struct SearchEntry {
#[template_child] #[template_child]
pub tags_box: TemplateChild<gtk::Box>, pub tags_box: TemplateChild<gtk::Box>,
#[template_child] #[template_child]
@ -23,14 +25,14 @@ mod imp {
#[template_child] #[template_child]
pub clear_icon: TemplateChild<gtk::Image>, pub clear_icon: TemplateChild<gtk::Image>,
pub tags: RefCell<Vec<MusicusSearchTag>>, pub tags: RefCell<Vec<SearchTag>>,
pub query_changed: RefCell<Option<gio::Cancellable>>, pub query_changed: RefCell<Option<gio::Cancellable>>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusSearchEntry { impl ObjectSubclass for SearchEntry {
const NAME: &'static str = "MusicusSearchEntry"; const NAME: &'static str = "MusicusSearchEntry";
type Type = super::MusicusSearchEntry; type Type = super::SearchEntry;
type ParentType = gtk::Box; type ParentType = gtk::Box;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -45,8 +47,8 @@ mod imp {
gdk::ModifierType::empty(), gdk::ModifierType::empty(),
)) ))
.action(&gtk::CallbackAction::new(|widget, _| match widget .action(&gtk::CallbackAction::new(|widget, _| match widget
.downcast_ref::<super::MusicusSearchEntry>( .downcast_ref::<super::SearchEntry>()
) { {
Some(obj) => { Some(obj) => {
obj.reset(); obj.reset();
Propagation::Stop Propagation::Stop
@ -62,7 +64,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusSearchEntry { impl ObjectImpl for SearchEntry {
fn constructed(&self) { fn constructed(&self) {
let controller = gtk::GestureClick::new(); let controller = gtk::GestureClick::new();
@ -90,22 +92,22 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusSearchEntry { impl WidgetImpl for SearchEntry {
fn grab_focus(&self) -> bool { fn grab_focus(&self) -> bool {
self.text.grab_focus_without_selecting() self.text.grab_focus_without_selecting()
} }
} }
impl BoxImpl for MusicusSearchEntry {} impl BoxImpl for SearchEntry {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusSearchEntry(ObjectSubclass<imp::MusicusSearchEntry>) pub struct SearchEntry(ObjectSubclass<imp::SearchEntry>)
@extends gtk::Widget; @extends gtk::Widget;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusSearchEntry { impl SearchEntry {
pub fn new() -> Self { pub fn new() -> Self {
glib::Object::new() glib::Object::new()
} }
@ -166,7 +168,7 @@ impl MusicusSearchEntry {
imp.clear_icon.set_visible(true); imp.clear_icon.set_visible(true);
imp.text.set_text(""); imp.text.set_text("");
let tag = MusicusSearchTag::new(tag); let tag = SearchTag::new(tag);
tag.connect_remove(clone!( tag.connect_remove(clone!(
#[weak(rename_to = this)] #[weak(rename_to = this)]

View file

@ -1,6 +1,7 @@
use std::cell::OnceCell;
use adw::{glib, glib::subclass::Signal, prelude::*, subclass::prelude::*}; use adw::{glib, glib::subclass::Signal, prelude::*, subclass::prelude::*};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::OnceCell;
use crate::db::models::{Ensemble, Person, Work}; use crate::db::models::{Ensemble, Person, Work};
@ -9,16 +10,16 @@ mod imp {
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/search_tag.blp")] #[template(file = "data/ui/search_tag.blp")]
pub struct MusicusSearchTag { pub struct SearchTag {
#[template_child] #[template_child]
pub label: TemplateChild<gtk::Label>, pub label: TemplateChild<gtk::Label>,
pub tag: OnceCell<Tag>, pub tag: OnceCell<Tag>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusSearchTag { impl ObjectSubclass for SearchTag {
const NAME: &'static str = "MusicusSearchTag"; const NAME: &'static str = "MusicusSearchTag";
type Type = super::MusicusSearchTag; type Type = super::SearchTag;
type ParentType = gtk::Box; type ParentType = gtk::Box;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -31,7 +32,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusSearchTag { impl ObjectImpl for SearchTag {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]); Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -40,19 +41,19 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusSearchTag {} impl WidgetImpl for SearchTag {}
impl BoxImpl for MusicusSearchTag {} impl BoxImpl for SearchTag {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusSearchTag(ObjectSubclass<imp::MusicusSearchTag>) pub struct SearchTag(ObjectSubclass<imp::SearchTag>)
@extends gtk::Widget; @extends gtk::Widget;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusSearchTag { impl SearchTag {
pub fn new(tag: Tag) -> Self { pub fn new(tag: Tag) -> Self {
let obj: MusicusSearchTag = glib::Object::new(); let obj: SearchTag = glib::Object::new();
obj.imp().label.set_label(match &tag { obj.imp().label.set_label(match &tag {
Tag::Composer(person) => person.name.get(), Tag::Composer(person) => person.name.get(),

View file

@ -1,4 +1,4 @@
use crate::{db::models::Ensemble, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -8,19 +8,17 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{activatable_row::ActivatableRow, db::models::Ensemble, library::Library};
use super::activatable_row::MusicusActivatableRow;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusEnsembleSelectorPopover)] #[properties(wrapper_type = super::EnsembleSelectorPopover)]
#[template(file = "data/ui/ensemble_selector_popover.blp")] #[template(file = "data/ui/selector/ensemble.blp")]
pub struct MusicusEnsembleSelectorPopover { pub struct EnsembleSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub ensembles: RefCell<Vec<Ensemble>>, pub ensembles: RefCell<Vec<Ensemble>>,
@ -33,9 +31,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusEnsembleSelectorPopover { impl ObjectSubclass for EnsembleSelectorPopover {
const NAME: &'static str = "MusicusEnsembleSelectorPopover"; const NAME: &'static str = "MusicusEnsembleSelectorPopover";
type Type = super::MusicusEnsembleSelectorPopover; type Type = super::EnsembleSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,12 +47,11 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusEnsembleSelectorPopover { impl ObjectImpl for EnsembleSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::MusicusEnsembleSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().search_entry.set_text(""); obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus(); obj.imp().search_entry.grab_focus();
@ -79,7 +76,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusEnsembleSelectorPopover { impl WidgetImpl for EnsembleSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -90,17 +87,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusEnsembleSelectorPopover {} impl PopoverImpl for EnsembleSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusEnsembleSelectorPopover(ObjectSubclass<imp::MusicusEnsembleSelectorPopover>) pub struct EnsembleSelectorPopover(ObjectSubclass<imp::EnsembleSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusEnsembleSelectorPopover { impl EnsembleSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -151,7 +148,7 @@ impl MusicusEnsembleSelectorPopover {
imp.list_box.remove_all(); imp.list_box.remove_all();
for ensemble in &ensembles { for ensemble in &ensembles {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(ensemble.to_string()) .label(ensemble.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -162,7 +159,7 @@ impl MusicusEnsembleSelectorPopover {
let ensemble = ensemble.clone(); let ensemble = ensemble.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(ensemble.clone()); obj.select(ensemble.clone());
}); });
@ -178,9 +175,9 @@ impl MusicusEnsembleSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

View file

@ -1,4 +1,4 @@
use crate::{db::models::Instrument, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -8,19 +8,17 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{activatable_row::ActivatableRow, db::models::Instrument, library::Library};
use super::activatable_row::MusicusActivatableRow;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusInstrumentSelectorPopover)] #[properties(wrapper_type = super::InstrumentSelectorPopover)]
#[template(file = "data/ui/instrument_selector_popover.blp")] #[template(file = "data/ui/selector/instrument.blp")]
pub struct MusicusInstrumentSelectorPopover { pub struct InstrumentSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub instruments: RefCell<Vec<Instrument>>, pub instruments: RefCell<Vec<Instrument>>,
@ -33,9 +31,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusInstrumentSelectorPopover { impl ObjectSubclass for InstrumentSelectorPopover {
const NAME: &'static str = "MusicusInstrumentSelectorPopover"; const NAME: &'static str = "MusicusInstrumentSelectorPopover";
type Type = super::MusicusInstrumentSelectorPopover; type Type = super::InstrumentSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,12 +47,11 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusInstrumentSelectorPopover { impl ObjectImpl for InstrumentSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::MusicusInstrumentSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().search_entry.set_text(""); obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus(); obj.imp().search_entry.grab_focus();
@ -79,7 +76,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusInstrumentSelectorPopover { impl WidgetImpl for InstrumentSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -90,17 +87,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusInstrumentSelectorPopover {} impl PopoverImpl for InstrumentSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusInstrumentSelectorPopover(ObjectSubclass<imp::MusicusInstrumentSelectorPopover>) pub struct InstrumentSelectorPopover(ObjectSubclass<imp::InstrumentSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusInstrumentSelectorPopover { impl InstrumentSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -156,7 +153,7 @@ impl MusicusInstrumentSelectorPopover {
imp.list_box.remove_all(); imp.list_box.remove_all();
for instrument in &instruments { for instrument in &instruments {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(instrument.to_string()) .label(instrument.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -167,7 +164,7 @@ impl MusicusInstrumentSelectorPopover {
let instrument = instrument.clone(); let instrument = instrument.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(instrument.clone()); obj.select(instrument.clone());
}); });
@ -183,9 +180,9 @@ impl MusicusInstrumentSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

7
src/selector/mod.rs Normal file
View file

@ -0,0 +1,7 @@
pub mod ensemble;
pub mod instrument;
pub mod performer_role;
pub mod person;
pub mod recording;
pub mod role;
pub mod work;

View file

@ -1,7 +1,4 @@
use crate::{ use std::cell::{OnceCell, RefCell};
db::models::{Instrument, Role},
library::MusicusLibrary,
};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -12,19 +9,21 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{
activatable_row::ActivatableRow,
use super::activatable_row::MusicusActivatableRow; db::models::{Instrument, Role},
library::Library,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusPerformerRoleSelectorPopover)] #[properties(wrapper_type = super::PerformerRoleSelectorPopover)]
#[template(file = "data/ui/performer_role_selector_popover.blp")] #[template(file = "data/ui/selector/performer_role.blp")]
pub struct MusicusPerformerRoleSelectorPopover { pub struct PerformerRoleSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub roles: RefCell<Vec<Role>>, pub roles: RefCell<Vec<Role>>,
pub instruments: RefCell<Vec<Instrument>>, pub instruments: RefCell<Vec<Instrument>>,
@ -50,9 +49,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusPerformerRoleSelectorPopover { impl ObjectSubclass for PerformerRoleSelectorPopover {
const NAME: &'static str = "MusicusPerformerRoleSelectorPopover"; const NAME: &'static str = "MusicusPerformerRoleSelectorPopover";
type Type = super::MusicusPerformerRoleSelectorPopover; type Type = super::PerformerRoleSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -66,20 +65,18 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusPerformerRoleSelectorPopover { impl ObjectImpl for PerformerRoleSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj().connect_visible_notify( self.obj().connect_visible_notify(|obj| {
|obj: &super::MusicusPerformerRoleSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().stack.set_visible_child(&*obj.imp().role_view); obj.imp().stack.set_visible_child(&*obj.imp().role_view);
obj.imp().role_search_entry.set_text(""); obj.imp().role_search_entry.set_text("");
obj.imp().role_search_entry.grab_focus(); obj.imp().role_search_entry.grab_focus();
obj.imp().role_scrolled_window.vadjustment().set_value(0.0); obj.imp().role_scrolled_window.vadjustment().set_value(0.0);
} }
}, });
);
self.obj().search_roles(""); self.obj().search_roles("");
} }
@ -99,7 +96,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusPerformerRoleSelectorPopover { impl WidgetImpl for PerformerRoleSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -114,17 +111,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusPerformerRoleSelectorPopover {} impl PopoverImpl for PerformerRoleSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusPerformerRoleSelectorPopover(ObjectSubclass<imp::MusicusPerformerRoleSelectorPopover>) pub struct PerformerRoleSelectorPopover(ObjectSubclass<imp::PerformerRoleSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusPerformerRoleSelectorPopover { impl PerformerRoleSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -204,7 +201,7 @@ impl MusicusPerformerRoleSelectorPopover {
imp.role_list.remove_all(); imp.role_list.remove_all();
for role in &roles { for role in &roles {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(role.to_string()) .label(role.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -216,7 +213,7 @@ impl MusicusPerformerRoleSelectorPopover {
let role = role.clone(); let role = role.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select_role(role.clone()); obj.select_role(role.clone());
}); });
@ -232,9 +229,9 @@ impl MusicusPerformerRoleSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create_role(); obj.create_role();
}); });
@ -256,7 +253,7 @@ impl MusicusPerformerRoleSelectorPopover {
imp.instrument_list.remove_all(); imp.instrument_list.remove_all();
for instrument in &instruments { for instrument in &instruments {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(instrument.to_string()) .label(instrument.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -268,7 +265,7 @@ impl MusicusPerformerRoleSelectorPopover {
let instrument = instrument.clone(); let instrument = instrument.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select_instrument(instrument.clone()); obj.select_instrument(instrument.clone());
}); });
@ -284,9 +281,9 @@ impl MusicusPerformerRoleSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create_instrument(); obj.create_instrument();
}); });

View file

@ -1,4 +1,4 @@
use crate::{db::models::Person, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -8,19 +8,17 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{activatable_row::ActivatableRow, db::models::Person, library::Library};
use super::activatable_row::MusicusActivatableRow;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusPersonSelectorPopover)] #[properties(wrapper_type = super::PersonSelectorPopover)]
#[template(file = "data/ui/person_selector_popover.blp")] #[template(file = "data/ui/selector/person.blp")]
pub struct MusicusPersonSelectorPopover { pub struct PersonSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub persons: RefCell<Vec<Person>>, pub persons: RefCell<Vec<Person>>,
@ -33,9 +31,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusPersonSelectorPopover { impl ObjectSubclass for PersonSelectorPopover {
const NAME: &'static str = "MusicusPersonSelectorPopover"; const NAME: &'static str = "MusicusPersonSelectorPopover";
type Type = super::MusicusPersonSelectorPopover; type Type = super::PersonSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,12 +47,11 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusPersonSelectorPopover { impl ObjectImpl for PersonSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::MusicusPersonSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().search_entry.set_text(""); obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus(); obj.imp().search_entry.grab_focus();
@ -79,7 +76,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusPersonSelectorPopover { impl WidgetImpl for PersonSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -90,17 +87,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusPersonSelectorPopover {} impl PopoverImpl for PersonSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusPersonSelectorPopover(ObjectSubclass<imp::MusicusPersonSelectorPopover>) pub struct PersonSelectorPopover(ObjectSubclass<imp::PersonSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusPersonSelectorPopover { impl PersonSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -151,7 +148,7 @@ impl MusicusPersonSelectorPopover {
imp.list_box.remove_all(); imp.list_box.remove_all();
for person in &persons { for person in &persons {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(person.to_string()) .label(person.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -162,7 +159,7 @@ impl MusicusPersonSelectorPopover {
let person = person.clone(); let person = person.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(person.clone()); obj.select(person.clone());
}); });
@ -178,9 +175,9 @@ impl MusicusPersonSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

View file

@ -1,7 +1,4 @@
use crate::{ use std::cell::{OnceCell, RefCell};
db::models::{Person, Recording, Work},
library::MusicusLibrary,
};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -12,19 +9,21 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{
activatable_row::ActivatableRow,
use super::activatable_row::MusicusActivatableRow; db::models::{Person, Recording, Work},
library::Library,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::RecordingSelectorPopover)] #[properties(wrapper_type = super::RecordingSelectorPopover)]
#[template(file = "data/ui/recording_selector_popover.blp")] #[template(file = "data/ui/selector/recording.blp")]
pub struct RecordingSelectorPopover { pub struct RecordingSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub composers: RefCell<Vec<Person>>, pub composers: RefCell<Vec<Person>>,
pub works: RefCell<Vec<Work>>, pub works: RefCell<Vec<Work>>,
@ -86,8 +85,7 @@ mod imp {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::RecordingSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().stack.set_visible_child(&*obj.imp().composer_view); obj.imp().stack.set_visible_child(&*obj.imp().composer_view);
obj.imp().composer_search_entry.set_text(""); obj.imp().composer_search_entry.set_text("");
@ -143,7 +141,7 @@ glib::wrapper! {
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl RecordingSelectorPopover { impl RecordingSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -236,7 +234,7 @@ impl RecordingSelectorPopover {
imp.composer_list.remove_all(); imp.composer_list.remove_all();
for person in &persons { for person in &persons {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(person.to_string()) .label(person.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -248,7 +246,7 @@ impl RecordingSelectorPopover {
let person = person.clone(); let person = person.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select_composer(person.clone()); obj.select_composer(person.clone());
}); });
@ -264,9 +262,9 @@ impl RecordingSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });
@ -288,7 +286,7 @@ impl RecordingSelectorPopover {
imp.work_list.remove_all(); imp.work_list.remove_all();
for work in &works { for work in &works {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(work.name.get()) .label(work.name.get())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -300,7 +298,7 @@ impl RecordingSelectorPopover {
let work = work.clone(); let work = work.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select_work(work.clone()); obj.select_work(work.clone());
}); });
@ -316,9 +314,9 @@ impl RecordingSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });
@ -346,7 +344,7 @@ impl RecordingSelectorPopover {
label.push_str(&format!(" ({year})")); label.push_str(&format!(" ({year})"));
} }
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(&label) .label(&label)
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -358,7 +356,7 @@ impl RecordingSelectorPopover {
let recording = recording.clone(); let recording = recording.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(recording.clone()); obj.select(recording.clone());
}); });
@ -374,9 +372,9 @@ impl RecordingSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

View file

@ -1,4 +1,4 @@
use crate::{db::models::Role, library::MusicusLibrary}; use std::cell::{OnceCell, RefCell};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -8,19 +8,17 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{activatable_row::ActivatableRow, db::models::Role, library::Library};
use super::activatable_row::MusicusActivatableRow;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusRoleSelectorPopover)] #[properties(wrapper_type = super::RoleSelectorPopover)]
#[template(file = "data/ui/role_selector_popover.blp")] #[template(file = "data/ui/selector/role.blp")]
pub struct MusicusRoleSelectorPopover { pub struct RoleSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub roles: RefCell<Vec<Role>>, pub roles: RefCell<Vec<Role>>,
@ -33,9 +31,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusRoleSelectorPopover { impl ObjectSubclass for RoleSelectorPopover {
const NAME: &'static str = "MusicusRoleSelectorPopover"; const NAME: &'static str = "MusicusRoleSelectorPopover";
type Type = super::MusicusRoleSelectorPopover; type Type = super::RoleSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -49,12 +47,11 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusRoleSelectorPopover { impl ObjectImpl for RoleSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::MusicusRoleSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().search_entry.set_text(""); obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus(); obj.imp().search_entry.grab_focus();
@ -79,7 +76,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusRoleSelectorPopover { impl WidgetImpl for RoleSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -90,17 +87,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusRoleSelectorPopover {} impl PopoverImpl for RoleSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusRoleSelectorPopover(ObjectSubclass<imp::MusicusRoleSelectorPopover>) pub struct RoleSelectorPopover(ObjectSubclass<imp::RoleSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusRoleSelectorPopover { impl RoleSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -151,7 +148,7 @@ impl MusicusRoleSelectorPopover {
imp.list_box.remove_all(); imp.list_box.remove_all();
for role in &roles { for role in &roles {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(role.to_string()) .label(role.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -162,7 +159,7 @@ impl MusicusRoleSelectorPopover {
let role = role.clone(); let role = role.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(role.clone()); obj.select(role.clone());
}); });
@ -178,9 +175,9 @@ impl MusicusRoleSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

View file

@ -1,7 +1,4 @@
use crate::{ use std::cell::{OnceCell, RefCell};
db::models::{Person, Work},
library::MusicusLibrary,
};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{ use gtk::{
@ -12,19 +9,21 @@ use gtk::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell}; use crate::{
activatable_row::ActivatableRow,
use super::activatable_row::MusicusActivatableRow; db::models::{Person, Work},
library::Library,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)] #[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusWorkSelectorPopover)] #[properties(wrapper_type = super::WorkSelectorPopover)]
#[template(file = "data/ui/work_selector_popover.blp")] #[template(file = "data/ui/selector/work.blp")]
pub struct MusicusWorkSelectorPopover { pub struct WorkSelectorPopover {
#[property(get, construct_only)] #[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>, pub library: OnceCell<Library>,
pub composers: RefCell<Vec<Person>>, pub composers: RefCell<Vec<Person>>,
pub composer: RefCell<Option<Person>>, pub composer: RefCell<Option<Person>>,
@ -53,9 +52,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWorkSelectorPopover { impl ObjectSubclass for WorkSelectorPopover {
const NAME: &'static str = "MusicusWorkSelectorPopover"; const NAME: &'static str = "MusicusWorkSelectorPopover";
type Type = super::MusicusWorkSelectorPopover; type Type = super::WorkSelectorPopover;
type ParentType = gtk::Popover; type ParentType = gtk::Popover;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -69,12 +68,11 @@ mod imp {
} }
#[glib::derived_properties] #[glib::derived_properties]
impl ObjectImpl for MusicusWorkSelectorPopover { impl ObjectImpl for WorkSelectorPopover {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj() self.obj().connect_visible_notify(|obj| {
.connect_visible_notify(|obj: &super::MusicusWorkSelectorPopover| {
if obj.is_visible() { if obj.is_visible() {
obj.imp().stack.set_visible_child(&*obj.imp().composer_view); obj.imp().stack.set_visible_child(&*obj.imp().composer_view);
obj.imp().composer_search_entry.set_text(""); obj.imp().composer_search_entry.set_text("");
@ -103,7 +101,7 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWorkSelectorPopover { impl WidgetImpl for WorkSelectorPopover {
// TODO: Fix focus. // TODO: Fix focus.
fn focus(&self, direction_type: gtk::DirectionType) -> bool { fn focus(&self, direction_type: gtk::DirectionType) -> bool {
if direction_type == gtk::DirectionType::Down { if direction_type == gtk::DirectionType::Down {
@ -118,17 +116,17 @@ mod imp {
} }
} }
impl PopoverImpl for MusicusWorkSelectorPopover {} impl PopoverImpl for WorkSelectorPopover {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWorkSelectorPopover(ObjectSubclass<imp::MusicusWorkSelectorPopover>) pub struct WorkSelectorPopover(ObjectSubclass<imp::WorkSelectorPopover>)
@extends gtk::Widget, gtk::Popover; @extends gtk::Widget, gtk::Popover;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWorkSelectorPopover { impl WorkSelectorPopover {
pub fn new(library: &MusicusLibrary) -> Self { pub fn new(library: &Library) -> Self {
glib::Object::builder().property("library", library).build() glib::Object::builder().property("library", library).build()
} }
@ -198,7 +196,7 @@ impl MusicusWorkSelectorPopover {
imp.composer_list.remove_all(); imp.composer_list.remove_all();
for person in &persons { for person in &persons {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(person.to_string()) .label(person.to_string())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -210,7 +208,7 @@ impl MusicusWorkSelectorPopover {
let person = person.clone(); let person = person.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select_composer(person.clone()); obj.select_composer(person.clone());
}); });
@ -226,9 +224,9 @@ impl MusicusWorkSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });
@ -250,7 +248,7 @@ impl MusicusWorkSelectorPopover {
imp.work_list.remove_all(); imp.work_list.remove_all();
for work in &works { for work in &works {
let row = MusicusActivatableRow::new( let row = ActivatableRow::new(
&gtk::Label::builder() &gtk::Label::builder()
.label(work.name.get()) .label(work.name.get())
.halign(gtk::Align::Start) .halign(gtk::Align::Start)
@ -262,7 +260,7 @@ impl MusicusWorkSelectorPopover {
let work = work.clone(); let work = work.clone();
let obj = self.clone(); let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| { row.connect_activated(move |_: &ActivatableRow| {
obj.select(work.clone()); obj.select(work.clone());
}); });
@ -278,9 +276,9 @@ impl MusicusWorkSelectorPopover {
.build(), .build(),
); );
let create_row = MusicusActivatableRow::new(&create_box); let create_row = ActivatableRow::new(&create_box);
let obj = self.clone(); let obj = self.clone();
create_row.connect_activated(move |_: &MusicusActivatableRow| { create_row.connect_activated(move |_: &ActivatableRow| {
obj.create(); obj.create();
}); });

View file

@ -1,13 +1,15 @@
use crate::search_tag::Tag;
use gtk::{glib, prelude::*, subclass::prelude::*};
use std::cell::OnceCell; use std::cell::OnceCell;
use gtk::{glib, prelude::*, subclass::prelude::*};
use crate::search_tag::Tag;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/tag_tile.blp")] #[template(file = "data/ui/tag_tile.blp")]
pub struct MusicusTagTile { pub struct TagTile {
#[template_child] #[template_child]
pub title_label: TemplateChild<gtk::Label>, pub title_label: TemplateChild<gtk::Label>,
#[template_child] #[template_child]
@ -17,9 +19,9 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusTagTile { impl ObjectSubclass for TagTile {
const NAME: &'static str = "MusicusTagTile"; const NAME: &'static str = "MusicusTagTile";
type Type = super::MusicusTagTile; type Type = super::TagTile;
type ParentType = gtk::FlowBoxChild; type ParentType = gtk::FlowBoxChild;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -31,17 +33,17 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusTagTile {} impl ObjectImpl for TagTile {}
impl WidgetImpl for MusicusTagTile {} impl WidgetImpl for TagTile {}
impl FlowBoxChildImpl for MusicusTagTile {} impl FlowBoxChildImpl for TagTile {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusTagTile(ObjectSubclass<imp::MusicusTagTile>) pub struct TagTile(ObjectSubclass<imp::TagTile>)
@extends gtk::Widget, gtk::FlowBoxChild; @extends gtk::Widget, gtk::FlowBoxChild;
} }
impl MusicusTagTile { impl TagTile {
pub fn new(tag: Tag) -> Self { pub fn new(tag: Tag) -> Self {
let obj: Self = glib::Object::new(); let obj: Self = glib::Object::new();
let imp = obj.imp(); let imp = obj.imp();

View file

@ -1,24 +1,24 @@
use crate::config;
use adw::subclass::{navigation_page::NavigationPageImpl, prelude::*}; use adw::subclass::{navigation_page::NavigationPageImpl, prelude::*};
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{gio, glib, glib::subclass::Signal, prelude::*}; use gtk::{gio, glib, glib::subclass::Signal, prelude::*};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::config;
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/welcome_page.blp")] #[template(file = "data/ui/welcome_page.blp")]
pub struct MusicusWelcomePage { pub struct WelcomePage {
#[template_child] #[template_child]
pub status_page: TemplateChild<adw::StatusPage>, pub status_page: TemplateChild<adw::StatusPage>,
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWelcomePage { impl ObjectSubclass for WelcomePage {
const NAME: &'static str = "MusicusWelcomePage"; const NAME: &'static str = "MusicusWelcomePage";
type Type = super::MusicusWelcomePage; type Type = super::WelcomePage;
type ParentType = adw::NavigationPage; type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
@ -31,7 +31,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusWelcomePage { impl ObjectImpl for WelcomePage {
fn signals() -> &'static [Signal] { fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| { static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("folder-selected") vec![Signal::builder("folder-selected")
@ -48,17 +48,17 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWelcomePage {} impl WidgetImpl for WelcomePage {}
impl NavigationPageImpl for MusicusWelcomePage {} impl NavigationPageImpl for WelcomePage {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWelcomePage(ObjectSubclass<imp::MusicusWelcomePage>) pub struct WelcomePage(ObjectSubclass<imp::WelcomePage>)
@extends gtk::Widget, adw::NavigationPage; @extends gtk::Widget, adw::NavigationPage;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWelcomePage { impl WelcomePage {
pub fn new() -> Self { pub fn new() -> Self {
glib::Object::new() glib::Object::new()
} }

View file

@ -1,22 +1,22 @@
use crate::{ use std::{cell::RefCell, path::Path};
config, editor::tracks_editor::TracksEditor, home_page::MusicusHomePage,
library::MusicusLibrary, library_manager::LibraryManager, player::MusicusPlayer,
player_bar::PlayerBar, playlist_page::MusicusPlaylistPage, welcome_page::MusicusWelcomePage,
};
use adw::subclass::prelude::*; use adw::subclass::prelude::*;
use gtk::{gio, glib, glib::clone, prelude::*}; use gtk::{gio, glib, glib::clone, prelude::*};
use std::{cell::RefCell, path::Path}; use crate::{
config, editor::tracks::TracksEditor, home_page::HomePage, library::Library,
library_manager::LibraryManager, player::Player, player_bar::PlayerBar,
playlist_page::PlaylistPage, welcome_page::WelcomePage,
};
mod imp { mod imp {
use super::*; use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)] #[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/window.blp")] #[template(file = "data/ui/window.blp")]
pub struct MusicusWindow { pub struct Window {
pub library: RefCell<Option<MusicusLibrary>>, pub library: RefCell<Option<Library>>,
pub player: MusicusPlayer, pub player: Player,
#[template_child] #[template_child]
pub stack: TemplateChild<gtk::Stack>, pub stack: TemplateChild<gtk::Stack>,
@ -27,13 +27,13 @@ mod imp {
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for MusicusWindow { impl ObjectSubclass for Window {
const NAME: &'static str = "MusicusWindow"; const NAME: &'static str = "MusicusWindow";
type Type = super::MusicusWindow; type Type = super::Window;
type ParentType = adw::ApplicationWindow; type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) { fn class_init(klass: &mut Self::Class) {
MusicusWelcomePage::static_type(); WelcomePage::static_type();
klass.bind_template(); klass.bind_template();
klass.bind_template_instance_callbacks(); klass.bind_template_instance_callbacks();
} }
@ -43,7 +43,7 @@ mod imp {
} }
} }
impl ObjectImpl for MusicusWindow { impl ObjectImpl for Window {
fn constructed(&self) { fn constructed(&self) {
self.parent_constructed(); self.parent_constructed();
self.obj().load_window_state(); self.obj().load_window_state();
@ -79,7 +79,7 @@ mod imp {
let player_bar = PlayerBar::new(&self.player); let player_bar = PlayerBar::new(&self.player);
self.player_bar_revealer.set_child(Some(&player_bar)); self.player_bar_revealer.set_child(Some(&player_bar));
let playlist_page = MusicusPlaylistPage::new(&self.player); let playlist_page = PlaylistPage::new(&self.player);
self.stack.add_named(&playlist_page, Some("playlist")); self.stack.add_named(&playlist_page, Some("playlist"));
let stack = self.stack.get(); let stack = self.stack.get();
@ -125,9 +125,9 @@ mod imp {
} }
} }
impl WidgetImpl for MusicusWindow {} impl WidgetImpl for Window {}
impl WindowImpl for MusicusWindow { impl WindowImpl for Window {
fn close_request(&self) -> glib::signal::Propagation { fn close_request(&self) -> glib::signal::Propagation {
if let Err(err) = self.obj().save_window_state() { if let Err(err) = self.obj().save_window_state() {
log::warn!("Failed to save window state: {err}"); log::warn!("Failed to save window state: {err}");
@ -137,18 +137,18 @@ mod imp {
} }
} }
impl ApplicationWindowImpl for MusicusWindow {} impl ApplicationWindowImpl for Window {}
impl AdwApplicationWindowImpl for MusicusWindow {} impl AdwApplicationWindowImpl for Window {}
} }
glib::wrapper! { glib::wrapper! {
pub struct MusicusWindow(ObjectSubclass<imp::MusicusWindow>) pub struct Window(ObjectSubclass<imp::Window>)
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow, @extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, adw::ApplicationWindow,
@implements gio::ActionGroup, gio::ActionMap; @implements gio::ActionGroup, gio::ActionMap;
} }
#[gtk::template_callbacks] #[gtk::template_callbacks]
impl MusicusWindow { impl Window {
pub fn new<P: IsA<gtk::Application>>(application: &P) -> Self { pub fn new<P: IsA<gtk::Application>>(application: &P) -> Self {
glib::Object::builder() glib::Object::builder()
.property("application", application) .property("application", application)
@ -185,12 +185,11 @@ impl MusicusWindow {
} }
fn load_library(&self, path: impl AsRef<Path>) { fn load_library(&self, path: impl AsRef<Path>) {
let library = MusicusLibrary::new(path); let library = Library::new(path);
self.imp().player.set_library(&library); self.imp().player.set_library(&library);
let navigation = self.imp().navigation_view.get(); let navigation = self.imp().navigation_view.get();
navigation navigation.replace(&[HomePage::new(&navigation, &library, &self.imp().player).into()]);
.replace(&[MusicusHomePage::new(&navigation, &library, &self.imp().player).into()]);
self.imp().library.replace(Some(library)); self.imp().library.replace(Some(library));
} }