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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,24 +1,10 @@
pub mod activatable_row;
pub mod album_editor;
pub mod ensemble_editor;
pub mod ensemble_selector_popover;
pub mod instrument_editor;
pub mod instrument_selector_popover;
pub mod performer_role_selector_popover;
pub mod person_editor;
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 album;
pub mod ensemble;
pub mod instrument;
pub mod person;
pub mod recording;
pub mod role;
pub mod tracks;
pub mod translation;
pub mod translation_entry;
pub mod work_editor;
pub mod work_editor_composer_row;
pub mod work_editor_part_row;
pub mod work_selector_popover;
pub mod work;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +1,4 @@
use super::activatable_row::MusicusActivatableRow;
use crate::db::models::Work;
use std::cell::{OnceCell, RefCell};
use gtk::{
glib::{self, subclass::Signal},
@ -8,13 +7,13 @@ use gtk::{
};
use once_cell::sync::Lazy;
use std::cell::{OnceCell, RefCell};
use crate::{activatable_row::ActivatableRow, db::models::Work};
mod imp {
use super::*;
#[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 parts: OnceCell<Vec<Work>>,
pub parts_filtered: RefCell<Vec<Work>>,
@ -47,14 +46,13 @@ mod imp {
fn constructed(&self) {
self.parent_constructed();
self.obj()
.connect_visible_notify(|obj: &super::TracksEditorPartsPopover| {
if obj.is_visible() {
obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus();
obj.imp().scrolled_window.vadjustment().set_value(0.0);
}
});
self.obj().connect_visible_notify(|obj| {
if obj.is_visible() {
obj.imp().search_entry.set_text("");
obj.imp().search_entry.grab_focus();
obj.imp().scrolled_window.vadjustment().set_value(0.0);
}
});
}
fn signals() -> &'static [Signal] {
@ -143,7 +141,7 @@ impl TracksEditorPartsPopover {
imp.list_box.remove_all();
for part in &parts_filtered {
let row = MusicusActivatableRow::new(
let row = ActivatableRow::new(
&gtk::Label::builder()
.label(part.to_string())
.halign(gtk::Align::Start)
@ -154,7 +152,7 @@ impl TracksEditorPartsPopover {
let part = part.clone();
let obj = self.clone();
row.connect_activated(move |_: &MusicusActivatableRow| {
row.connect_activated(move |_: &ActivatableRow| {
obj.select(part.clone());
});

View file

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

View file

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

View file

@ -6,8 +6,8 @@ mod imp {
use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(file = "data/ui/translation_entry.blp")]
pub struct MusicusTranslationEntry {
#[template(file = "data/ui/editor/translation_entry.blp")]
pub struct TranslationEntry {
#[template_child]
pub lang_popover: TemplateChild<gtk::Popover>,
#[template_child]
@ -15,9 +15,9 @@ mod imp {
}
#[glib::object_subclass]
impl ObjectSubclass for MusicusTranslationEntry {
impl ObjectSubclass for TranslationEntry {
const NAME: &'static str = "MusicusTranslationEntry";
type Type = super::MusicusTranslationEntry;
type Type = super::TranslationEntry;
type ParentType = adw::EntryRow;
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] {
static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("remove").build()]);
@ -43,21 +43,21 @@ mod imp {
}
}
impl WidgetImpl for MusicusTranslationEntry {}
impl ListBoxRowImpl for MusicusTranslationEntry {}
impl PreferencesRowImpl for MusicusTranslationEntry {}
impl EntryRowImpl for MusicusTranslationEntry {}
impl EditableImpl for MusicusTranslationEntry {}
impl WidgetImpl for TranslationEntry {}
impl ListBoxRowImpl for TranslationEntry {}
impl PreferencesRowImpl for TranslationEntry {}
impl EntryRowImpl for TranslationEntry {}
impl EditableImpl for TranslationEntry {}
}
glib::wrapper! {
pub struct MusicusTranslationEntry(ObjectSubclass<imp::MusicusTranslationEntry>)
pub struct TranslationEntry(ObjectSubclass<imp::TranslationEntry>)
@extends gtk::Widget, gtk::ListBoxRow, adw::PreferencesRow, adw::EntryRow,
@implements gtk::Editable;
}
#[gtk::template_callbacks]
impl MusicusTranslationEntry {
impl TranslationEntry {
pub fn new(lang: &str, translation: &str) -> Self {
let obj: Self = glib::Object::new();
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::{
db::{
self,
models::{Composer, Instrument, Person, Work},
},
editor::{
instrument_editor::MusicusInstrumentEditor,
instrument_selector_popover::MusicusInstrumentSelectorPopover,
person_editor::MusicusPersonEditor, person_selector_popover::MusicusPersonSelectorPopover,
translation_editor::MusicusTranslationEditor,
work_editor_composer_row::MusicusWorkEditorComposerRow,
work_editor_part_row::MusicusWorkEditorPartRow,
},
library::MusicusLibrary,
editor::{instrument::InstrumentEditor, person::PersonEditor, translation::TranslationEditor},
library::Library,
selector::{instrument::InstrumentSelectorPopover, person::PersonSelectorPopover},
};
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 {
use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate, Properties)]
#[properties(wrapper_type = super::MusicusWorkEditor)]
#[template(file = "data/ui/work_editor.blp")]
pub struct MusicusWorkEditor {
#[properties(wrapper_type = super::WorkEditor)]
#[template(file = "data/ui/editor/work.blp")]
pub struct WorkEditor {
#[property(get, construct_only)]
pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)]
pub library: OnceCell<MusicusLibrary>,
pub library: OnceCell<Library>,
pub work_id: OnceCell<String>,
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
// results when finishing the process of editing the work. The composer rows
// handle all state related to the composer.
pub composer_rows: RefCell<Vec<MusicusWorkEditorComposerRow>>,
pub part_rows: RefCell<Vec<MusicusWorkEditorPartRow>>,
pub composer_rows: RefCell<Vec<WorkEditorComposerRow>>,
pub part_rows: RefCell<Vec<WorkEditorPartRow>>,
pub instruments: RefCell<Vec<Instrument>>,
pub persons_popover: OnceCell<MusicusPersonSelectorPopover>,
pub instruments_popover: OnceCell<MusicusInstrumentSelectorPopover>,
pub persons_popover: OnceCell<PersonSelectorPopover>,
pub instruments_popover: OnceCell<InstrumentSelectorPopover>,
#[template_child]
pub name_editor: TemplateChild<MusicusTranslationEditor>,
pub name_editor: TemplateChild<TranslationEditor>,
#[template_child]
pub composer_list: TemplateChild<gtk::ListBox>,
#[template_child]
@ -68,13 +64,13 @@ mod imp {
}
#[glib::object_subclass]
impl ObjectSubclass for MusicusWorkEditor {
impl ObjectSubclass for WorkEditor {
const NAME: &'static str = "MusicusWorkEditor";
type Type = super::MusicusWorkEditor;
type Type = super::WorkEditor;
type ParentType = adw::NavigationPage;
fn class_init(klass: &mut Self::Class) {
MusicusTranslationEditor::static_type();
TranslationEditor::static_type();
klass.bind_template();
klass.bind_template_instance_callbacks();
}
@ -85,7 +81,7 @@ mod imp {
}
#[glib::derived_properties]
impl ObjectImpl for MusicusWorkEditor {
impl ObjectImpl for WorkEditor {
fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("created")
@ -99,7 +95,7 @@ mod imp {
fn constructed(&self) {
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();
persons_popover.connect_person_selected(move |_, person| {
@ -108,7 +104,7 @@ mod imp {
let obj = self.obj().clone();
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!(
#[weak]
@ -124,8 +120,7 @@ mod imp {
self.select_person_box.append(&persons_popover);
self.persons_popover.set(persons_popover).unwrap();
let instruments_popover =
MusicusInstrumentSelectorPopover::new(self.library.get().unwrap());
let instruments_popover = InstrumentSelectorPopover::new(self.library.get().unwrap());
let obj = self.obj().clone();
instruments_popover.connect_instrument_selected(move |_, instrument| {
@ -134,7 +129,7 @@ mod imp {
let obj = self.obj().clone();
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!(
#[weak]
@ -152,20 +147,20 @@ mod imp {
}
}
impl WidgetImpl for MusicusWorkEditor {}
impl NavigationPageImpl for MusicusWorkEditor {}
impl WidgetImpl for WorkEditor {}
impl NavigationPageImpl for WorkEditor {}
}
glib::wrapper! {
pub struct MusicusWorkEditor(ObjectSubclass<imp::MusicusWorkEditor>)
pub struct WorkEditor(ObjectSubclass<imp::WorkEditor>)
@extends gtk::Widget, adw::NavigationPage;
}
#[gtk::template_callbacks]
impl MusicusWorkEditor {
impl WorkEditor {
pub fn new(
navigation: &adw::NavigationView,
library: &MusicusLibrary,
library: &Library,
work: Option<&Work>,
is_part_editor: bool,
) -> Self {
@ -218,7 +213,7 @@ impl MusicusWorkEditor {
#[template_callback]
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!(
#[weak(rename_to = this)]
@ -243,7 +238,7 @@ impl MusicusWorkEditor {
}
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!(
#[weak(rename_to = this)]
@ -262,7 +257,7 @@ impl MusicusWorkEditor {
}
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!(
#[weak(rename_to = this)]

View file

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

View file

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

View file

@ -1,6 +1,8 @@
use crate::{
db::{self, models::*, schema::*, tables, TranslatedString},
program::Program,
use std::{
cell::{OnceCell, RefCell},
ffi::OsString,
fs,
path::{Path, PathBuf},
};
use adw::{
@ -13,11 +15,9 @@ use chrono::prelude::*;
use diesel::{dsl::exists, prelude::*, QueryDsl, SqliteConnection};
use once_cell::sync::Lazy;
use std::{
cell::{OnceCell, RefCell},
ffi::OsString,
fs,
path::{Path, PathBuf},
use crate::{
db::{self, models::*, schema::*, tables, TranslatedString},
program::Program,
};
diesel::define_sql_function! {
@ -29,21 +29,21 @@ mod imp {
use super::*;
#[derive(Properties, Default)]
#[properties(wrapper_type = super::MusicusLibrary)]
pub struct MusicusLibrary {
#[properties(wrapper_type = super::Library)]
pub struct Library {
#[property(get, construct_only)]
pub folder: OnceCell<String>,
pub connection: RefCell<Option<SqliteConnection>>,
}
#[glib::object_subclass]
impl ObjectSubclass for MusicusLibrary {
impl ObjectSubclass for Library {
const NAME: &'static str = "MusicusLibrary";
type Type = super::MusicusLibrary;
type Type = super::Library;
}
#[glib::derived_properties]
impl ObjectImpl for MusicusLibrary {
impl ObjectImpl for Library {
fn signals() -> &'static [Signal] {
static SIGNALS: Lazy<Vec<Signal>> =
Lazy::new(|| vec![Signal::builder("changed").build()]);
@ -62,10 +62,10 @@ mod imp {
}
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 {
glib::Object::builder()
.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 gettextrs::gettext;
use gtk::glib::{self, clone};
use std::cell::{OnceCell, RefCell};
use crate::{db::models::Album, editor::album::AlbumEditor, library::Library};
mod imp {
use super::*;
@ -13,7 +13,7 @@ mod imp {
#[template(file = "data/ui/library_manager_albums_page.blp")]
pub struct AlbumsPage {
pub navigation: OnceCell<adw::NavigationView>,
pub library: OnceCell<MusicusLibrary>,
pub library: OnceCell<Library>,
pub albums: RefCell<Vec<Album>>,
pub albums_filtered: RefCell<Vec<Album>>,
@ -57,7 +57,7 @@ glib::wrapper! {
#[gtk::template_callbacks]
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 imp = obj.imp();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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