mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
Restore edit and delete menus
This commit is contained in:
parent
a93c7276d2
commit
40050b3ac3
12 changed files with 253 additions and 144 deletions
|
|
@ -27,11 +27,12 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuButton" id="menu_button">
|
<object class="GtkMenuButton">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="focus-on-click">False</property>
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
<property name="menu-model">menu</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage">
|
<object class="GtkImage">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
@ -200,4 +201,16 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<menu id="menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Edit ensemble</attribute>
|
||||||
|
<attribute name="action">widget.edit</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete ensemble</attribute>
|
||||||
|
<attribute name="action">widget.delete</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,12 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuButton" id="menu_button">
|
<object class="GtkMenuButton">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="focus-on-click">False</property>
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
<property name="menu-model">menu</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage">
|
<object class="GtkImage">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
@ -258,4 +259,16 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<menu id="menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Edit person</attribute>
|
||||||
|
<attribute name="action">widget.edit</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete person</attribute>
|
||||||
|
<attribute name="action">widget.delete</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,12 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuButton" id="menu_button">
|
<object class="GtkMenuButton">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="focus-on-click">False</property>
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
<property name="menu-model">menu</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage">
|
<object class="GtkImage">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
@ -159,4 +160,26 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<menu id="menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Edit recording</attribute>
|
||||||
|
<attribute name="action">widget.edit</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete recording</attribute>
|
||||||
|
<attribute name="action">widget.delete</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Edit tracks</attribute>
|
||||||
|
<attribute name="action">widget.edit-tracks</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete tracks</attribute>
|
||||||
|
<attribute name="action">widget.delete-tracks</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,12 @@
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkMenuButton" id="menu_button">
|
<object class="GtkMenuButton">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="focus-on-click">False</property>
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
<property name="menu-model">menu</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkImage">
|
<object class="GtkImage">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
@ -200,4 +201,16 @@
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<menu id="menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Edit work</attribute>
|
||||||
|
<attribute name="action">widget.edit</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Delete work</attribute>
|
||||||
|
<attribute name="action">widget.delete</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ where
|
||||||
let c = glib::MainContext::default();
|
let c = glib::MainContext::default();
|
||||||
c.spawn_local(async move {
|
c.spawn_local(async move {
|
||||||
clone.backend.db().update_ensemble(ensemble.clone()).await.unwrap();
|
clone.backend.db().update_ensemble(ensemble.clone()).await.unwrap();
|
||||||
clone.window.close();
|
|
||||||
(clone.callback)(ensemble.clone());
|
(clone.callback)(ensemble.clone());
|
||||||
|
clone.window.close();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,9 @@ impl RecordingEditorDialog {
|
||||||
editor.set_selected_cb(clone!(@strong this => move |recording| {
|
editor.set_selected_cb(clone!(@strong this => move |recording| {
|
||||||
if let Some(cb) = &*this.selected_cb.borrow() {
|
if let Some(cb) = &*this.selected_cb.borrow() {
|
||||||
cb(recording);
|
cb(recording);
|
||||||
this.window.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.window.close();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this
|
this
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,9 @@ impl WorkEditorDialog {
|
||||||
editor.set_saved_cb(clone!(@strong this => move |work| {
|
editor.set_saved_cb(clone!(@strong this => move |work| {
|
||||||
if let Some(cb) = &*this.saved_cb.borrow() {
|
if let Some(cb) = &*this.saved_cb.borrow() {
|
||||||
cb(work);
|
cb(work);
|
||||||
this.window.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.window.close();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this
|
this
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
|
use crate::dialogs::EnsembleEditor;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
|
use gio::prelude::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk_macros::get_widget;
|
use gtk_macros::get_widget;
|
||||||
|
|
@ -12,6 +14,8 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub struct EnsembleScreen {
|
pub struct EnsembleScreen {
|
||||||
backend: Rc<Backend>,
|
backend: Rc<Backend>,
|
||||||
|
window: gtk::Window,
|
||||||
|
ensemble: Ensemble,
|
||||||
widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
recording_list: Rc<List<Recording>>,
|
recording_list: Rc<List<Recording>>,
|
||||||
|
|
@ -19,36 +23,29 @@ pub struct EnsembleScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnsembleScreen {
|
impl EnsembleScreen {
|
||||||
pub fn new(backend: Rc<Backend>, ensemble: Ensemble) -> Rc<Self> {
|
pub fn new<W>(backend: Rc<Backend>, window: &W, ensemble: Ensemble) -> Rc<Self>
|
||||||
|
where
|
||||||
|
W: IsA<gtk::Window>,
|
||||||
|
{
|
||||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/ensemble_screen.ui");
|
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/ensemble_screen.ui");
|
||||||
|
|
||||||
get_widget!(builder, gtk::Box, widget);
|
get_widget!(builder, gtk::Box, widget);
|
||||||
get_widget!(builder, libhandy::HeaderBar, header);
|
get_widget!(builder, libhandy::HeaderBar, header);
|
||||||
get_widget!(builder, gtk::Button, back_button);
|
get_widget!(builder, gtk::Button, back_button);
|
||||||
get_widget!(builder, gtk::MenuButton, menu_button);
|
|
||||||
get_widget!(builder, gtk::SearchEntry, search_entry);
|
get_widget!(builder, gtk::SearchEntry, search_entry);
|
||||||
get_widget!(builder, gtk::Stack, stack);
|
get_widget!(builder, gtk::Stack, stack);
|
||||||
get_widget!(builder, gtk::Frame, recording_frame);
|
get_widget!(builder, gtk::Frame, recording_frame);
|
||||||
|
|
||||||
header.set_title(Some(&ensemble.name));
|
header.set_title(Some(&ensemble.name));
|
||||||
|
|
||||||
let edit_menu_item = gio::MenuItem::new(Some(&gettext("Edit ensemble")), None);
|
let edit_action = gio::SimpleAction::new("edit", None);
|
||||||
edit_menu_item.set_action_and_target_value(
|
let delete_action = gio::SimpleAction::new("delete", None);
|
||||||
Some("win.edit-ensemble"),
|
|
||||||
Some(&glib::Variant::from(ensemble.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let delete_menu_item = gio::MenuItem::new(Some(&gettext("Delete ensemble")), None);
|
let actions = gio::SimpleActionGroup::new();
|
||||||
delete_menu_item.set_action_and_target_value(
|
actions.add_action(&edit_action);
|
||||||
Some("win.delete-ensemble"),
|
actions.add_action(&delete_action);
|
||||||
Some(&glib::Variant::from(ensemble.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let menu = gio::Menu::new();
|
widget.insert_action_group("widget", Some(&actions));
|
||||||
menu.append_item(&edit_menu_item);
|
|
||||||
menu.append_item(&delete_menu_item);
|
|
||||||
|
|
||||||
menu_button.set_menu_model(Some(&menu));
|
|
||||||
|
|
||||||
let recording_list = List::new(&gettext("No recordings found."));
|
let recording_list = List::new(&gettext("No recordings found."));
|
||||||
|
|
||||||
|
|
@ -83,6 +80,8 @@ impl EnsembleScreen {
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
backend,
|
backend,
|
||||||
|
window: window.clone().upcast(),
|
||||||
|
ensemble,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
recording_list,
|
recording_list,
|
||||||
|
|
@ -105,17 +104,29 @@ impl EnsembleScreen {
|
||||||
.set_selected(clone!(@strong result => move |recording| {
|
.set_selected(clone!(@strong result => move |recording| {
|
||||||
let navigator = result.navigator.borrow().clone();
|
let navigator = result.navigator.borrow().clone();
|
||||||
if let Some(navigator) = navigator {
|
if let Some(navigator) = navigator {
|
||||||
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
navigator.push(RecordingScreen::new(result.backend.clone(), &result.window, recording.clone()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
edit_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
EnsembleEditor::new(result.backend.clone(), &result.window, Some(result.ensemble.clone()), |_| {}).show();
|
||||||
|
}));
|
||||||
|
|
||||||
|
delete_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = result.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
clone.backend.db().delete_ensemble(clone.ensemble.id).await.unwrap();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let recordings = clone
|
let recordings = clone
|
||||||
.backend
|
.backend
|
||||||
.db()
|
.db()
|
||||||
.get_recordings_for_ensemble(ensemble.id as u32)
|
.get_recordings_for_ensemble(clone.ensemble.id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
|
use crate::dialogs::PersonEditor;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
|
use gio::prelude::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk_macros::get_widget;
|
use gtk_macros::get_widget;
|
||||||
|
|
@ -12,6 +14,8 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub struct PersonScreen {
|
pub struct PersonScreen {
|
||||||
backend: Rc<Backend>,
|
backend: Rc<Backend>,
|
||||||
|
window: gtk::Window,
|
||||||
|
person: Person,
|
||||||
widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
work_list: Rc<List<Work>>,
|
work_list: Rc<List<Work>>,
|
||||||
|
|
@ -20,13 +24,15 @@ pub struct PersonScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PersonScreen {
|
impl PersonScreen {
|
||||||
pub fn new(backend: Rc<Backend>, person: Person) -> Rc<Self> {
|
pub fn new<W>(backend: Rc<Backend>, window: &W, person: Person) -> Rc<Self>
|
||||||
|
where
|
||||||
|
W: IsA<gtk::Window>,
|
||||||
|
{
|
||||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/person_screen.ui");
|
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/person_screen.ui");
|
||||||
|
|
||||||
get_widget!(builder, gtk::Box, widget);
|
get_widget!(builder, gtk::Box, widget);
|
||||||
get_widget!(builder, libhandy::HeaderBar, header);
|
get_widget!(builder, libhandy::HeaderBar, header);
|
||||||
get_widget!(builder, gtk::Button, back_button);
|
get_widget!(builder, gtk::Button, back_button);
|
||||||
get_widget!(builder, gtk::MenuButton, menu_button);
|
|
||||||
get_widget!(builder, gtk::SearchEntry, search_entry);
|
get_widget!(builder, gtk::SearchEntry, search_entry);
|
||||||
get_widget!(builder, gtk::Stack, stack);
|
get_widget!(builder, gtk::Stack, stack);
|
||||||
get_widget!(builder, gtk::Box, work_box);
|
get_widget!(builder, gtk::Box, work_box);
|
||||||
|
|
@ -36,23 +42,14 @@ impl PersonScreen {
|
||||||
|
|
||||||
header.set_title(Some(&person.name_fl()));
|
header.set_title(Some(&person.name_fl()));
|
||||||
|
|
||||||
let edit_menu_item = gio::MenuItem::new(Some(&gettext("Edit person")), None);
|
let edit_action = gio::SimpleAction::new("edit", None);
|
||||||
edit_menu_item.set_action_and_target_value(
|
let delete_action = gio::SimpleAction::new("delete", None);
|
||||||
Some("win.edit-person"),
|
|
||||||
Some(&glib::Variant::from(person.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let delete_menu_item = gio::MenuItem::new(Some(&gettext("Delete person")), None);
|
let actions = gio::SimpleActionGroup::new();
|
||||||
delete_menu_item.set_action_and_target_value(
|
actions.add_action(&edit_action);
|
||||||
Some("win.delete-person"),
|
actions.add_action(&delete_action);
|
||||||
Some(&glib::Variant::from(person.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let menu = gio::Menu::new();
|
widget.insert_action_group("widget", Some(&actions));
|
||||||
menu.append_item(&edit_menu_item);
|
|
||||||
menu.append_item(&delete_menu_item);
|
|
||||||
|
|
||||||
menu_button.set_menu_model(Some(&menu));
|
|
||||||
|
|
||||||
let work_list = List::new(&gettext("No works found."));
|
let work_list = List::new(&gettext("No works found."));
|
||||||
|
|
||||||
|
|
@ -106,6 +103,8 @@ impl PersonScreen {
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
backend,
|
backend,
|
||||||
|
window: window.clone().upcast(),
|
||||||
|
person,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
work_list,
|
work_list,
|
||||||
|
|
@ -131,7 +130,7 @@ impl PersonScreen {
|
||||||
result.recording_list.clear_selection();
|
result.recording_list.clear_selection();
|
||||||
let navigator = result.navigator.borrow().clone();
|
let navigator = result.navigator.borrow().clone();
|
||||||
if let Some(navigator) = navigator {
|
if let Some(navigator) = navigator {
|
||||||
navigator.push(WorkScreen::new(result.backend.clone(), work.clone()));
|
navigator.push(WorkScreen::new(result.backend.clone(), &result.window, work.clone()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
@ -141,23 +140,35 @@ impl PersonScreen {
|
||||||
result.work_list.clear_selection();
|
result.work_list.clear_selection();
|
||||||
let navigator = result.navigator.borrow().clone();
|
let navigator = result.navigator.borrow().clone();
|
||||||
if let Some(navigator) = navigator {
|
if let Some(navigator) = navigator {
|
||||||
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
navigator.push(RecordingScreen::new(result.backend.clone(), &result.window, recording.clone()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
edit_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
PersonEditor::new(result.backend.clone(), &result.window, Some(result.person.clone()), |_| {}).show();
|
||||||
|
}));
|
||||||
|
|
||||||
|
delete_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = result.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
clone.backend.db().delete_person(clone.person.id).await.unwrap();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let works = clone
|
let works = clone
|
||||||
.backend
|
.backend
|
||||||
.db()
|
.db()
|
||||||
.get_works(person.id as u32)
|
.get_works(clone.person.id as u32)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let recordings = clone
|
let recordings = clone
|
||||||
.backend
|
.backend
|
||||||
.db()
|
.db()
|
||||||
.get_recordings_for_person(person.id as u32)
|
.get_recordings_for_person(clone.person.id as u32)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
|
use crate::dialogs::{RecordingEditorDialog, TracksEditor};
|
||||||
use crate::player::*;
|
use crate::player::*;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
|
use gio::prelude::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk_macros::get_widget;
|
use gtk_macros::get_widget;
|
||||||
|
|
@ -12,6 +14,8 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub struct RecordingScreen {
|
pub struct RecordingScreen {
|
||||||
backend: Rc<Backend>,
|
backend: Rc<Backend>,
|
||||||
|
window: gtk::Window,
|
||||||
|
recording: Recording,
|
||||||
widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
tracks: RefCell<Vec<Track>>,
|
tracks: RefCell<Vec<Track>>,
|
||||||
|
|
@ -19,13 +23,15 @@ pub struct RecordingScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecordingScreen {
|
impl RecordingScreen {
|
||||||
pub fn new(backend: Rc<Backend>, recording: Recording) -> Rc<Self> {
|
pub fn new<W>(backend: Rc<Backend>, window: &W, recording: Recording) -> Rc<Self>
|
||||||
|
where
|
||||||
|
W: IsA<gtk::Window>,
|
||||||
|
{
|
||||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/recording_screen.ui");
|
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/recording_screen.ui");
|
||||||
|
|
||||||
get_widget!(builder, gtk::Box, widget);
|
get_widget!(builder, gtk::Box, widget);
|
||||||
get_widget!(builder, libhandy::HeaderBar, header);
|
get_widget!(builder, libhandy::HeaderBar, header);
|
||||||
get_widget!(builder, gtk::Button, back_button);
|
get_widget!(builder, gtk::Button, back_button);
|
||||||
get_widget!(builder, gtk::MenuButton, menu_button);
|
|
||||||
get_widget!(builder, gtk::Stack, stack);
|
get_widget!(builder, gtk::Stack, stack);
|
||||||
get_widget!(builder, gtk::Frame, frame);
|
get_widget!(builder, gtk::Frame, frame);
|
||||||
get_widget!(builder, gtk::Button, add_to_playlist_button);
|
get_widget!(builder, gtk::Button, add_to_playlist_button);
|
||||||
|
|
@ -33,46 +39,36 @@ impl RecordingScreen {
|
||||||
header.set_title(Some(&recording.work.get_title()));
|
header.set_title(Some(&recording.work.get_title()));
|
||||||
header.set_subtitle(Some(&recording.get_performers()));
|
header.set_subtitle(Some(&recording.get_performers()));
|
||||||
|
|
||||||
let edit_menu_item = gio::MenuItem::new(Some(&gettext("Edit recording")), None);
|
let edit_action = gio::SimpleAction::new("edit", None);
|
||||||
edit_menu_item.set_action_and_target_value(
|
let delete_action = gio::SimpleAction::new("delete", None);
|
||||||
Some("win.edit-recording"),
|
let edit_tracks_action = gio::SimpleAction::new("edit-tracks", None);
|
||||||
Some(&glib::Variant::from(recording.id)),
|
let delete_tracks_action = gio::SimpleAction::new("delete-tracks", None);
|
||||||
);
|
|
||||||
|
|
||||||
let delete_menu_item = gio::MenuItem::new(Some(&gettext("Delete recording")), None);
|
let actions = gio::SimpleActionGroup::new();
|
||||||
delete_menu_item.set_action_and_target_value(
|
actions.add_action(&edit_action);
|
||||||
Some("win.delete-recording"),
|
actions.add_action(&delete_action);
|
||||||
Some(&glib::Variant::from(recording.id)),
|
actions.add_action(&edit_tracks_action);
|
||||||
);
|
actions.add_action(&delete_tracks_action);
|
||||||
|
|
||||||
let edit_tracks_menu_item = gio::MenuItem::new(Some(&gettext("Edit tracks")), None);
|
widget.insert_action_group("widget", Some(&actions));
|
||||||
edit_tracks_menu_item.set_action_and_target_value(
|
|
||||||
Some("win.edit-tracks"),
|
|
||||||
Some(&glib::Variant::from(recording.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let delete_tracks_menu_item = gio::MenuItem::new(Some(&gettext("Delete tracks")), None);
|
|
||||||
delete_tracks_menu_item.set_action_and_target_value(
|
|
||||||
Some("win.delete-tracks"),
|
|
||||||
Some(&glib::Variant::from(recording.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let menu = gio::Menu::new();
|
|
||||||
menu.append_item(&edit_menu_item);
|
|
||||||
menu.append_item(&delete_menu_item);
|
|
||||||
menu.append_item(&edit_tracks_menu_item);
|
|
||||||
menu.append_item(&delete_tracks_menu_item);
|
|
||||||
|
|
||||||
menu_button.set_menu_model(Some(&menu));
|
|
||||||
|
|
||||||
let recording = Rc::new(recording);
|
|
||||||
let list = List::new(&gettext("No tracks found."));
|
let list = List::new(&gettext("No tracks found."));
|
||||||
|
frame.add(&list.widget);
|
||||||
|
|
||||||
list.set_make_widget(
|
let result = Rc::new(Self {
|
||||||
clone!(@strong recording => move |track: &Track| {
|
backend,
|
||||||
|
window: window.clone().upcast(),
|
||||||
|
recording,
|
||||||
|
widget,
|
||||||
|
stack,
|
||||||
|
tracks: RefCell::new(Vec::new()),
|
||||||
|
navigator: RefCell::new(None),
|
||||||
|
});
|
||||||
|
|
||||||
|
list.set_make_widget(clone!(@strong result => move |track: &Track| {
|
||||||
let mut title_parts = Vec::<String>::new();
|
let mut title_parts = Vec::<String>::new();
|
||||||
for part in &track.work_parts {
|
for part in &track.work_parts {
|
||||||
title_parts.push(recording.work.parts[*part].title.clone());
|
title_parts.push(result.recording.work.parts[*part].title.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = if title_parts.is_empty() {
|
let title = if title_parts.is_empty() {
|
||||||
|
|
@ -96,18 +92,7 @@ impl RecordingScreen {
|
||||||
vbox.add(&file_name_label);
|
vbox.add(&file_name_label);
|
||||||
|
|
||||||
vbox.upcast()
|
vbox.upcast()
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
|
|
||||||
frame.add(&list.widget);
|
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
|
||||||
backend,
|
|
||||||
widget,
|
|
||||||
stack,
|
|
||||||
tracks: RefCell::new(Vec::new()),
|
|
||||||
navigator: RefCell::new(None),
|
|
||||||
});
|
|
||||||
|
|
||||||
back_button.connect_clicked(clone!(@strong result => move |_| {
|
back_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
let navigator = result.navigator.borrow().clone();
|
let navigator = result.navigator.borrow().clone();
|
||||||
|
|
@ -116,22 +101,49 @@ impl RecordingScreen {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
add_to_playlist_button.connect_clicked(
|
add_to_playlist_button.connect_clicked(clone!(@strong result => move |_| {
|
||||||
clone!(@strong result, @strong recording => move |_| {
|
|
||||||
if let Some(player) = result.backend.get_player() {
|
if let Some(player) = result.backend.get_player() {
|
||||||
player.add_item(PlaylistItem {
|
player.add_item(PlaylistItem {
|
||||||
recording: (*recording).clone(),
|
recording: result.recording.clone(),
|
||||||
tracks: result.tracks.borrow().clone(),
|
tracks: result.tracks.borrow().clone(),
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
}
|
}
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
|
edit_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
RecordingEditorDialog::new(result.backend.clone(), &result.window, Some(result.recording.clone())).show();
|
||||||
|
}));
|
||||||
|
|
||||||
|
delete_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = result.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
clone.backend.db().delete_recording(clone.recording.id).await.unwrap();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
edit_tracks_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
TracksEditor::new(result.backend.clone(), &result.window, Some(result.recording.clone()), result.tracks.borrow().clone()).show();
|
||||||
|
}));
|
||||||
|
|
||||||
|
delete_tracks_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = result.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
clone.backend.db().delete_tracks(clone.recording.id).await.unwrap();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
let id = recording.id;
|
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let tracks = clone.backend.db().get_tracks(id as u32).await.unwrap();
|
let tracks = clone
|
||||||
|
.backend
|
||||||
|
.db()
|
||||||
|
.get_tracks(clone.recording.id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
list.show_items(tracks.clone());
|
list.show_items(tracks.clone());
|
||||||
clone.stack.set_visible_child_name("content");
|
clone.stack.set_visible_child_name("content");
|
||||||
clone.tracks.replace(tracks);
|
clone.tracks.replace(tracks);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::backend::*;
|
use crate::backend::*;
|
||||||
use crate::database::*;
|
use crate::database::*;
|
||||||
|
use crate::dialogs::WorkEditorDialog;
|
||||||
use crate::widgets::*;
|
use crate::widgets::*;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
|
use gio::prelude::*;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk_macros::get_widget;
|
use gtk_macros::get_widget;
|
||||||
|
|
@ -12,6 +14,8 @@ use std::rc::Rc;
|
||||||
|
|
||||||
pub struct WorkScreen {
|
pub struct WorkScreen {
|
||||||
backend: Rc<Backend>,
|
backend: Rc<Backend>,
|
||||||
|
window: gtk::Window,
|
||||||
|
work: Work,
|
||||||
widget: gtk::Box,
|
widget: gtk::Box,
|
||||||
stack: gtk::Stack,
|
stack: gtk::Stack,
|
||||||
recording_list: Rc<List<Recording>>,
|
recording_list: Rc<List<Recording>>,
|
||||||
|
|
@ -19,13 +23,15 @@ pub struct WorkScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkScreen {
|
impl WorkScreen {
|
||||||
pub fn new(backend: Rc<Backend>, work: Work) -> Rc<Self> {
|
pub fn new<W>(backend: Rc<Backend>, window: &W, work: Work) -> Rc<Self>
|
||||||
|
where
|
||||||
|
W: IsA<gtk::Window>,
|
||||||
|
{
|
||||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/work_screen.ui");
|
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/work_screen.ui");
|
||||||
|
|
||||||
get_widget!(builder, gtk::Box, widget);
|
get_widget!(builder, gtk::Box, widget);
|
||||||
get_widget!(builder, libhandy::HeaderBar, header);
|
get_widget!(builder, libhandy::HeaderBar, header);
|
||||||
get_widget!(builder, gtk::Button, back_button);
|
get_widget!(builder, gtk::Button, back_button);
|
||||||
get_widget!(builder, gtk::MenuButton, menu_button);
|
|
||||||
get_widget!(builder, gtk::SearchEntry, search_entry);
|
get_widget!(builder, gtk::SearchEntry, search_entry);
|
||||||
get_widget!(builder, gtk::Stack, stack);
|
get_widget!(builder, gtk::Stack, stack);
|
||||||
get_widget!(builder, gtk::Frame, recording_frame);
|
get_widget!(builder, gtk::Frame, recording_frame);
|
||||||
|
|
@ -33,23 +39,14 @@ impl WorkScreen {
|
||||||
header.set_title(Some(&work.title));
|
header.set_title(Some(&work.title));
|
||||||
header.set_subtitle(Some(&work.composer.name_fl()));
|
header.set_subtitle(Some(&work.composer.name_fl()));
|
||||||
|
|
||||||
let edit_menu_item = gio::MenuItem::new(Some(&gettext("Edit work")), None);
|
let edit_action = gio::SimpleAction::new("edit", None);
|
||||||
edit_menu_item.set_action_and_target_value(
|
let delete_action = gio::SimpleAction::new("delete", None);
|
||||||
Some("win.edit-work"),
|
|
||||||
Some(&glib::Variant::from(work.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let delete_menu_item = gio::MenuItem::new(Some(&gettext("Delete work")), None);
|
let actions = gio::SimpleActionGroup::new();
|
||||||
delete_menu_item.set_action_and_target_value(
|
actions.add_action(&edit_action);
|
||||||
Some("win.delete-work"),
|
actions.add_action(&delete_action);
|
||||||
Some(&glib::Variant::from(work.id)),
|
|
||||||
);
|
|
||||||
|
|
||||||
let menu = gio::Menu::new();
|
widget.insert_action_group("widget", Some(&actions));
|
||||||
menu.append_item(&edit_menu_item);
|
|
||||||
menu.append_item(&delete_menu_item);
|
|
||||||
|
|
||||||
menu_button.set_menu_model(Some(&menu));
|
|
||||||
|
|
||||||
let recording_list = List::new(&gettext("No recordings found."));
|
let recording_list = List::new(&gettext("No recordings found."));
|
||||||
|
|
||||||
|
|
@ -82,6 +79,8 @@ impl WorkScreen {
|
||||||
|
|
||||||
let result = Rc::new(Self {
|
let result = Rc::new(Self {
|
||||||
backend,
|
backend,
|
||||||
|
window: window.clone().upcast(),
|
||||||
|
work,
|
||||||
widget,
|
widget,
|
||||||
stack,
|
stack,
|
||||||
recording_list,
|
recording_list,
|
||||||
|
|
@ -104,17 +103,29 @@ impl WorkScreen {
|
||||||
.set_selected(clone!(@strong result => move |recording| {
|
.set_selected(clone!(@strong result => move |recording| {
|
||||||
let navigator = result.navigator.borrow().clone();
|
let navigator = result.navigator.borrow().clone();
|
||||||
if let Some(navigator) = navigator {
|
if let Some(navigator) = navigator {
|
||||||
navigator.push(RecordingScreen::new(result.backend.clone(), recording.clone()));
|
navigator.push(RecordingScreen::new(result.backend.clone(), &result.window, recording.clone()));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
edit_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
WorkEditorDialog::new(result.backend.clone(), &result.window, Some(result.work.clone())).show();
|
||||||
|
}));
|
||||||
|
|
||||||
|
delete_action.connect_activate(clone!(@strong result => move |_, _| {
|
||||||
|
let context = glib::MainContext::default();
|
||||||
|
let clone = result.clone();
|
||||||
|
context.spawn_local(async move {
|
||||||
|
clone.backend.db().delete_work(clone.work.id).await.unwrap();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
let context = glib::MainContext::default();
|
let context = glib::MainContext::default();
|
||||||
let clone = result.clone();
|
let clone = result.clone();
|
||||||
context.spawn_local(async move {
|
context.spawn_local(async move {
|
||||||
let recordings = clone
|
let recordings = clone
|
||||||
.backend
|
.backend
|
||||||
.db()
|
.db()
|
||||||
.get_recordings_for_work(work.id as u32)
|
.get_recordings_for_work(clone.work.id as u32)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,10 +161,10 @@ impl Window {
|
||||||
result.leaflet.set_visible_child(&result.navigator.widget);
|
result.leaflet.set_visible_child(&result.navigator.widget);
|
||||||
match poe {
|
match poe {
|
||||||
PersonOrEnsemble::Person(person) => {
|
PersonOrEnsemble::Person(person) => {
|
||||||
result.navigator.clone().replace(PersonScreen::new(result.backend.clone(), person.clone()));
|
result.navigator.clone().replace(PersonScreen::new(result.backend.clone(), &result.window, person.clone()));
|
||||||
}
|
}
|
||||||
PersonOrEnsemble::Ensemble(ensemble) => {
|
PersonOrEnsemble::Ensemble(ensemble) => {
|
||||||
result.navigator.clone().replace(EnsembleScreen::new(result.backend.clone(), ensemble.clone()));
|
result.navigator.clone().replace(EnsembleScreen::new(result.backend.clone(), &result.window, ensemble.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue