mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Implement deletion
This commit is contained in:
parent
b25d7fe8ee
commit
751dcde351
8 changed files with 340 additions and 40 deletions
39
data/ui/error_dialog.blp
Normal file
39
data/ui/error_dialog.blp
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
template $MusicusErrorDialog: Adw.Dialog {
|
||||||
|
content-width: 600;
|
||||||
|
content-height: 400;
|
||||||
|
|
||||||
|
Adw.ToastOverlay toast_overlay {
|
||||||
|
Adw.ToolbarView {
|
||||||
|
[top]
|
||||||
|
Adw.HeaderBar {
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: _("Error");
|
||||||
|
};
|
||||||
|
|
||||||
|
[end]
|
||||||
|
Gtk.Button {
|
||||||
|
icon-name: "edit-copy-symbolic";
|
||||||
|
tooltip-text: _("Copy details to clipboard");
|
||||||
|
clicked => $copy() swapped;
|
||||||
|
|
||||||
|
styles [
|
||||||
|
"flat",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk.ScrolledWindow {
|
||||||
|
Gtk.Label error_label {
|
||||||
|
xalign: 0.0;
|
||||||
|
margin-start: 12;
|
||||||
|
margin-end: 12;
|
||||||
|
margin-top: 12;
|
||||||
|
margin-bottom: 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,12 +4,14 @@ using Adw 1;
|
||||||
template $MusicusWindow: Adw.ApplicationWindow {
|
template $MusicusWindow: Adw.ApplicationWindow {
|
||||||
title: _("Musicus");
|
title: _("Musicus");
|
||||||
|
|
||||||
|
Adw.ToastOverlay toast_overlay {
|
||||||
Adw.ToolbarView {
|
Adw.ToolbarView {
|
||||||
Gtk.Stack stack {
|
Gtk.Stack stack {
|
||||||
transition-type: over_up_down;
|
transition-type: over_up_down;
|
||||||
|
|
||||||
Gtk.StackPage {
|
Gtk.StackPage {
|
||||||
name: "navigation";
|
name: "navigation";
|
||||||
|
|
||||||
child: Adw.NavigationView navigation_view {
|
child: Adw.NavigationView navigation_view {
|
||||||
$MusicusWelcomePage {
|
$MusicusWelcomePage {
|
||||||
folder-selected => $set_library_folder() swapped;
|
folder-selected => $set_library_folder() swapped;
|
||||||
|
|
@ -25,3 +27,4 @@ template $MusicusWindow : Adw.ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
use std::cell::OnceCell;
|
use std::cell::OnceCell;
|
||||||
|
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
|
use gettextrs::gettext;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio,
|
gio,
|
||||||
glib::{self, Properties},
|
glib::{self, clone, Properties},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::models::*, editor::album::AlbumEditor, library::Library, player::Player,
|
db::models::*, editor::album::AlbumEditor, library::Library, player::Player,
|
||||||
playlist_item::PlaylistItem, recording_tile::RecordingTile,
|
playlist_item::PlaylistItem, recording_tile::RecordingTile, util::error_dialog::ErrorDialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
|
|
@ -19,6 +20,9 @@ mod imp {
|
||||||
#[properties(wrapper_type = super::AlbumPage)]
|
#[properties(wrapper_type = super::AlbumPage)]
|
||||||
#[template(file = "data/ui/album_page.blp")]
|
#[template(file = "data/ui/album_page.blp")]
|
||||||
pub struct AlbumPage {
|
pub struct AlbumPage {
|
||||||
|
#[property(get, construct_only)]
|
||||||
|
pub toast_overlay: OnceCell<adw::ToastOverlay>,
|
||||||
|
|
||||||
#[property(get, construct_only)]
|
#[property(get, construct_only)]
|
||||||
pub navigation: OnceCell<adw::NavigationView>,
|
pub navigation: OnceCell<adw::NavigationView>,
|
||||||
|
|
||||||
|
|
@ -90,10 +94,28 @@ mod imp {
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// let obj = self.obj().to_owned();
|
let obj = self.obj().to_owned();
|
||||||
let delete_action = gio::ActionEntry::builder("delete")
|
let delete_action = gio::ActionEntry::builder("delete")
|
||||||
.activate(move |_, _, _| {
|
.activate(move |_, _, _| {
|
||||||
log::error!("Delete not implemented");
|
if let Err(err) = obj
|
||||||
|
.library()
|
||||||
|
.delete_album(&obj.imp().album.get().unwrap().album_id)
|
||||||
|
{
|
||||||
|
let toast = adw::Toast::builder()
|
||||||
|
.title(&gettext("Failed to delete album"))
|
||||||
|
.button_label("Details")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
toast.connect_button_clicked(clone!(
|
||||||
|
#[weak]
|
||||||
|
obj,
|
||||||
|
move |_| {
|
||||||
|
ErrorDialog::present(&err, &obj);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
obj.toast_overlay().add_toast(toast);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
@ -115,12 +137,14 @@ glib::wrapper! {
|
||||||
#[gtk::template_callbacks]
|
#[gtk::template_callbacks]
|
||||||
impl AlbumPage {
|
impl AlbumPage {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
toast_overlay: &adw::ToastOverlay,
|
||||||
navigation: &adw::NavigationView,
|
navigation: &adw::NavigationView,
|
||||||
library: &Library,
|
library: &Library,
|
||||||
player: &Player,
|
player: &Player,
|
||||||
album: Album,
|
album: Album,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let obj: Self = glib::Object::builder()
|
let obj: Self = glib::Object::builder()
|
||||||
|
.property("toast-overlay", toast_overlay)
|
||||||
.property("navigation", navigation)
|
.property("navigation", navigation)
|
||||||
.property("library", library)
|
.property("library", library)
|
||||||
.property("player", player)
|
.property("player", player)
|
||||||
|
|
|
||||||
|
|
@ -879,6 +879,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_person(&self, person_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(persons::table)
|
||||||
|
.filter(persons::person_id.eq(person_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_instrument(&self, name: TranslatedString) -> Result<Instrument> {
|
pub fn create_instrument(&self, name: TranslatedString) -> Result<Instrument> {
|
||||||
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
|
@ -921,6 +933,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_instrument(&self, instrument_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(instruments::table)
|
||||||
|
.filter(instruments::instrument_id.eq(instrument_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_role(&self, name: TranslatedString) -> Result<Role> {
|
pub fn create_role(&self, name: TranslatedString) -> Result<Role> {
|
||||||
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
|
@ -962,6 +986,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_role(&self, role_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(roles::table)
|
||||||
|
.filter(roles::role_id.eq(role_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_work(
|
pub fn create_work(
|
||||||
&self,
|
&self,
|
||||||
name: TranslatedString,
|
name: TranslatedString,
|
||||||
|
|
@ -1175,6 +1211,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_work(&self, work_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(works::table)
|
||||||
|
.filter(works::work_id.eq(work_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_ensemble(&self, name: TranslatedString) -> Result<Ensemble> {
|
pub fn create_ensemble(&self, name: TranslatedString) -> Result<Ensemble> {
|
||||||
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
|
@ -1223,6 +1271,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_ensemble(&self, ensemble_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(ensembles::table)
|
||||||
|
.filter(ensembles::ensemble_id.eq(ensemble_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_recording(
|
pub fn create_recording(
|
||||||
&self,
|
&self,
|
||||||
work: Work,
|
work: Work,
|
||||||
|
|
@ -1345,6 +1405,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_recording(&self, recording_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(recordings::table)
|
||||||
|
.filter(recordings::recording_id.eq(recording_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_album(
|
pub fn create_album(
|
||||||
&self,
|
&self,
|
||||||
name: TranslatedString,
|
name: TranslatedString,
|
||||||
|
|
@ -1427,6 +1499,18 @@ impl Library {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn delete_album(&self, album_id: &str) -> Result<()> {
|
||||||
|
let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap();
|
||||||
|
|
||||||
|
diesel::delete(albums::table)
|
||||||
|
.filter(albums::album_id.eq(album_id))
|
||||||
|
.execute(connection)?;
|
||||||
|
|
||||||
|
self.changed();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Import a track into the music library.
|
/// Import a track into the music library.
|
||||||
// TODO: Support mediums.
|
// TODO: Support mediums.
|
||||||
pub fn import_track(
|
pub fn import_track(
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use formatx::formatx;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
gio,
|
gio,
|
||||||
glib::{self, Properties},
|
glib::{self, clone, Properties},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -25,6 +25,7 @@ use crate::{
|
||||||
recording_tile::RecordingTile,
|
recording_tile::RecordingTile,
|
||||||
search_tag::Tag,
|
search_tag::Tag,
|
||||||
tag_tile::TagTile,
|
tag_tile::TagTile,
|
||||||
|
util::error_dialog::ErrorDialog,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod imp {
|
mod imp {
|
||||||
|
|
@ -34,6 +35,9 @@ mod imp {
|
||||||
#[properties(wrapper_type = super::SearchPage)]
|
#[properties(wrapper_type = super::SearchPage)]
|
||||||
#[template(file = "data/ui/search_page.blp")]
|
#[template(file = "data/ui/search_page.blp")]
|
||||||
pub struct SearchPage {
|
pub struct SearchPage {
|
||||||
|
#[property(get, construct_only)]
|
||||||
|
pub toast_overlay: OnceCell<adw::ToastOverlay>,
|
||||||
|
|
||||||
#[property(get, construct_only)]
|
#[property(get, construct_only)]
|
||||||
pub navigation: OnceCell<adw::NavigationView>,
|
pub navigation: OnceCell<adw::NavigationView>,
|
||||||
|
|
||||||
|
|
@ -162,12 +166,14 @@ glib::wrapper! {
|
||||||
#[gtk::template_callbacks]
|
#[gtk::template_callbacks]
|
||||||
impl SearchPage {
|
impl SearchPage {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
toast_overlay: &adw::ToastOverlay,
|
||||||
navigation: &adw::NavigationView,
|
navigation: &adw::NavigationView,
|
||||||
library: &Library,
|
library: &Library,
|
||||||
player: &Player,
|
player: &Player,
|
||||||
query: LibraryQuery,
|
query: LibraryQuery,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let obj: Self = glib::Object::builder()
|
let obj: Self = glib::Object::builder()
|
||||||
|
.property("toast-overlay", toast_overlay)
|
||||||
.property("navigation", navigation)
|
.property("navigation", navigation)
|
||||||
.property("library", library)
|
.property("library", library)
|
||||||
.property("player", player)
|
.property("player", player)
|
||||||
|
|
@ -230,24 +236,82 @@ impl SearchPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(&self) {
|
fn delete(&self) {
|
||||||
log::warn!("Deletion not implemented");
|
if let Some(highlight) = &*self.imp().highlight.borrow() {
|
||||||
|
match highlight {
|
||||||
|
Tag::Composer(person) | Tag::Performer(person) => {
|
||||||
|
if let Err(err) = self.library().delete_person(&person.person_id) {
|
||||||
|
let toast = adw::Toast::builder()
|
||||||
|
.title(&gettext("Failed to delete person"))
|
||||||
|
.button_label("Details")
|
||||||
|
.build();
|
||||||
|
|
||||||
// if let Some(highlight) = &*self.imp().highlight.borrow() {
|
toast.connect_button_clicked(clone!(
|
||||||
// match highlight {
|
#[weak(rename_to = obj)]
|
||||||
// Tag::Composer(person) | Tag::Performer(person) => {
|
self,
|
||||||
// // TODO
|
move |_| {
|
||||||
// }
|
ErrorDialog::present(&err, &obj);
|
||||||
// Tag::Ensemble(ensemble) => {
|
}
|
||||||
// // TODO
|
));
|
||||||
// }
|
|
||||||
// Tag::Instrument(instrument) => {
|
self.toast_overlay().add_toast(toast);
|
||||||
// // TODO
|
}
|
||||||
// }
|
}
|
||||||
// Tag::Work(work) => {
|
Tag::Ensemble(ensemble) => {
|
||||||
// // TODO
|
if let Err(err) = self.library().delete_ensemble(&ensemble.ensemble_id) {
|
||||||
// }
|
let toast = adw::Toast::builder()
|
||||||
// }
|
.title(&gettext("Failed to delete ensemble"))
|
||||||
// }
|
.button_label("Details")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
toast.connect_button_clicked(clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
|
ErrorDialog::present(&err, &obj);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
self.toast_overlay().add_toast(toast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::Instrument(instrument) => {
|
||||||
|
if let Err(err) = self.library().delete_instrument(&instrument.instrument_id) {
|
||||||
|
let toast = adw::Toast::builder()
|
||||||
|
.title(&gettext("Failed to delete instrument"))
|
||||||
|
.button_label("Details")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
toast.connect_button_clicked(clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
|
ErrorDialog::present(&err, &obj);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
self.toast_overlay().add_toast(toast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag::Work(work) => {
|
||||||
|
if let Err(err) = self.library().delete_work(&work.work_id) {
|
||||||
|
let toast = adw::Toast::builder()
|
||||||
|
.title(&gettext("Failed to delete work"))
|
||||||
|
.button_label("Details")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
toast.connect_button_clicked(clone!(
|
||||||
|
#[weak(rename_to = obj)]
|
||||||
|
self,
|
||||||
|
move |_| {
|
||||||
|
ErrorDialog::present(&err, &obj);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
self.toast_overlay().add_toast(toast);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
|
|
@ -297,6 +361,7 @@ impl SearchPage {
|
||||||
|
|
||||||
if query_changed {
|
if query_changed {
|
||||||
self.navigation().push(&SearchPage::new(
|
self.navigation().push(&SearchPage::new(
|
||||||
|
&self.toast_overlay(),
|
||||||
&self.navigation(),
|
&self.navigation(),
|
||||||
&self.library(),
|
&self.library(),
|
||||||
&self.player(),
|
&self.player(),
|
||||||
|
|
@ -325,6 +390,7 @@ impl SearchPage {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.navigation().push(&SearchPage::new(
|
self.navigation().push(&SearchPage::new(
|
||||||
|
&self.toast_overlay(),
|
||||||
&self.navigation(),
|
&self.navigation(),
|
||||||
&self.library(),
|
&self.library(),
|
||||||
&self.player(),
|
&self.player(),
|
||||||
|
|
@ -347,6 +413,7 @@ impl SearchPage {
|
||||||
|
|
||||||
fn show_album(&self, album: &Album) {
|
fn show_album(&self, album: &Album) {
|
||||||
self.navigation().push(&AlbumPage::new(
|
self.navigation().push(&AlbumPage::new(
|
||||||
|
&self.toast_overlay(),
|
||||||
&self.navigation(),
|
&self.navigation(),
|
||||||
&self.library(),
|
&self.library(),
|
||||||
&self.player(),
|
&self.player(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod activatable_row;
|
pub mod activatable_row;
|
||||||
pub mod drag_widget;
|
pub mod drag_widget;
|
||||||
|
pub mod error_dialog;
|
||||||
|
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
|
||||||
79
src/util/error_dialog.rs
Normal file
79
src/util/error_dialog.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
use std::cell::OnceCell;
|
||||||
|
|
||||||
|
use adw::{prelude::*, subclass::prelude::*};
|
||||||
|
use gettextrs::gettext;
|
||||||
|
use gtk::{
|
||||||
|
gdk,
|
||||||
|
glib::{self, Properties},
|
||||||
|
};
|
||||||
|
|
||||||
|
mod imp {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
|
||||||
|
#[properties(wrapper_type = super::ErrorDialog)]
|
||||||
|
#[template(file = "data/ui/error_dialog.blp")]
|
||||||
|
pub struct ErrorDialog {
|
||||||
|
#[property(get, construct_only)]
|
||||||
|
pub error_text: OnceCell<String>,
|
||||||
|
|
||||||
|
#[template_child]
|
||||||
|
pub toast_overlay: TemplateChild<adw::ToastOverlay>,
|
||||||
|
|
||||||
|
#[template_child]
|
||||||
|
pub error_label: TemplateChild<gtk::Label>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for ErrorDialog {
|
||||||
|
const NAME: &'static str = "MusicusErrorDialog";
|
||||||
|
type Type = super::ErrorDialog;
|
||||||
|
type ParentType = adw::Dialog;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
klass.bind_template();
|
||||||
|
klass.bind_template_instance_callbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for ErrorDialog {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
self.error_label.set_label(&self.obj().error_text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for ErrorDialog {}
|
||||||
|
impl AdwDialogImpl for ErrorDialog {}
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct ErrorDialog(ObjectSubclass<imp::ErrorDialog>)
|
||||||
|
@extends gtk::Widget, adw::Dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[gtk::template_callbacks]
|
||||||
|
impl ErrorDialog {
|
||||||
|
pub fn present(err: &anyhow::Error, parent: &impl IsA<gtk::Widget>) {
|
||||||
|
let obj: Self = glib::Object::builder()
|
||||||
|
.property("error-text", &format!("{err:?}"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
obj.present(Some(parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[template_callback]
|
||||||
|
fn copy(&self) {
|
||||||
|
if let Some(display) = gdk::Display::default() {
|
||||||
|
display.clipboard().set_text(&self.error_text());
|
||||||
|
self.imp()
|
||||||
|
.toast_overlay
|
||||||
|
.add_toast(adw::Toast::new(&gettext("Copied to clipboard")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,8 @@ mod imp {
|
||||||
pub player: Player,
|
pub player: Player,
|
||||||
pub process_manager: ProcessManager,
|
pub process_manager: ProcessManager,
|
||||||
|
|
||||||
|
#[template_child]
|
||||||
|
pub toast_overlay: TemplateChild<adw::ToastOverlay>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub stack: TemplateChild<gtk::Stack>,
|
pub stack: TemplateChild<gtk::Stack>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
|
|
@ -242,6 +244,7 @@ impl Window {
|
||||||
fn reset_view(&self) {
|
fn reset_view(&self) {
|
||||||
let navigation = self.imp().navigation_view.get();
|
let navigation = self.imp().navigation_view.get();
|
||||||
navigation.replace(&[SearchPage::new(
|
navigation.replace(&[SearchPage::new(
|
||||||
|
&self.imp().toast_overlay,
|
||||||
&navigation,
|
&navigation,
|
||||||
self.imp().library.borrow().as_ref().unwrap(),
|
self.imp().library.borrow().as_ref().unwrap(),
|
||||||
&self.imp().player,
|
&self.imp().player,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue