From 41c2a9c1fcafc11c6a231742e86dec1fbc910305 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Fri, 9 May 2025 13:25:14 +0200 Subject: [PATCH 01/10] Use LazyLock instead of lazy_static --- Cargo.lock | 1 - Cargo.toml | 1 - src/util.rs | 27 +++++++++++++-------------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b78e6d8..2c4e493 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1880,7 +1880,6 @@ dependencies = [ "glib", "gstreamer-play", "gtk4", - "lazy_static", "libadwaita", "log", "mpris-server", diff --git a/Cargo.toml b/Cargo.toml index 4f0b267..ac6b612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ gettext-rs = { version = "0.7", features = ["gettext-system"] } glib = { version = "0.20", features = ["v2_84"] } gstreamer-play = "0.23" gtk = { package = "gtk4", version = "0.9", features = ["v4_18", "blueprint"] } -lazy_static = "1" log = "0.4" mpris-server = "0.8" once_cell = "1" diff --git a/src/util.rs b/src/util.rs index 6358704..ecf9f07 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,27 +2,26 @@ pub mod activatable_row; pub mod drag_widget; pub mod error_dialog; +use std::sync::LazyLock; + use gettextrs::gettext; use gtk::glib::{self, clone}; -use lazy_static::lazy_static; use error_dialog::ErrorDialog; -lazy_static! { - /// The user's language code. - pub static ref LANG: String = { - let lang = match glib::language_names().first() { - Some(language_name) => match language_name.split('_').next() { - Some(lang) => lang.to_string(), - None => "generic".to_string(), - }, +/// The user's language code. +pub static LANG: LazyLock = LazyLock::new(|| { + let lang = match glib::language_names().first() { + Some(language_name) => match language_name.split('_').next() { + Some(lang) => lang.to_string(), None => "generic".to_string(), - }; - - log::info!("Intialized user language to '{lang}'."); - lang + }, + None => "generic".to_string(), }; -} + + log::info!("Intialized user language to '{lang}'."); + lang +}); /// Create and show an error toast. This will also log the error to the console. pub fn error_toast(msgid: &str, err: anyhow::Error, toast_overlay: &adw::ToastOverlay) { From 8903ce7d2c88ddfa08bc1d3491650c00d537387b Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Tue, 13 May 2025 09:29:52 +0200 Subject: [PATCH 02/10] flatpak: Remove bluprint-compiler from devel It is now included in the GNOME SDK. --- flatpak/de.johrpan.Musicus.Devel.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/flatpak/de.johrpan.Musicus.Devel.json b/flatpak/de.johrpan.Musicus.Devel.json index 07cabd6..8e77a87 100644 --- a/flatpak/de.johrpan.Musicus.Devel.json +++ b/flatpak/de.johrpan.Musicus.Devel.json @@ -31,17 +31,6 @@ } }, "modules": [ - { - "name": "blueprint-compiler", - "buildsystem": "meson", - "sources": [ - { - "type": "git", - "url": "https://gitlab.gnome.org/jwestman/blueprint-compiler.git", - "tag": "v0.16.0" - } - ] - }, { "name": "musicus", "buildsystem": "meson", From 5917b0ac368abaf10e6be94a266482e390673411 Mon Sep 17 00:00:00 2001 From: lo <115636509+lo2dev@users.noreply.github.com> Date: Fri, 16 May 2025 10:19:50 +0300 Subject: [PATCH 03/10] Make search entry rounded --- data/res/style.css | 8 ++++++++ data/ui/search_page.blp | 14 ++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/data/res/style.css b/data/res/style.css index 316dcd4..b3ebbf3 100644 --- a/data/res/style.css +++ b/data/res/style.css @@ -6,6 +6,14 @@ font-size: smaller; } +.rounded-entry { + border-radius: 999px; + padding-left: 12px; + padding-right: 12px; + padding-top: 3px; + padding-bottom: 3px; +} + .searchbar .searchtag { background-color: alpha(currentColor, 0.1); border-radius: 100px; diff --git a/data/ui/search_page.blp b/data/ui/search_page.blp index 9c42770..01d7b0d 100644 --- a/data/ui/search_page.blp +++ b/data/ui/search_page.blp @@ -74,10 +74,16 @@ template $MusicusSearchPage: Adw.NavigationPage { } } - Gtk.SearchEntry search_entry { - placeholder-text: _("Enter composers, performers, works…"); - margin-top: 24; - activate => $select() swapped; + Adw.Clamp { + Gtk.SearchEntry search_entry { + placeholder-text: _("Enter composers, performers, works…"); + margin-top: 24; + activate => $select() swapped; + + styles [ + "rounded-entry" + ] + } } Gtk.Stack stack { From 1252ca0a1b261a9b3182cdfbcad97ad6ad45256c Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Fri, 30 May 2025 15:31:25 +0200 Subject: [PATCH 04/10] window: Inhibit system suspend during playback --- po/de.po | 16 ++++++++++------ po/template.pot | 16 ++++++++++------ src/window.rs | 25 ++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/po/de.po b/po/de.po index 57c58a9..f95d221 100644 --- a/po/de.po +++ b/po/de.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-27 17:54+0200\n" +"POT-Creation-Date: 2025-05-30 15:27+0200\n" "PO-Revision-Date: 2025-04-27 18:23+0200\n" "Last-Translator: elias@johrpan.de\n" "Language-Team: German \n" @@ -818,7 +818,7 @@ msgstr "Bibliothek exportieren" msgid "Exporting music library to {}" msgstr "Bibliothek wird nach {} exportiert" -#: src/library_manager.rs:234 src/window.rs:282 +#: src/library_manager.rs:234 src/window.rs:305 msgid "Updating metadata" msgstr "Metadaten werden aktualisiert" @@ -826,19 +826,23 @@ msgstr "Metadaten werden aktualisiert" msgid "Updating music library" msgstr "Musikbibliothek wird aktualisiert" -#: src/window.rs:167 +#: src/window.rs:166 +msgid "Currently playing music" +msgstr "Musik wird abgespielt" + +#: src/window.rs:190 msgid "Close window?" msgstr "Fenster schließen?" -#: src/window.rs:169 +#: src/window.rs:192 msgid "There are ongoing processes that will be canceled." msgstr "Es gibt laufende Prozesse, die abgebrochen werden." -#: src/window.rs:174 +#: src/window.rs:197 msgid "Keep open" msgstr "Nicht schließen" -#: src/window.rs:175 +#: src/window.rs:198 msgid "Close window" msgstr "Fenster schließen" diff --git a/po/template.pot b/po/template.pot index 03c8554..e47fe6b 100644 --- a/po/template.pot +++ b/po/template.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-27 17:54+0200\n" +"POT-Creation-Date: 2025-05-30 15:27+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -784,7 +784,7 @@ msgstr "" msgid "Exporting music library to {}" msgstr "" -#: src/library_manager.rs:234 src/window.rs:282 +#: src/library_manager.rs:234 src/window.rs:305 msgid "Updating metadata" msgstr "" @@ -792,18 +792,22 @@ msgstr "" msgid "Updating music library" msgstr "" -#: src/window.rs:167 +#: src/window.rs:166 +msgid "Currently playing music" +msgstr "" + +#: src/window.rs:190 msgid "Close window?" msgstr "" -#: src/window.rs:169 +#: src/window.rs:192 msgid "There are ongoing processes that will be canceled." msgstr "" -#: src/window.rs:174 +#: src/window.rs:197 msgid "Keep open" msgstr "" -#: src/window.rs:175 +#: src/window.rs:198 msgid "Close window" msgstr "" diff --git a/src/window.rs b/src/window.rs index ce2f4ab..b263423 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,4 +1,7 @@ -use std::{cell::RefCell, path::Path}; +use std::{ + cell::{Cell, RefCell}, + path::Path, +}; use adw::{prelude::*, subclass::prelude::*}; use anyhow::{anyhow, Result}; @@ -31,6 +34,7 @@ mod imp { pub library: RefCell>, pub player: Player, pub process_manager: ProcessManager, + pub inhibitor_cookie: Cell>, #[template_child] pub toast_overlay: TemplateChild, @@ -148,6 +152,25 @@ mod imp { let obj = self.obj().to_owned(); self.player.connect_raise(move |_| obj.present()); + let obj = self.obj().to_owned(); + self.player.connect_playing_notify(move |player| { + if let Some(app) = obj.application() { + if let Some(cookie) = obj.imp().inhibitor_cookie.take() { + app.uninhibit(cookie); + }; + + if player.playing() { + let cookie = app.inhibit( + Some(&obj), + gtk::ApplicationInhibitFlags::SUSPEND, + Some(&gettext("Currently playing music")), + ); + + obj.imp().inhibitor_cookie.set(Some(cookie)); + } + } + }); + let settings = gio::Settings::new(config::APP_ID); let library_path = settings.string("library-path").to_string(); if !library_path.is_empty() { From 3c65905a3739d4c3c4874748fa3e71ae7eb2e4fb Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sat, 9 Aug 2025 10:43:53 +0200 Subject: [PATCH 05/10] flatpak: Use LLVM 20 --- flatpak/de.johrpan.Musicus.Devel.json | 4 ++-- flatpak/de.johrpan.Musicus.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flatpak/de.johrpan.Musicus.Devel.json b/flatpak/de.johrpan.Musicus.Devel.json index 8e77a87..09a2fd1 100644 --- a/flatpak/de.johrpan.Musicus.Devel.json +++ b/flatpak/de.johrpan.Musicus.Devel.json @@ -5,7 +5,7 @@ "sdk": "org.gnome.Sdk", "sdk-extensions": [ "org.freedesktop.Sdk.Extension.rust-stable", - "org.freedesktop.Sdk.Extension.llvm18" + "org.freedesktop.Sdk.Extension.llvm20" ], "command": "musicus", "finish-args": [ @@ -20,7 +20,7 @@ "--env=G_MESSAGES_DEBUG=none" ], "build-options": { - "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin", + "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm20/bin", "build-args": [ "--share=network" ], diff --git a/flatpak/de.johrpan.Musicus.json b/flatpak/de.johrpan.Musicus.json index 3ddfaaa..7b12404 100644 --- a/flatpak/de.johrpan.Musicus.json +++ b/flatpak/de.johrpan.Musicus.json @@ -5,7 +5,7 @@ "sdk": "org.gnome.Sdk", "sdk-extensions": [ "org.freedesktop.Sdk.Extension.rust-stable", - "org.freedesktop.Sdk.Extension.llvm18" + "org.freedesktop.Sdk.Extension.llvm20" ], "command": "musicus", "finish-args": [ @@ -20,7 +20,7 @@ "--env=G_MESSAGES_DEBUG=none" ], "build-options": { - "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin", + "append-path": "/usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm20/bin", "build-args": [ "--share=network" ], From 48cfdd354aeccf8ab14a2349345c9c2cfaa740c7 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sat, 9 Aug 2025 11:00:08 +0200 Subject: [PATCH 06/10] search page: Remove additional clamp for search entry --- data/ui/search_page.blp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/data/ui/search_page.blp b/data/ui/search_page.blp index 01d7b0d..24daf4d 100644 --- a/data/ui/search_page.blp +++ b/data/ui/search_page.blp @@ -73,17 +73,15 @@ template $MusicusSearchPage: Adw.NavigationPage { ] } } + + Gtk.SearchEntry search_entry { + placeholder-text: _("Enter composers, performers, works…"); + margin-top: 24; + activate => $select() swapped; - Adw.Clamp { - Gtk.SearchEntry search_entry { - placeholder-text: _("Enter composers, performers, works…"); - margin-top: 24; - activate => $select() swapped; - - styles [ - "rounded-entry" - ] - } + styles [ + "rounded-entry" + ] } Gtk.Stack stack { From c50ef90e9b39acd465917fe2f8481ee872c75e61 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sun, 10 Aug 2025 11:56:28 +0200 Subject: [PATCH 07/10] Remove AlbumPage from stack on library changes --- src/window.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/window.rs b/src/window.rs index b263423..14ef619 100644 --- a/src/window.rs +++ b/src/window.rs @@ -9,6 +9,7 @@ use gettextrs::gettext; use gtk::{gio, glib, glib::clone}; use crate::{ + album_page::AlbumPage, config, editor::tracks::TracksEditor, empty_page::EmptyPage, @@ -362,17 +363,12 @@ impl Window { fn reset_view(&self) { let navigation = self.imp().navigation_view.get(); - // Get all pages that are not instances of SearchPage. + // Get all pages that are not instances of SearchPage or AlbumPage. let mut navigation_stack = navigation .navigation_stack() .iter::() - .filter_map(|page| match page { - Ok(page) => match page.downcast_ref::() { - Some(_) => None, - None => Some(page), - }, - Err(_) => None, - }) + .filter_map(|page| page.ok()) + .filter(|page| !page.is::() && !page.is::()) .collect::>(); navigation_stack.insert( From 45338c1bf957ab71bea3e52d7280b2b7b798fa7a Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sun, 10 Aug 2025 11:57:18 +0200 Subject: [PATCH 08/10] Expose AlbumEditor in primary menu --- data/ui/empty_page.blp | 39 +++++++++++++++++++++++-------------- data/ui/search_page.blp | 43 +++++++++++++++++++++++++---------------- src/window.rs | 20 ++++++++++++++++--- 3 files changed, 67 insertions(+), 35 deletions(-) diff --git a/data/ui/empty_page.blp b/data/ui/empty_page.blp index bee614a..1be754d 100644 --- a/data/ui/empty_page.blp +++ b/data/ui/empty_page.blp @@ -50,23 +50,32 @@ template $MusicusEmptyPage: Adw.NavigationPage { } menu primary_menu { - item { - label: _("_Import music"); - action: "win.import"; + section { + item { + label: _("_Import music"); + action: "win.import"; + } + + item { + label: _("_Create album"); + action: "win.create-album"; + } + + item { + label: _("_Library manager"); + action: "win.library"; + } } - item { - label: _("_Library manager"); - action: "win.library"; - } + section { + item { + label: _("_Preferences"); + action: "win.preferences"; + } - item { - label: _("_Preferences"); - action: "win.preferences"; - } - - item { - label: _("_About Musicus"); - action: "app.about"; + item { + label: _("_About Musicus"); + action: "app.about"; + } } } diff --git a/data/ui/search_page.blp b/data/ui/search_page.blp index 24daf4d..1cae41a 100644 --- a/data/ui/search_page.blp +++ b/data/ui/search_page.blp @@ -73,14 +73,14 @@ template $MusicusSearchPage: Adw.NavigationPage { ] } } - + Gtk.SearchEntry search_entry { placeholder-text: _("Enter composers, performers, works…"); margin-top: 24; activate => $select() swapped; styles [ - "rounded-entry" + "rounded-entry", ] } @@ -264,24 +264,33 @@ template $MusicusSearchPage: Adw.NavigationPage { } menu primary_menu { - item { - label: _("_Import music"); - action: "win.import"; + section { + item { + label: _("_Import music"); + action: "win.import"; + } + + item { + label: _("_Create album"); + action: "win.create-album"; + } + + item { + label: _("_Library manager"); + action: "win.library"; + } } - item { - label: _("_Library manager"); - action: "win.library"; - } + section { + item { + label: _("_Preferences"); + action: "win.preferences"; + } - item { - label: _("_Preferences"); - action: "win.preferences"; - } - - item { - label: _("_About Musicus"); - action: "app.about"; + item { + label: _("_About Musicus"); + action: "app.about"; + } } } diff --git a/src/window.rs b/src/window.rs index 14ef619..5a5cc61 100644 --- a/src/window.rs +++ b/src/window.rs @@ -11,7 +11,7 @@ use gtk::{gio, glib, glib::clone}; use crate::{ album_page::AlbumPage, config, - editor::tracks::TracksEditor, + editor::{album::AlbumEditor, tracks::TracksEditor}, empty_page::EmptyPage, library::{Library, LibraryQuery}, library_manager::LibraryManager, @@ -88,6 +88,16 @@ mod imp { }) .build(); + let obj = self.obj().to_owned(); + let create_album_action = gio::ActionEntry::builder("create-album") + .activate(move |_, _, _| { + if let Some(library) = &*obj.imp().library.borrow() { + let editor = AlbumEditor::new(&obj.imp().navigation_view, library, None); + obj.imp().navigation_view.push(&editor); + } + }) + .build(); + let obj = self.obj().to_owned(); let library_action = gio::ActionEntry::builder("library") .activate(move |_, _, _| { @@ -109,8 +119,12 @@ mod imp { }) .build(); - self.obj() - .add_action_entries([import_action, library_action, preferences_action]); + self.obj().add_action_entries([ + import_action, + create_album_action, + library_action, + preferences_action, + ]); let player_bar = PlayerBar::new(&self.player); self.player_bar_revealer.set_child(Some(&player_bar)); From 66af523d5a3d698a46331633fe4b283bd9a85511 Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sun, 10 Aug 2025 12:13:00 +0200 Subject: [PATCH 09/10] Remove unused SearchTag --- data/res/style.css | 11 ----- data/ui/search_tag.blp | 22 --------- src/library/exchange.rs | 10 ++++- src/library_manager.rs | 16 ++++++- src/main.rs | 1 - src/search_page.rs | 3 +- src/search_tag.rs | 98 ----------------------------------------- src/tag_tile.rs | 11 ++++- 8 files changed, 33 insertions(+), 139 deletions(-) delete mode 100644 data/ui/search_tag.blp delete mode 100644 src/search_tag.rs diff --git a/data/res/style.css b/data/res/style.css index b3ebbf3..4e55c11 100644 --- a/data/res/style.css +++ b/data/res/style.css @@ -14,17 +14,6 @@ padding-bottom: 3px; } -.searchbar .searchtag { - background-color: alpha(currentColor, 0.1); - border-radius: 100px; -} - -.searchbar .searchtag>button { - min-width: 24px; - min-height: 24px; - margin: 0px; -} - .tile { min-height: 50px; min-width: 200px; diff --git a/data/ui/search_tag.blp b/data/ui/search_tag.blp deleted file mode 100644 index be66cf5..0000000 --- a/data/ui/search_tag.blp +++ /dev/null @@ -1,22 +0,0 @@ -using Gtk 4.0; - -template $MusicusSearchTag : Gtk.Box { - styles ["searchtag"] - - margin-start: 6; - margin-end: 6; - - Gtk.Label label { - styles ["caption-heading"] - margin-start: 12; - margin-end: 6; - max-width-chars: 15; - ellipsize: end; - } - - Gtk.Button button { - styles ["flat", "circular"] - icon-name: "window-close-symbolic"; - clicked => $remove() swapped; - } -} \ No newline at end of file diff --git a/src/library/exchange.rs b/src/library/exchange.rs index 5e512ae..3560d9f 100644 --- a/src/library/exchange.rs +++ b/src/library/exchange.rs @@ -29,7 +29,10 @@ impl Library { &self, path: impl AsRef, ) -> Result> { - log::info!("Importing library from ZIP at {}", path.as_ref().to_string_lossy()); + log::info!( + "Importing library from ZIP at {}", + path.as_ref().to_string_lossy() + ); let path = path.as_ref().to_owned(); let library_folder = PathBuf::from(&self.folder()); let this_connection = self.imp().connection.get().unwrap().clone(); @@ -52,7 +55,10 @@ impl Library { &self, path: impl AsRef, ) -> Result> { - log::info!("Exporting library to ZIP at {}", path.as_ref().to_string_lossy()); + log::info!( + "Exporting library to ZIP at {}", + path.as_ref().to_string_lossy() + ); let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap(); let path = path.as_ref().to_owned(); diff --git a/src/library_manager.rs b/src/library_manager.rs index 5c494f3..5d1d987 100644 --- a/src/library_manager.rs +++ b/src/library_manager.rs @@ -128,7 +128,13 @@ impl LibraryManager { } Ok(path) => { if let Some(path) = path.path() { - match self.imp().library.get().unwrap().import_library_from_zip(&path) { + match self + .imp() + .library + .get() + .unwrap() + .import_library_from_zip(&path) + { Ok(receiver) => { let process = Process::new( &formatx!( @@ -186,7 +192,13 @@ impl LibraryManager { } Ok(path) => { if let Some(path) = path.path() { - match self.imp().library.get().unwrap().export_library_to_zip(&path) { + match self + .imp() + .library + .get() + .unwrap() + .export_library_to_zip(&path) + { Ok(receiver) => { let process = Process::new( &formatx!( diff --git a/src/main.rs b/src/main.rs index 35e5a4c..14115fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,6 @@ mod program; mod program_tile; mod recording_tile; mod search_page; -mod search_tag; mod selector; mod slider_row; mod tag_tile; diff --git a/src/search_page.rs b/src/search_page.rs index b9c6ff7..ce7983b 100644 --- a/src/search_page.rs +++ b/src/search_page.rs @@ -22,8 +22,7 @@ use crate::{ program::Program, program_tile::ProgramTile, recording_tile::RecordingTile, - search_tag::Tag, - tag_tile::TagTile, + tag_tile::{Tag, TagTile}, util, }; diff --git a/src/search_tag.rs b/src/search_tag.rs deleted file mode 100644 index e2cdb8b..0000000 --- a/src/search_tag.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::cell::OnceCell; - -use adw::{glib, glib::subclass::Signal, prelude::*, subclass::prelude::*}; -use once_cell::sync::Lazy; - -use crate::db::models::{Ensemble, Instrument, Person, Work}; - -mod imp { - use super::*; - - #[derive(Debug, Default, gtk::CompositeTemplate)] - #[template(file = "data/ui/search_tag.blp")] - pub struct SearchTag { - #[template_child] - pub label: TemplateChild, - pub tag: OnceCell, - } - - #[glib::object_subclass] - impl ObjectSubclass for SearchTag { - const NAME: &'static str = "MusicusSearchTag"; - type Type = super::SearchTag; - type ParentType = gtk::Box; - - fn class_init(klass: &mut Self::Class) { - klass.bind_template(); - klass.bind_template_instance_callbacks(); - } - - fn instance_init(obj: &glib::subclass::InitializingObject) { - obj.init_template(); - } - } - - impl ObjectImpl for SearchTag { - fn signals() -> &'static [Signal] { - static SIGNALS: Lazy> = - Lazy::new(|| vec![Signal::builder("remove").build()]); - - SIGNALS.as_ref() - } - } - - impl WidgetImpl for SearchTag {} - impl BoxImpl for SearchTag {} -} - -glib::wrapper! { - pub struct SearchTag(ObjectSubclass) - @extends gtk::Widget; -} - -#[gtk::template_callbacks] -impl SearchTag { - pub fn new(tag: Tag) -> Self { - let obj: SearchTag = glib::Object::new(); - - let label = match &tag { - Tag::Composer(person) => person.name.get(), - Tag::Performer(person) => person.name.get(), - Tag::Ensemble(ensemble) => ensemble.name.get(), - Tag::Instrument(instrument) => instrument.name.get(), - Tag::Work(work) => work.name.get(), - }; - - obj.imp().label.set_label(label); - obj.set_tooltip_text(Some(label)); - obj.imp().tag.set(tag).unwrap(); - - obj - } - - pub fn connect_remove(&self, f: F) -> glib::SignalHandlerId { - self.connect_local("remove", true, move |values| { - let obj = values[0].get::().unwrap(); - f(&obj); - None - }) - } - - pub fn tag(&self) -> &Tag { - self.imp().tag.get().unwrap() - } - - #[template_callback] - fn remove(&self) { - self.emit_by_name::<()>("remove", &[]); - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum Tag { - Composer(Person), - Performer(Person), - Ensemble(Ensemble), - Instrument(Instrument), - Work(Work), -} diff --git a/src/tag_tile.rs b/src/tag_tile.rs index 2f2f642..7b92ea5 100644 --- a/src/tag_tile.rs +++ b/src/tag_tile.rs @@ -2,7 +2,7 @@ use std::cell::OnceCell; use gtk::{glib, prelude::*, subclass::prelude::*}; -use crate::search_tag::Tag; +use crate::db::models::{Ensemble, Instrument, Person, Work}; mod imp { use super::*; @@ -78,3 +78,12 @@ impl TagTile { self.imp().tag.get().unwrap() } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Tag { + Composer(Person), + Performer(Person), + Ensemble(Ensemble), + Instrument(Instrument), + Work(Work), +} From 8d9690dad65e554e772fb63a8e821afffca0c06f Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Sun, 10 Aug 2025 12:37:33 +0200 Subject: [PATCH 10/10] Implement some Clippy suggestions --- src/album_page.rs | 6 ++---- src/album_tile.rs | 2 +- src/editor/program.rs | 2 +- src/editor/recording.rs | 2 +- src/editor/tracks.rs | 3 +-- src/editor/work.rs | 18 ++++++++---------- src/editor/work/part_row.rs | 2 +- src/empty_page.rs | 4 ++-- src/library/edit.rs | 14 ++++++-------- src/library/exchange.rs | 20 ++++++++------------ src/library/query.rs | 1 - src/main.rs | 2 +- src/player.rs | 18 +++++++++--------- src/program.rs | 2 +- src/program_tile.rs | 2 +- src/recording_tile.rs | 8 ++++---- src/search_page.rs | 8 ++++---- src/selector/recording.rs | 2 +- src/selector/work.rs | 2 +- src/util.rs | 2 +- src/util/error_dialog.rs | 2 +- src/window.rs | 4 ++-- 22 files changed, 57 insertions(+), 69 deletions(-) diff --git a/src/album_page.rs b/src/album_page.rs index dfab603..2eb51e3 100644 --- a/src/album_page.rs +++ b/src/album_page.rs @@ -72,8 +72,7 @@ mod imp { .unwrap() .recordings .iter() - .map(|r| obj.player().recording_to_playlist(r)) - .flatten() + .flat_map(|r| obj.player().recording_to_playlist(r)) .collect::>(); if let Err(err) = obj.player().append(playlist) { @@ -165,8 +164,7 @@ impl AlbumPage { .unwrap() .recordings .iter() - .map(|r| self.player().recording_to_playlist(r)) - .flatten() + .flat_map(|r| self.player().recording_to_playlist(r)) .collect::>(); self.player().append_and_play(playlist); diff --git a/src/album_tile.rs b/src/album_tile.rs index 73667cb..464b98e 100644 --- a/src/album_tile.rs +++ b/src/album_tile.rs @@ -45,7 +45,7 @@ impl AlbumTile { pub fn new(album: &Album) -> Self { let obj: Self = glib::Object::new(); - obj.imp().title_label.set_label(&album.name.get()); + obj.imp().title_label.set_label(album.name.get()); obj.imp().album.set(album.clone()).unwrap(); obj diff --git a/src/editor/program.rs b/src/editor/program.rs index 708c7b0..1ae1cca 100644 --- a/src/editor/program.rs +++ b/src/editor/program.rs @@ -69,7 +69,7 @@ mod imp { self.parent_constructed(); let set_design_action = gio::ActionEntry::builder("set-design") - .parameter_type(Some(&glib::VariantTy::STRING)) + .parameter_type(Some(glib::VariantTy::STRING)) .state(glib::Variant::from("program-1")) .build(); diff --git a/src/editor/recording.rs b/src/editor/recording.rs index 4d60e66..a8029e7 100644 --- a/src/editor/recording.rs +++ b/src/editor/recording.rs @@ -246,7 +246,7 @@ impl RecordingEditor { } fn set_work(&self, work: Work) { - self.imp().work_row.set_title(&work.name.get()); + self.imp().work_row.set_title(work.name.get()); self.imp().work_row.set_subtitle( &work .composers_string() diff --git a/src/editor/tracks.rs b/src/editor/tracks.rs index 4c05e47..caf356c 100644 --- a/src/editor/tracks.rs +++ b/src/editor/tracks.rs @@ -245,8 +245,7 @@ impl TracksEditor { .track_rows .borrow() .iter() - .map(|t| t.track_data().parts.clone()) - .flatten() + .flat_map(|t| t.track_data().parts.clone()) .collect::>() }; diff --git a/src/editor/work.rs b/src/editor/work.rs index 18191c7..77f9d17 100644 --- a/src/editor/work.rs +++ b/src/editor/work.rs @@ -390,17 +390,15 @@ impl WorkEditor { }; self.emit_by_name::<()>("created", &[&part]); + } else if let Some(work_id) = self.imp().work_id.get() { + library + .update_work(work_id, name, parts, composers, instruments, enable_updates) + .unwrap(); } else { - if let Some(work_id) = self.imp().work_id.get() { - library - .update_work(work_id, name, parts, composers, instruments, enable_updates) - .unwrap(); - } else { - let work = library - .create_work(name, parts, composers, instruments, enable_updates) - .unwrap(); - self.emit_by_name::<()>("created", &[&work]); - } + let work = library + .create_work(name, parts, composers, instruments, enable_updates) + .unwrap(); + self.emit_by_name::<()>("created", &[&work]); } self.imp().navigation.get().unwrap().pop(); diff --git a/src/editor/work/part_row.rs b/src/editor/work/part_row.rs index b7d3e42..ca5ae1d 100644 --- a/src/editor/work/part_row.rs +++ b/src/editor/work/part_row.rs @@ -145,7 +145,7 @@ impl WorkEditorPartRow { } fn set_part(&self, part: Work) { - self.set_title(&part.name.get()); + self.set_title(part.name.get()); if !part.parts.is_empty() { self.set_subtitle( diff --git a/src/empty_page.rs b/src/empty_page.rs index 1cf2ffb..14acc04 100644 --- a/src/empty_page.rs +++ b/src/empty_page.rs @@ -92,8 +92,8 @@ impl EmptyPage { #[template_callback] async fn download_library(&self) { let dialog = adw::AlertDialog::builder() - .heading(&gettext("Disclaimer")) - .body(&gettext("You are about to download a library of audio files. These are from recordings that are in the public domain under EU law and are hosted on a server within the EU. Please ensure that you comply with the copyright laws of you country.")) + .heading(gettext("Disclaimer")) + .body(gettext("You are about to download a library of audio files. These are from recordings that are in the public domain under EU law and are hosted on a server within the EU. Please ensure that you comply with the copyright laws of you country.")) .build(); dialog.add_response("continue", &gettext("Continue")); diff --git a/src/library/edit.rs b/src/library/edit.rs index 1e71da9..b7d3134 100644 --- a/src/library/edit.rs +++ b/src/library/edit.rs @@ -209,7 +209,7 @@ impl Library { ) -> Result { let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap(); - let work = self.create_work_priv( + let work = Self::create_work_priv( connection, name, parts, @@ -226,7 +226,6 @@ impl Library { } fn create_work_priv( - &self, connection: &mut SqliteConnection, name: TranslatedString, parts: Vec, @@ -242,7 +241,7 @@ impl Library { let work_data = tables::Work { work_id: work_id.clone(), parent_work_id: parent_work_id.map(|w| w.to_string()), - sequence_number: sequence_number, + sequence_number, name, created_at: now, edited_at: now, @@ -256,7 +255,7 @@ impl Library { .execute(connection)?; for (index, part) in parts.into_iter().enumerate() { - self.create_work_priv( + Self::create_work_priv( connection, part.name, part.parts, @@ -309,7 +308,7 @@ impl Library { ) -> Result<()> { let connection = &mut *self.imp().connection.get().unwrap().lock().unwrap(); - self.update_work_priv( + Self::update_work_priv( connection, work_id, name, @@ -327,7 +326,6 @@ impl Library { } fn update_work_priv( - &self, connection: &mut SqliteConnection, work_id: &str, name: TranslatedString, @@ -367,7 +365,7 @@ impl Library { .optional()? .is_some() { - self.update_work_priv( + Self::update_work_priv( connection, &part.work_id, part.name, @@ -381,7 +379,7 @@ impl Library { } else { // Note: The previously used ID is discarded. This should be OK, because // at this point, the part ID should not have been used anywhere. - self.create_work_priv( + Self::create_work_priv( connection, part.name, part.parts, diff --git a/src/library/exchange.rs b/src/library/exchange.rs index 3560d9f..acec25e 100644 --- a/src/library/exchange.rs +++ b/src/library/exchange.rs @@ -229,22 +229,18 @@ fn import_metadata_from_url_priv( formatx!(gettext("Downloading {}"), &url).unwrap(), )); - match runtime.block_on(download_tmp_file(&url, &sender)) { + match runtime.block_on(download_tmp_file(&url, sender)) { Ok(db_file) => { let _ = sender.send_blocking(ProcessMsg::Message( formatx!(gettext("Importing downloaded library"), &url).unwrap(), )); let _ = sender.send_blocking(ProcessMsg::Result( - import_metadata_from_file(db_file.path(), this_connection, true).and_then( - |tracks| { - if !tracks.is_empty() { - log::warn!("The metadata file at {url} contains tracks."); - } - - Ok(()) - }, - ), + import_metadata_from_file(db_file.path(), this_connection, true).map(|tracks| { + if !tracks.is_empty() { + log::warn!("The metadata file at {url} contains tracks."); + } + }), )); } Err(err) => { @@ -269,7 +265,7 @@ fn import_library_from_url_priv( formatx!(gettext("Downloading {}"), &url).unwrap(), )); - let archive_file = runtime.block_on(download_tmp_file(&url, &sender)); + let archive_file = runtime.block_on(download_tmp_file(&url, sender)); match archive_file { Ok(archive_file) => { @@ -281,7 +277,7 @@ fn import_library_from_url_priv( archive_file.path(), library_folder, this_connection, - &sender, + sender, ))); } Err(err) => { diff --git a/src/library/query.rs b/src/library/query.rs index 43b685f..502d354 100644 --- a/src/library/query.rs +++ b/src/library/query.rs @@ -414,7 +414,6 @@ impl Library { works, recordings, albums, - ..Default::default() } } LibraryQuery { diff --git a/src/main.rs b/src/main.rs index 14115fe..2a9821e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,7 +46,7 @@ fn main() -> glib::ExitCode { gettextrs::textdomain(config::PKGNAME).unwrap(); gio::resources_register( - &gio::Resource::load(&format!( + &gio::Resource::load(format!( "{}/{}/{}.gresource", config::DATADIR, config::PKGNAME, diff --git a/src/player.rs b/src/player.rs index 8f75d9a..da1c1bc 100644 --- a/src/player.rs +++ b/src/player.rs @@ -221,14 +221,14 @@ impl Player { items.push(PlaylistItem::new( true, recording.work.composers_string(), - &recording.work.name.get(), + recording.work.name.get(), Some(&performances), None, - &self.library_path_to_file_path(&tracks[0].path), + self.library_path_to_file_path(&tracks[0].path), &tracks[0].track_id, )); } else { - let mut tracks = tracks.into_iter(); + let mut tracks = tracks.iter(); let first_track = tracks.next().unwrap(); let track_title = |track: &Track, number: usize| -> String { @@ -249,10 +249,10 @@ impl Player { items.push(PlaylistItem::new( true, recording.work.composers_string(), - &recording.work.name.get(), + recording.work.name.get(), Some(&performances), - Some(&track_title(&first_track, 1)), - &self.library_path_to_file_path(&first_track.path), + Some(&track_title(first_track, 1)), + self.library_path_to_file_path(&first_track.path), &first_track.track_id, )); @@ -260,11 +260,11 @@ impl Player { items.push(PlaylistItem::new( false, recording.work.composers_string(), - &recording.work.name.get(), + recording.work.name.get(), Some(&performances), // track number = track index + 1 (first track) + 1 (zero based) - Some(&track_title(&track, index + 2)), - &self.library_path_to_file_path(&track.path), + Some(&track_title(track, index + 2)), + self.library_path_to_file_path(&track.path), &track.track_id, )); } diff --git a/src/program.rs b/src/program.rs index 803dbe5..435cd38 100644 --- a/src/program.rs +++ b/src/program.rs @@ -83,7 +83,7 @@ impl Program { } pub fn from_query(query: LibraryQuery) -> Self { - let settings = gio::Settings::new(&config::APP_ID); + let settings = gio::Settings::new(config::APP_ID); glib::Object::builder() .property( diff --git a/src/program_tile.rs b/src/program_tile.rs index 78f5718..d776864 100644 --- a/src/program_tile.rs +++ b/src/program_tile.rs @@ -56,7 +56,7 @@ mod imp { self.set_program_from_settings(&settings); let obj = self.obj().to_owned(); - settings.connect_changed(Some(&self.key.get().unwrap()), move |settings, _| { + settings.connect_changed(Some(self.key.get().unwrap()), move |settings, _| { obj.imp().set_program_from_settings(settings); }); } diff --git a/src/recording_tile.rs b/src/recording_tile.rs index 8ff1373..f7afd6c 100644 --- a/src/recording_tile.rs +++ b/src/recording_tile.rs @@ -69,7 +69,7 @@ mod imp { .push(&RecordingEditor::new( obj.imp().navigation.get().unwrap(), obj.imp().library.get().unwrap(), - Some(&obj.imp().recording.get().unwrap()), + Some(obj.imp().recording.get().unwrap()), )); }) .build(); @@ -90,8 +90,8 @@ mod imp { let delete_action = gio::ActionEntry::builder("delete") .activate(move |_, _, _| { let dialog = adw::AlertDialog::builder() - .heading(&gettext("Delete recording?")) - .body(&gettext("The recording will be removed from your music library and the corresponding audio files will be deleted. This action cannot be undone.")) + .heading(gettext("Delete recording?")) + .body(gettext("The recording will be removed from your music library and the corresponding audio files will be deleted. This action cannot be undone.")) .build(); dialog.add_response("delete", &gettext("Delete")); @@ -142,7 +142,7 @@ impl RecordingTile { let obj: Self = glib::Object::new(); let imp = obj.imp(); - imp.work_label.set_label(&recording.work.name.get()); + imp.work_label.set_label(recording.work.name.get()); imp.composer_label.set_label( &recording .work diff --git a/src/search_page.rs b/src/search_page.rs index ce7983b..21dc00f 100644 --- a/src/search_page.rs +++ b/src/search_page.rs @@ -391,7 +391,7 @@ impl SearchPage { imp.header_box.set_visible(!query.is_empty()); let highlight = if let Some(work) = &query.work { - imp.title_label.set_text(&work.name.get()); + imp.title_label.set_text(work.name.get()); if let Some(composers) = work.composers_string() { imp.subtitle_label.set_text(&composers); imp.subtitle_label.set_visible(true); @@ -400,15 +400,15 @@ impl SearchPage { } Some(Tag::Work(work.to_owned())) } else if let Some(person) = &query.composer { - imp.title_label.set_text(&person.name.get()); + imp.title_label.set_text(person.name.get()); imp.subtitle_label.set_visible(false); Some(Tag::Composer(person.to_owned())) } else if let Some(person) = &query.performer { - imp.title_label.set_text(&person.name.get()); + imp.title_label.set_text(person.name.get()); imp.subtitle_label.set_visible(false); Some(Tag::Performer(person.to_owned())) } else if let Some(ensemble) = &query.ensemble { - imp.title_label.set_text(&ensemble.name.get()); + imp.title_label.set_text(ensemble.name.get()); imp.subtitle_label.set_visible(false); Some(Tag::Ensemble(ensemble.to_owned())) } else if let Some(instrument) = &query.instrument { diff --git a/src/selector/recording.rs b/src/selector/recording.rs index eb16c67..1a256d8 100644 --- a/src/selector/recording.rs +++ b/src/selector/recording.rs @@ -294,7 +294,7 @@ impl RecordingSelectorPopover { .build(), ); - row.set_tooltip_text(Some(&work.name.get())); + row.set_tooltip_text(Some(work.name.get())); let work = work.clone(); let obj = self.clone(); diff --git a/src/selector/work.rs b/src/selector/work.rs index 46e84f1..c636d3a 100644 --- a/src/selector/work.rs +++ b/src/selector/work.rs @@ -256,7 +256,7 @@ impl WorkSelectorPopover { .build(), ); - row.set_tooltip_text(Some(&work.name.get())); + row.set_tooltip_text(Some(work.name.get())); let work = work.clone(); let obj = self.clone(); diff --git a/src/util.rs b/src/util.rs index ecf9f07..f1c1322 100644 --- a/src/util.rs +++ b/src/util.rs @@ -28,7 +28,7 @@ pub fn error_toast(msgid: &str, err: anyhow::Error, toast_overlay: &adw::ToastOv log::error!("{msgid}: {err:?}"); let toast = adw::Toast::builder() - .title(&gettext(msgid)) + .title(gettext(msgid)) .button_label("Details") .build(); diff --git a/src/util/error_dialog.rs b/src/util/error_dialog.rs index 50d8977..280386d 100644 --- a/src/util/error_dialog.rs +++ b/src/util/error_dialog.rs @@ -61,7 +61,7 @@ glib::wrapper! { impl ErrorDialog { pub fn present(err: &anyhow::Error, parent: &impl IsA) { let obj: Self = glib::Object::builder() - .property("error-text", &format!("{err:?}")) + .property("error-text", format!("{err:?}")) .build(); obj.present(Some(parent)); diff --git a/src/window.rs b/src/window.rs index 5a5cc61..220e270 100644 --- a/src/window.rs +++ b/src/window.rs @@ -202,8 +202,8 @@ mod imp { fn close_request(&self) -> glib::signal::Propagation { if self.process_manager.any_ongoing() { let dialog = adw::AlertDialog::builder() - .heading(&gettext("Close window?")) - .body(&gettext( + .heading(gettext("Close window?")) + .body(gettext( "There are ongoing processes that will be canceled.", )) .build();