mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Add home page header and hook up editors
This commit is contained in:
parent
38613c0063
commit
f49f23a501
10 changed files with 236 additions and 55 deletions
|
|
@ -1,7 +1,7 @@
|
|||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
|
||||
template $MusicusHomePage : Adw.NavigationPage {
|
||||
template $MusicusHomePage: Adw.NavigationPage {
|
||||
title: _("Musicus");
|
||||
tag: "home";
|
||||
|
||||
|
|
@ -21,14 +21,65 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
maximum-size: 1000;
|
||||
tightening-threshold: 600;
|
||||
|
||||
Gtk.Box {
|
||||
orientation: vertical;
|
||||
|
||||
$MusicusSearchEntry search_entry {
|
||||
activate => $select() swapped;
|
||||
}
|
||||
|
||||
Gtk.Box header_box {
|
||||
visible: false;
|
||||
spacing: 12;
|
||||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
margin-top: 24;
|
||||
margin-bottom: 12;
|
||||
|
||||
Gtk.Button {
|
||||
styles [
|
||||
"flat"
|
||||
]
|
||||
|
||||
valign: center;
|
||||
icon-name: "go-previous-symbolic";
|
||||
clicked => $back_button_clicked() swapped;
|
||||
}
|
||||
|
||||
Gtk.Box {
|
||||
orientation: vertical;
|
||||
hexpand: true;
|
||||
|
||||
Gtk.Label title_label {
|
||||
styles [
|
||||
"title-1"
|
||||
]
|
||||
|
||||
xalign: 0.0;
|
||||
}
|
||||
|
||||
Gtk.Label subtitle_label {
|
||||
xalign: 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.Button {
|
||||
styles [
|
||||
"flat"
|
||||
]
|
||||
|
||||
valign: center;
|
||||
icon-name: "document-edit-symbolic";
|
||||
clicked => $edit_button_clicked() swapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.Stack stack {
|
||||
Gtk.StackPage {
|
||||
name: "results";
|
||||
|
||||
child: Gtk.ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
|
||||
|
|
@ -44,7 +95,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
margin-bottom: 68;
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind composers_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Composers");
|
||||
|
|
@ -61,7 +115,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind performers_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Performers");
|
||||
|
|
@ -78,7 +135,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind ensembles_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Ensembles");
|
||||
|
|
@ -95,7 +155,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind works_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Works");
|
||||
|
|
@ -112,7 +175,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind recordings_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Recordings");
|
||||
|
|
@ -129,7 +195,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
|
||||
Gtk.Label {
|
||||
styles ["heading"]
|
||||
styles [
|
||||
"heading"
|
||||
]
|
||||
|
||||
visible: bind albums_flow_box.visible;
|
||||
halign: start;
|
||||
label: _("Albums");
|
||||
|
|
@ -148,8 +217,10 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
Gtk.StackPage {
|
||||
name: "empty";
|
||||
|
||||
child: Adw.StatusPage {
|
||||
icon-name: "system-search-symbolic";
|
||||
title: _("Nothing Found");
|
||||
|
|
@ -161,7 +232,11 @@ template $MusicusHomePage : Adw.NavigationPage {
|
|||
|
||||
[overlay]
|
||||
Gtk.Button play_button {
|
||||
styles ["pill", "suggested-action"]
|
||||
styles [
|
||||
"pill",
|
||||
"suggested-action"
|
||||
]
|
||||
|
||||
halign: end;
|
||||
valign: end;
|
||||
margin-end: 24;
|
||||
|
|
@ -177,10 +252,12 @@ menu primary_menu {
|
|||
label: _("_Library manager");
|
||||
action: "win.library";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("_Preferences");
|
||||
action: "app.preferences";
|
||||
}
|
||||
|
||||
item {
|
||||
label: _("_About Musicus");
|
||||
action: "app.about";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ template $MusicusPersonEditor: Adw.NavigationPage {
|
|||
Adw.HeaderBar header_bar {}
|
||||
|
||||
Adw.Clamp {
|
||||
Gtk.Box {
|
||||
orientation: vertical;
|
||||
|
||||
Gtk.Label {
|
||||
label: _("Name");
|
||||
xalign: 0;
|
||||
|
|
@ -20,7 +23,8 @@ template $MusicusPersonEditor: Adw.NavigationPage {
|
|||
}
|
||||
|
||||
$MusicusTranslationEditor name_editor {
|
||||
margin-start: 12;
|
||||
margin-top: 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,5 +35,12 @@ template $MusicusRecordingTile : Gtk.FlowBoxChild {
|
|||
wrap: true;
|
||||
}
|
||||
}
|
||||
|
||||
Gtk.Button {
|
||||
styles ["flat"]
|
||||
valign: start;
|
||||
margin-top: 12;
|
||||
icon-name: "view-more-symbolic";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
use adw::{prelude::*, subclass::prelude::*};
|
||||
use gtk::glib;
|
||||
|
||||
use crate::editor::translation_editor::MusicusTranslationEditor;
|
||||
use crate::{db::models::Person, editor::translation_editor::MusicusTranslationEditor};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(file = "data/ui/person_editor.blp")]
|
||||
pub struct MusicusPersonEditor {}
|
||||
pub struct MusicusPersonEditor {
|
||||
#[template_child]
|
||||
pub name_editor: TemplateChild<MusicusTranslationEditor>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for MusicusPersonEditor {
|
||||
|
|
@ -39,7 +42,13 @@ glib::wrapper! {
|
|||
|
||||
#[gtk::template_callbacks]
|
||||
impl MusicusPersonEditor {
|
||||
pub fn new() -> Self {
|
||||
glib::Object::new()
|
||||
pub fn new(person: Option<&Person>) -> Self {
|
||||
let obj: Self = glib::Object::new();
|
||||
|
||||
if let Some(person) = person {
|
||||
obj.imp().name_editor.set_translation(&person.name);
|
||||
}
|
||||
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,19 +55,20 @@ glib::wrapper! {
|
|||
|
||||
#[gtk::template_callbacks]
|
||||
impl MusicusTranslationEditor {
|
||||
pub fn new(translation: TranslatedString) -> Self {
|
||||
let obj: Self = glib::Object::new();
|
||||
let mut translation = translation.0;
|
||||
pub fn new() -> Self {
|
||||
glib::Object::new()
|
||||
}
|
||||
|
||||
obj.imp()
|
||||
pub fn set_translation(&self, translation: &TranslatedString) {
|
||||
let mut translation = translation.0.clone();
|
||||
|
||||
self.imp()
|
||||
.entry_row
|
||||
.set_text(&translation.remove("generic").unwrap_or_default());
|
||||
|
||||
for (lang, translation) in translation {
|
||||
obj.add_entry(&lang, &translation);
|
||||
self.add_entry(&lang, &translation);
|
||||
}
|
||||
|
||||
obj
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
|
|
@ -92,11 +93,17 @@ impl MusicusTranslationEditor {
|
|||
|
||||
let obj = self.clone();
|
||||
entry.connect_remove(move |entry| {
|
||||
obj.imp().translation_entries.borrow_mut().retain(|e| e != entry);
|
||||
obj.imp()
|
||||
.translation_entries
|
||||
.borrow_mut()
|
||||
.retain(|e| e != entry);
|
||||
obj.imp().list_box.remove(entry);
|
||||
});
|
||||
|
||||
self.imp().list_box.insert(&entry, self.imp().translation_entries.borrow().len() as i32 + 1);
|
||||
self.imp().list_box.insert(
|
||||
&entry,
|
||||
self.imp().translation_entries.borrow().len() as i32 + 1,
|
||||
);
|
||||
entry.grab_focus();
|
||||
|
||||
self.imp().translation_entries.borrow_mut().push(entry);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
db::{
|
||||
self,
|
||||
models::{Composer, Instrument, Person, WorkPart},
|
||||
models::{Composer, Instrument, Person, Work, WorkPart},
|
||||
},
|
||||
editor::{
|
||||
instrument_selector_popover::MusicusInstrumentSelectorPopover,
|
||||
|
|
@ -25,6 +25,9 @@ mod imp {
|
|||
#[properties(wrapper_type = super::MusicusWorkEditor)]
|
||||
#[template(file = "data/ui/work_editor.blp")]
|
||||
pub struct MusicusWorkEditor {
|
||||
#[property(get, construct_only)]
|
||||
pub navigation: OnceCell<adw::NavigationView>,
|
||||
|
||||
#[property(get, construct_only)]
|
||||
pub library: OnceCell<MusicusLibrary>,
|
||||
|
||||
|
|
@ -38,6 +41,8 @@ mod imp {
|
|||
pub persons_popover: OnceCell<MusicusPersonSelectorPopover>,
|
||||
pub instruments_popover: OnceCell<MusicusInstrumentSelectorPopover>,
|
||||
|
||||
#[template_child]
|
||||
pub name_editor: TemplateChild<MusicusTranslationEditor>,
|
||||
#[template_child]
|
||||
pub composer_list: TemplateChild<gtk::ListBox>,
|
||||
#[template_child]
|
||||
|
|
@ -146,8 +151,21 @@ glib::wrapper! {
|
|||
|
||||
#[gtk::template_callbacks]
|
||||
impl MusicusWorkEditor {
|
||||
pub fn new(library: &MusicusLibrary) -> Self {
|
||||
glib::Object::builder().property("library", library).build()
|
||||
pub fn new(
|
||||
navigation: &adw::NavigationView,
|
||||
library: &MusicusLibrary,
|
||||
work: Option<&Work>,
|
||||
) -> Self {
|
||||
let obj: Self = glib::Object::builder()
|
||||
.property("navigation", navigation)
|
||||
.property("library", library)
|
||||
.build();
|
||||
|
||||
if let Some(_work) = work {
|
||||
// TODO: Initialize work data.
|
||||
}
|
||||
|
||||
obj
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
album_tile::MusicusAlbumTile,
|
||||
db::models::*,
|
||||
editor::{person_editor::MusicusPersonEditor, work_editor::MusicusWorkEditor},
|
||||
library::{LibraryQuery, MusicusLibrary},
|
||||
player::MusicusPlayer,
|
||||
playlist_item::PlaylistItem,
|
||||
|
|
@ -25,6 +26,9 @@ mod imp {
|
|||
#[properties(wrapper_type = super::MusicusHomePage)]
|
||||
#[template(file = "data/ui/home_page.blp")]
|
||||
pub struct MusicusHomePage {
|
||||
#[property(get, construct_only)]
|
||||
pub navigation: OnceCell<adw::NavigationView>,
|
||||
|
||||
#[property(get, construct_only)]
|
||||
pub library: OnceCell<MusicusLibrary>,
|
||||
|
||||
|
|
@ -43,6 +47,12 @@ mod imp {
|
|||
#[template_child]
|
||||
pub stack: TemplateChild<gtk::Stack>,
|
||||
#[template_child]
|
||||
pub header_box: TemplateChild<gtk::Box>,
|
||||
#[template_child]
|
||||
pub title_label: TemplateChild<gtk::Label>,
|
||||
#[template_child]
|
||||
pub subtitle_label: TemplateChild<gtk::Label>,
|
||||
#[template_child]
|
||||
pub composers_flow_box: TemplateChild<gtk::FlowBox>,
|
||||
#[template_child]
|
||||
pub performers_flow_box: TemplateChild<gtk::FlowBox>,
|
||||
|
|
@ -109,13 +119,41 @@ glib::wrapper! {
|
|||
|
||||
#[gtk::template_callbacks]
|
||||
impl MusicusHomePage {
|
||||
pub fn new(library: &MusicusLibrary, player: &MusicusPlayer) -> Self {
|
||||
pub fn new(
|
||||
navigation: &adw::NavigationView,
|
||||
library: &MusicusLibrary,
|
||||
player: &MusicusPlayer,
|
||||
) -> Self {
|
||||
glib::Object::builder()
|
||||
.property("navigation", navigation)
|
||||
.property("library", library)
|
||||
.property("player", player)
|
||||
.build()
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn back_button_clicked(&self, _: >k::Button) {
|
||||
self.imp().search_entry.reset();
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn edit_button_clicked(&self, _: >k::Button) {
|
||||
if let Some(tag) = self.imp().search_entry.tags().first() {
|
||||
match tag {
|
||||
Tag::Composer(person) | Tag::Performer(person) => {
|
||||
self.navigation()
|
||||
.push(&MusicusPersonEditor::new(Some(person)));
|
||||
}
|
||||
Tag::Ensemble(_) => todo!(),
|
||||
Tag::Work(work) => self.navigation().push(&MusicusWorkEditor::new(
|
||||
&self.navigation(),
|
||||
&self.library(),
|
||||
Some(work),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn play(&self, _: >k::Button) {
|
||||
log::info!("Play button clicked");
|
||||
|
|
@ -262,6 +300,28 @@ impl MusicusHomePage {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(tag) = imp.search_entry.tags().first() {
|
||||
match tag {
|
||||
Tag::Composer(person) | Tag::Performer(person) => {
|
||||
imp.title_label.set_text(&person.name.get());
|
||||
imp.subtitle_label.set_visible(false);
|
||||
}
|
||||
Tag::Ensemble(ensemble) => {
|
||||
imp.title_label.set_text(&ensemble.name.get());
|
||||
imp.subtitle_label.set_visible(false);
|
||||
}
|
||||
Tag::Work(work) => {
|
||||
imp.title_label.set_text(&work.name.get());
|
||||
imp.subtitle_label.set_text(&work.composers_string());
|
||||
imp.subtitle_label.set_visible(true);
|
||||
}
|
||||
}
|
||||
|
||||
imp.header_box.set_visible(true);
|
||||
} else {
|
||||
imp.header_box.set_visible(false);
|
||||
}
|
||||
|
||||
if results.is_empty() {
|
||||
imp.stack.set_visible_child_name("empty");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ use adw::{
|
|||
use gtk::glib::{self, Properties};
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use crate::editor::work_editor::MusicusWorkEditor;
|
||||
use crate::library::MusicusLibrary;
|
||||
|
||||
mod imp {
|
||||
|
|
@ -36,12 +35,7 @@ mod imp {
|
|||
}
|
||||
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for LibraryManager {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
self.obj().set_child(Some(&MusicusWorkEditor::new(self.library.get().unwrap())));
|
||||
}
|
||||
}
|
||||
impl ObjectImpl for LibraryManager {}
|
||||
|
||||
impl WidgetImpl for LibraryManager {}
|
||||
impl NavigationPageImpl for LibraryManager {}
|
||||
|
|
|
|||
|
|
@ -174,6 +174,15 @@ impl MusicusSearchEntry {
|
|||
self.emit_by_name::<()>("query-changed", &[]);
|
||||
}
|
||||
|
||||
pub fn tags(&self) -> Vec<Tag> {
|
||||
self.imp()
|
||||
.tags
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|t| t.tag().to_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn query(&self) -> LibraryQuery {
|
||||
let mut query = LibraryQuery {
|
||||
search: self.imp().text.text().to_string(),
|
||||
|
|
|
|||
|
|
@ -155,12 +155,8 @@ impl MusicusWindow {
|
|||
fn load_library(&self, path: impl AsRef<Path>) {
|
||||
let library = MusicusLibrary::new(path);
|
||||
|
||||
self.imp()
|
||||
.navigation_view
|
||||
.replace(&[MusicusHomePage::new(&library, &self.imp().player).into()]);
|
||||
|
||||
self.imp()
|
||||
.navigation_view
|
||||
.add(&LibraryManager::new(&library));
|
||||
let navigation = self.imp().navigation_view.get();
|
||||
navigation.replace(&[MusicusHomePage::new(&navigation, &library, &self.imp().player).into()]);
|
||||
navigation.add(&LibraryManager::new(&library));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue