Update dependencies, adapt code, fix warnings

This commit is contained in:
Elias Projahn 2023-03-28 14:39:54 +02:00
parent 75d4e82cf8
commit 835d4f0d42
44 changed files with 595 additions and 541 deletions

677
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,10 @@ edition = "2021"
[dependencies] [dependencies]
chrono = "0.4" chrono = "0.4"
fragile = "2" fragile = "2"
gio = "0.16" gio = "0.17"
glib = "0.16" glib = "0.17"
gstreamer = "0.19" gstreamer = "0.20"
gstreamer-player = "0.19" gstreamer-player = "0.20"
log = { version = "0.4", features = ["std"] } log = { version = "0.4", features = ["std"] }
musicus_database = { version = "0.1.0", path = "../database" } musicus_database = { version = "0.1.0", path = "../database" }
musicus_import = { version = "0.1.0", path = "../import" } musicus_import = { version = "0.1.0", path = "../import" }

View file

@ -1,6 +1,9 @@
use chrono::{Local, DateTime}; use chrono::{DateTime, Local};
use log::{Level, LevelFilter, Log, Metadata, Record}; use log::{Level, LevelFilter, Log, Metadata, Record};
use std::{fmt::Display, sync::{Arc, Mutex}}; use std::{
fmt::Display,
sync::{Arc, Mutex},
};
/// Register the custom logger. This will panic if called more than once. /// Register the custom logger. This will panic if called more than once.
pub fn register() -> Arc<Logger> { pub fn register() -> Arc<Logger> {
@ -72,6 +75,10 @@ impl<'a> From<&Record<'a>> for LogMessage {
impl Display for LogMessage { impl Display for LogMessage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {} ({}): {}", self.time, self.module, self.level, self.message) write!(
f,
"{} {} ({}): {}",
self.time, self.module, self.level, self.message
)
} }
} }

View file

@ -1,6 +1,7 @@
use crate::{Backend, Error, Result}; use crate::{Backend, Error, Result};
use db::Track; use db::Track;
use glib::clone; use glib::clone;
use gstreamer_player::PlayerVideoRenderer;
use musicus_database as db; use musicus_database as db;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::path::PathBuf; use std::path::PathBuf;
@ -32,10 +33,7 @@ pub struct Player {
impl Player { impl Player {
pub fn new(music_library_path: PathBuf) -> Rc<Self> { pub fn new(music_library_path: PathBuf) -> Rc<Self> {
let dispatcher = gstreamer_player::PlayerGMainContextSignalDispatcher::new(None); let dispatcher = gstreamer_player::PlayerGMainContextSignalDispatcher::new(None);
let player = gstreamer_player::Player::new( let player = gstreamer_player::Player::new(None::<PlayerVideoRenderer>, Some(dispatcher));
gstreamer_player::PlayerVideoRenderer::NONE,
Some(&dispatcher),
);
let mut config = player.config(); let mut config = player.config();
config.set_position_update_interval(250); config.set_position_update_interval(250);
player.set_config(config).unwrap(); player.set_config(config).unwrap();

View file

@ -2,7 +2,7 @@ use chrono::Utc;
use diesel::prelude::*; use diesel::prelude::*;
use log::info; use log::info;
use crate::{Result, schema::ensembles, defer_foreign_keys}; use crate::{defer_foreign_keys, schema::ensembles, Result};
/// An ensemble that takes part in recordings. /// An ensemble that takes part in recordings.
#[derive(Insertable, Queryable, PartialEq, Eq, Hash, Debug, Clone)] #[derive(Insertable, Queryable, PartialEq, Eq, Hash, Debug, Clone)]

View file

@ -82,7 +82,7 @@ impl Track {
/// Table data for a [`Medium`]. /// Table data for a [`Medium`].
#[derive(Insertable, Queryable, Debug, Clone)] #[derive(Insertable, Queryable, Debug, Clone)]
#[table_name = "mediums"] #[diesel(table_name = mediums)]
struct MediumRow { struct MediumRow {
pub id: String, pub id: String,
pub name: String, pub name: String,
@ -93,7 +93,7 @@ struct MediumRow {
/// Table data for a [`Track`]. /// Table data for a [`Track`].
#[derive(Insertable, Queryable, QueryableByName, Debug, Clone)] #[derive(Insertable, Queryable, QueryableByName, Debug, Clone)]
#[table_name = "tracks"] #[diesel(table_name = tracks)]
struct TrackRow { struct TrackRow {
pub id: String, pub id: String,
pub medium: Option<String>, pub medium: Option<String>,

View file

@ -97,7 +97,7 @@ impl PersonOrEnsemble {
/// Database table data for a recording. /// Database table data for a recording.
#[derive(Insertable, Queryable, QueryableByName, Debug, Clone)] #[derive(Insertable, Queryable, QueryableByName, Debug, Clone)]
#[table_name = "recordings"] #[diesel(table_name = recordings)]
struct RecordingRow { struct RecordingRow {
pub id: String, pub id: String,
pub work: String, pub work: String,
@ -120,7 +120,7 @@ impl From<Recording> for RecordingRow {
/// Database table data for a performance. /// Database table data for a performance.
#[derive(Insertable, Queryable, Debug, Clone)] #[derive(Insertable, Queryable, Debug, Clone)]
#[table_name = "performances"] #[diesel(table_name = performances)]
struct PerformanceRow { struct PerformanceRow {
pub id: i64, pub id: i64,
pub recording: String, pub recording: String,

View file

@ -10,7 +10,7 @@ use crate::{
/// Table row data for a work. /// Table row data for a work.
#[derive(Insertable, Queryable, Debug, Clone)] #[derive(Insertable, Queryable, Debug, Clone)]
#[table_name = "works"] #[diesel(table_name = works)]
struct WorkRow { struct WorkRow {
pub id: String, pub id: String,
pub composer: String, pub composer: String,
@ -33,7 +33,7 @@ impl From<Work> for WorkRow {
/// Definition that a work uses an instrument. /// Definition that a work uses an instrument.
#[derive(Insertable, Queryable, Debug, Clone)] #[derive(Insertable, Queryable, Debug, Clone)]
#[table_name = "instrumentations"] #[diesel(table_name = instrumentations)]
struct InstrumentationRow { struct InstrumentationRow {
pub id: i64, pub id: i64,
pub work: String, pub work: String,
@ -42,7 +42,7 @@ struct InstrumentationRow {
/// Table row data for a work part. /// Table row data for a work part.
#[derive(Insertable, Queryable, Debug, Clone)] #[derive(Insertable, Queryable, Debug, Clone)]
#[table_name = "work_parts"] #[diesel(table_name = work_parts)]
struct WorkPartRow { struct WorkPartRow {
pub id: i64, pub id: i64,
pub work: String, pub work: String,

View file

@ -4,10 +4,10 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
base64 = "0.13" base64 = "0.21"
glib = "0.16" glib = "0.17"
gstreamer = "0.19" gstreamer = "0.20"
gstreamer-pbutils = "0.19" gstreamer-pbutils = "0.20"
log = "0.4" log = "0.4"
once_cell = "1" once_cell = "1"
rand = "0.8" rand = "0.8"

View file

@ -1,5 +1,6 @@
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::session::{ImportSession, ImportTrack, State}; use crate::session::{ImportSession, ImportTrack, State};
use base64::Engine;
use gstreamer::prelude::*; use gstreamer::prelude::*;
use gstreamer::tags::{Duration, TrackNumber}; use gstreamer::tags::{Duration, TrackNumber};
use gstreamer::{ClockTime, ElementFactory, MessageType, MessageView, TocEntryType}; use gstreamer::{ClockTime, ElementFactory, MessageType, MessageView, TocEntryType};
@ -108,7 +109,7 @@ pub(super) fn new() -> Result<ImportSession> {
} }
} }
let source_id = base64::encode_config(hasher.finalize(), base64::URL_SAFE); let source_id = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(hasher.finalize());
info!("Successfully loaded audio CD with {} tracks.", tracks.len()); info!("Successfully loaded audio CD with {} tracks.", tracks.len());
info!("Source ID: {}", source_id); info!("Source ID: {}", source_id);

View file

@ -1,5 +1,6 @@
use crate::error::{Error, Result}; use crate::error::{Error, Result};
use crate::session::{ImportSession, ImportTrack, State}; use crate::session::{ImportSession, ImportTrack, State};
use base64::Engine;
use gstreamer::ClockTime; use gstreamer::ClockTime;
use gstreamer_pbutils::Discoverer; use gstreamer_pbutils::Discoverer;
use log::{info, warn}; use log::{info, warn};
@ -64,7 +65,7 @@ pub(super) fn new(path: PathBuf) -> Result<ImportSession> {
} }
} }
let source_id = base64::encode_config(hasher.finalize(), base64::URL_SAFE); let source_id = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(hasher.finalize());
info!("Source ID: {}", source_id); info!("Source ID: {}", source_id);

View file

@ -5,13 +5,13 @@ edition = "2021"
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
adw = { package = "libadwaita", version = "0.2", features = ["v1_2"] } adw = { package = "libadwaita", version = "0.3", features = ["v1_2"] }
futures-channel = "0.3" futures-channel = "0.3"
gettext-rs = { version = "0.7", features = ["gettext-system"] } gettext-rs = { version = "0.7", features = ["gettext-system"] }
gio = "0.16" gio = "0.17"
glib = "0.16" glib = "0.17"
gstreamer = "0.19" gstreamer = "0.20"
gtk = { package = "gtk4", version = "0.5" } gtk = { package = "gtk4", version = "0.6" }
gtk-macros = "0.3" gtk-macros = "0.3"
log = "0.4" log = "0.4"
musicus_backend = { version = "0.1.0", path = "../backend" } musicus_backend = { version = "0.1.0", path = "../backend" }

View file

@ -2,8 +2,8 @@ use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::{Editor, Section, Widget}; use crate::widgets::{Editor, Section, Widget};
use anyhow::Result; use anyhow::Result;
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{builders::ListBoxBuilder, glib::clone, prelude::*}; use gtk::{glib::clone, prelude::*};
use musicus_backend::db::{generate_id, Ensemble, self}; use musicus_backend::db::{self, generate_id, Ensemble};
use std::rc::Rc; use std::rc::Rc;
/// A dialog for creating or editing a ensemble. /// A dialog for creating or editing a ensemble.
@ -23,12 +23,12 @@ impl Screen<Option<Ensemble>, Ensemble> for EnsembleEditor {
let editor = Editor::new(); let editor = Editor::new();
editor.set_title("Ensemble"); editor.set_title("Ensemble");
let list = ListBoxBuilder::new() let list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
let name = adw::EntryRow::builder().title(&gettext("Name")).build(); let name = adw::EntryRow::builder().title(gettext("Name")).build();
list.append(&name); list.append(&name);
let section = Section::new(&gettext("General"), &list); let section = Section::new(&gettext("General"), &list);
@ -88,7 +88,10 @@ impl EnsembleEditor {
let ensemble = Ensemble::new(self.id.clone(), name.to_string()); let ensemble = Ensemble::new(self.id.clone(), name.to_string());
db::update_ensemble(&mut self.handle.backend.db().lock().unwrap(), ensemble.clone())?; db::update_ensemble(
&mut self.handle.backend.db().lock().unwrap(),
ensemble.clone(),
)?;
self.handle.backend.library_changed(); self.handle.backend.library_changed();
Ok(ensemble) Ok(ensemble)

View file

@ -2,7 +2,7 @@ use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::{Editor, Section, Widget}; use crate::widgets::{Editor, Section, Widget};
use anyhow::Result; use anyhow::Result;
use gettextrs::gettext; use gettextrs::gettext;
use gtk::{builders::ListBoxBuilder, glib::clone, prelude::*}; use gtk::{glib::clone, prelude::*};
use musicus_backend::db::{self, generate_id, Instrument}; use musicus_backend::db::{self, generate_id, Instrument};
use std::rc::Rc; use std::rc::Rc;
@ -23,12 +23,12 @@ impl Screen<Option<Instrument>, Instrument> for InstrumentEditor {
let editor = Editor::new(); let editor = Editor::new();
editor.set_title("Instrument/Role"); editor.set_title("Instrument/Role");
let list = ListBoxBuilder::new() let list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
let name = adw::EntryRow::builder().title(&gettext("Name")).build(); let name = adw::EntryRow::builder().title(gettext("Name")).build();
list.append(&name); list.append(&name);
let section = Section::new(&gettext("General"), &list); let section = Section::new(&gettext("General"), &list);

View file

@ -3,8 +3,8 @@ use crate::selectors::{EnsembleSelector, InstrumentSelector, PersonSelector};
use crate::widgets::{ButtonRow, Editor, Section, Widget}; use crate::widgets::{ButtonRow, Editor, Section, Widget};
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use gtk::builders::ButtonBuilder;
use gtk::{builders::ListBoxBuilder, glib::clone}; use gtk::glib::clone;
use log::error; use log::error;
use musicus_backend::db::{Ensemble, Instrument, Performance, Person, PersonOrEnsemble}; use musicus_backend::db::{Ensemble, Instrument, Performance, Person, PersonOrEnsemble};
use std::cell::RefCell; use std::cell::RefCell;
@ -30,7 +30,7 @@ impl Screen<Option<Performance>, Performance> for PerformanceEditor {
editor.set_title("Performance"); editor.set_title("Performance");
editor.set_may_save(false); editor.set_may_save(false);
let performer_list = ListBoxBuilder::new() let performer_list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
@ -46,12 +46,12 @@ impl Screen<Option<Performance>, Performance> for PerformanceEditor {
"Select either a person or an ensemble as a performer.", "Select either a person or an ensemble as a performer.",
)); ));
let role_list = ListBoxBuilder::new() let role_list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
let reset_role_button = ButtonBuilder::new() let reset_role_button = gtk::Button::builder()
.icon_name("user-trash-symbolic") .icon_name("user-trash-symbolic")
.valign(gtk::Align::Center) .valign(gtk::Align::Center)
.visible(false) .visible(false)

View file

@ -3,8 +3,8 @@ use crate::widgets::{Editor, Section, Widget};
use anyhow::Result; use anyhow::Result;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use gtk::{builders::ListBoxBuilder, prelude::*}; use gtk::prelude::*;
use musicus_backend::db::{generate_id, Person, self}; use musicus_backend::db::{self, generate_id, Person};
use std::rc::Rc; use std::rc::Rc;
/// A dialog for creating or editing a person. /// A dialog for creating or editing a person.
@ -25,18 +25,16 @@ impl Screen<Option<Person>, Person> for PersonEditor {
let editor = Editor::new(); let editor = Editor::new();
editor.set_title("Person"); editor.set_title("Person");
let list = ListBoxBuilder::new() let list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
let first_name = adw::EntryRow::builder() let first_name = adw::EntryRow::builder()
.title(&gettext("First name")) .title(gettext("First name"))
.build(); .build();
let last_name = adw::EntryRow::builder() let last_name = adw::EntryRow::builder().title(gettext("Last name")).build();
.title(&gettext("Last name"))
.build();
list.append(&first_name); list.append(&first_name);
list.append(&last_name); list.append(&last_name);

View file

@ -2,7 +2,7 @@ use super::performance::PerformanceEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::selectors::WorkSelector; use crate::selectors::WorkSelector;
use crate::widgets::{List, Widget}; use crate::widgets::{List, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use anyhow::Result; use anyhow::Result;
use gettextrs::gettext; use gettextrs::gettext;
@ -129,10 +129,10 @@ impl Screen<Option<Recording>, Recording> for RecordingEditor {
}); });
})); }));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.activatable_widget(&edit_button) .activatable_widget(&edit_button)
.title(&performance.get_title()) .title(performance.get_title())
.build(); .build();
row.add_suffix(&delete_button); row.add_suffix(&delete_button);

View file

@ -2,7 +2,7 @@ use super::work_part::WorkPartEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::selectors::{InstrumentSelector, PersonSelector}; use crate::selectors::{InstrumentSelector, PersonSelector};
use crate::widgets::{List, Widget}; use crate::widgets::{List, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use anyhow::Result; use anyhow::Result;
use gettextrs::gettext; use gettextrs::gettext;
@ -125,7 +125,7 @@ impl Screen<Option<Work>, Work> for WorkEditor {
this.instrument_list.update(length); this.instrument_list.update(length);
})); }));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.title(&instrument.name) .title(&instrument.name)
.build(); .build();
@ -184,7 +184,7 @@ impl Screen<Option<Work>, Work> for WorkEditor {
}); });
})); }));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.title(&part.title) .title(&part.title)
.activatable_widget(&edit_button) .activatable_widget(&edit_button)

View file

@ -3,7 +3,7 @@ use super::medium_preview::MediumPreview;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::selectors::MediumSelector; use crate::selectors::MediumSelector;
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use glib::clone; use glib::clone;
use gtk_macros::get_widget; use gtk_macros::get_widget;
@ -68,10 +68,10 @@ impl ImportScreen {
let this = self; let this = self;
for medium in mediums { for medium in mediums {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&medium.name) .title(&medium.name)
.subtitle(&format!("{} Tracks", medium.tracks.len())) .subtitle(format!("{} Tracks", medium.tracks.len()))
.build(); .build();
row.connect_activated(clone!(@weak this => move |_| { row.connect_activated(clone!(@weak this => move |_| {

View file

@ -1,7 +1,7 @@
use super::track_set_editor::{TrackData, TrackSetData, TrackSetEditor}; use super::track_set_editor::{TrackData, TrackSetData, TrackSetEditor};
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::{List, Widget}; use crate::widgets::{List, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use anyhow::Result; use anyhow::Result;
use glib::clone; use glib::clone;
@ -109,10 +109,10 @@ impl Screen<(Arc<ImportSession>, Option<Medium>), Medium> for MediumEditor {
edit_button.set_valign(gtk::Align::Center); edit_button.set_valign(gtk::Align::Center);
edit_button.set_child(Some(&edit_image)); edit_button.set_child(Some(&edit_image));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.title(&title) .title(title)
.subtitle(&subtitle) .subtitle(subtitle)
.activatable_widget(&edit_button) .activatable_widget(&edit_button)
.build(); .build();

View file

@ -1,11 +1,11 @@
use super::medium_editor::MediumEditor; use super::medium_editor::MediumEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use gtk::builders::{FrameBuilder, ListBoxBuilder};
use gtk::prelude::*; use gtk::prelude::*;
use gtk_macros::get_widget; use gtk_macros::get_widget;
use musicus_backend::db::{self, Medium}; use musicus_backend::db::{self, Medium};
@ -141,16 +141,16 @@ impl MediumPreview {
if track.recording.id != last_recording_id { if track.recording.id != last_recording_id {
last_recording_id = &track.recording.id; last_recording_id = &track.recording.id;
let list = ListBoxBuilder::new() let list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.margin_bottom(12) .margin_bottom(12)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
let header = ActionRowBuilder::new() let header = adw::ActionRow::builder()
.activatable(false) .activatable(false)
.title(&track.recording.work.get_title()) .title(track.recording.work.get_title())
.subtitle(&track.recording.get_performers()) .subtitle(track.recording.get_performers())
.build(); .build();
list.append(&header); list.append(&header);
@ -174,9 +174,9 @@ impl MediumPreview {
parts.join(", ") parts.join(", ")
}; };
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(false) .activatable(false)
.title(&title) .title(title)
.subtitle(&import_tracks[track.source_index].name) .subtitle(&import_tracks[track.source_index].name)
.margin_start(12) .margin_start(12)
.build(); .build();
@ -186,7 +186,7 @@ impl MediumPreview {
} }
if let Some(list) = &last_list { if let Some(list) = &last_list {
let frame = FrameBuilder::new().margin_bottom(12).build(); let frame = gtk::Frame::builder().margin_bottom(12).build();
frame.set_child(Some(list)); frame.set_child(Some(list));
self.medium_box.append(&frame); self.medium_box.append(&frame);

View file

@ -1,9 +1,9 @@
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use glib::clone; use glib::clone;
use gtk::builders::ListBoxBuilder;
use gtk_macros::get_widget; use gtk_macros::get_widget;
use musicus_backend::db::Recording; use musicus_backend::db::Recording;
use std::cell::RefCell; use std::cell::RefCell;
@ -31,7 +31,7 @@ impl Screen<(Recording, Vec<usize>), Vec<usize>> for TrackEditor {
get_widget!(builder, gtk::Button, select_button); get_widget!(builder, gtk::Button, select_button);
get_widget!(builder, adw::Clamp, clamp); get_widget!(builder, adw::Clamp, clamp);
let parts_list = ListBoxBuilder::new() let parts_list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
@ -68,7 +68,7 @@ impl Screen<(Recording, Vec<usize>), Vec<usize>> for TrackEditor {
} }
})); }));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.title(&part.title) .title(&part.title)
.activatable_widget(&check) .activatable_widget(&check)

View file

@ -1,9 +1,9 @@
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use glib::clone; use glib::clone;
use gtk::builders::ListBoxBuilder;
use gtk_macros::get_widget; use gtk_macros::get_widget;
use musicus_backend::import::ImportSession; use musicus_backend::import::ImportSession;
use std::cell::RefCell; use std::cell::RefCell;
@ -31,7 +31,7 @@ impl Screen<Arc<ImportSession>, Vec<usize>> for TrackSelector {
get_widget!(builder, gtk::Button, select_button); get_widget!(builder, gtk::Button, select_button);
get_widget!(builder, adw::Clamp, clamp); get_widget!(builder, adw::Clamp, clamp);
let track_list = ListBoxBuilder::new() let track_list = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
@ -78,7 +78,7 @@ impl Screen<Arc<ImportSession>, Vec<usize>> for TrackSelector {
} }
})); }));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.title(&track.name) .title(&track.name)
.activatable_widget(&check) .activatable_widget(&check)

View file

@ -3,7 +3,7 @@ use super::track_selector::TrackSelector;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::selectors::RecordingSelector; use crate::selectors::RecordingSelector;
use crate::widgets::{List, Widget}; use crate::widgets::{List, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -145,9 +145,9 @@ impl Screen<Arc<ImportSession>, TrackSetData> for TrackSetEditor {
edit_button.set_valign(gtk::Align::Center); edit_button.set_valign(gtk::Align::Center);
edit_button.set_child(Some(&edit_image)); edit_button.set_child(Some(&edit_image));
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.title(&title) .title(title)
.subtitle(track_name) .subtitle(track_name)
.activatable_widget(&edit_button) .activatable_widget(&edit_button)
.build(); .build();

View file

@ -2,7 +2,7 @@ use crate::widgets::Widget;
use futures_channel::oneshot; use futures_channel::oneshot;
use futures_channel::oneshot::{Receiver, Sender}; use futures_channel::oneshot::{Receiver, Sender};
use glib::clone; use glib::clone;
use gtk::builders::StackBuilder;
use gtk::prelude::*; use gtk::prelude::*;
use musicus_backend::Backend; use musicus_backend::Backend;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -97,7 +97,7 @@ impl Navigator {
W: IsA<gtk::Window>, W: IsA<gtk::Window>,
E: IsA<gtk::Widget>, E: IsA<gtk::Widget>,
{ {
let widget = StackBuilder::new() let widget = gtk::Stack::builder()
.hhomogeneous(false) .hhomogeneous(false)
.vhomogeneous(false) .vhomogeneous(false)
.interpolate_size(true) .interpolate_size(true)

View file

@ -3,7 +3,7 @@ use crate::editors::EnsembleEditor;
use crate::navigator::{NavigationHandle, NavigatorWindow, Screen}; use crate::navigator::{NavigationHandle, NavigatorWindow, Screen};
use crate::widgets; use crate::widgets;
use crate::widgets::{List, Section, Widget}; use crate::widgets::{List, Section, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -75,10 +75,10 @@ impl Screen<Ensemble, ()> for EnsembleScreen {
clone!(@weak this => @default-panic, move |index| { clone!(@weak this => @default-panic, move |index| {
let recording = &this.recordings.borrow()[index]; let recording = &this.recordings.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&recording.work.get_title()) .title(recording.work.get_title())
.subtitle(&recording.get_performers()) .subtitle(recording.get_performers())
.build(); .build();
let recording = recording.to_owned(); let recording = recording.to_owned();
@ -105,7 +105,7 @@ impl Screen<Ensemble, ()> for EnsembleScreen {
.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| { .set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
let medium = &this.mediums.borrow()[index]; let medium = &this.mediums.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&medium.name) .title(&medium.name)
.build(); .build();

View file

@ -4,7 +4,7 @@ use crate::import::SourceSelector;
use crate::navigator::{NavigationHandle, Navigator, NavigatorWindow, Screen}; use crate::navigator::{NavigationHandle, Navigator, NavigatorWindow, Screen};
use crate::preferences::Preferences; use crate::preferences::Preferences;
use crate::widgets::{List, PlayerBar, Widget}; use crate::widgets::{List, PlayerBar, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -102,9 +102,9 @@ impl Screen<(), ()> for MainScreen {
.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| { .set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
let poe = &this.poes.borrow()[index]; let poe = &this.poes.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&poe.get_title()) .title(poe.get_title())
.build(); .build();
let poe = poe.to_owned(); let poe = poe.to_owned();
@ -207,13 +207,13 @@ impl MainScreen {
copy_button.connect_clicked(clone!(@weak logger, @weak toast_overlay => move |widget| { copy_button.connect_clicked(clone!(@weak logger, @weak toast_overlay => move |widget| {
widget.clipboard().set_text(&logger.messages().into_iter().map(|m| m.to_string()).collect::<Vec<String>>().join("\n")); widget.clipboard().set_text(&logger.messages().into_iter().map(|m| m.to_string()).collect::<Vec<String>>().join("\n"));
toast_overlay.add_toast(&adw::Toast::builder().title(&gettext("Copied to clipboard")).build()); toast_overlay.add_toast(adw::Toast::builder().title(gettext("Copied to clipboard")).build());
})); }));
let header = adw::HeaderBar::builder() let header = adw::HeaderBar::builder()
.title_widget( .title_widget(
&adw::WindowTitle::builder() &adw::WindowTitle::builder()
.title(&gettext("Debug log")) .title(gettext("Debug log"))
.build(), .build(),
) )
.build(); .build();
@ -227,7 +227,7 @@ impl MainScreen {
for message in logger.messages() { for message in logger.messages() {
log_list.append( log_list.append(
&adw::ActionRow::builder() &adw::ActionRow::builder()
.title(&format!( .title(format!(
"<b>{}</b> {} <i>{}</i>", "<b>{}</b> {} <i>{}</i>",
message.level, message.level,
message.time.format("%Y-%m-%d %H:%M:%S"), message.time.format("%Y-%m-%d %H:%M:%S"),
@ -255,7 +255,7 @@ impl MainScreen {
adw::Window::builder() adw::Window::builder()
.transient_for(&self.handle.window) .transient_for(&self.handle.window)
.modal(true) .modal(true)
.title(&gettext("Debug log")) .title(gettext("Debug log"))
.default_width(640) .default_width(640)
.default_height(480) .default_height(480)
.content(&toast_overlay) .content(&toast_overlay)
@ -269,10 +269,10 @@ impl MainScreen {
.transient_for(&self.handle.window) .transient_for(&self.handle.window)
.modal(true) .modal(true)
.application_icon("de.johrpan.musicus") .application_icon("de.johrpan.musicus")
.application_name(&gettext("Musicus")) .application_name(gettext("Musicus"))
.developer_name("Elias Projahn") .developer_name("Elias Projahn")
.version(config::VERSION) .version(config::VERSION)
.comments(&gettext("The classical music player and organizer.")) .comments(gettext("The classical music player and organizer."))
.website("https://code.johrpan.de/johrpan/musicus") .website("https://code.johrpan.de/johrpan/musicus")
.developers(vec![String::from("Elias Projahn <elias@johrpan.de>")]) .developers(vec![String::from("Elias Projahn <elias@johrpan.de>")])
.copyright("© 2022 Elias Projahn") .copyright("© 2022 Elias Projahn")

View file

@ -1,7 +1,7 @@
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets; use crate::widgets;
use crate::widgets::{List, Section, Widget}; use crate::widgets::{List, Section, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -75,10 +75,10 @@ impl Screen<Medium, ()> for MediumScreen {
parts.join(", ") parts.join(", ")
}; };
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.margin_start(12) .margin_start(12)
.selectable(false) .selectable(false)
.title(&title) .title(title)
.build(); .build();
row.upcast() row.upcast()

View file

@ -3,7 +3,7 @@ use crate::editors::PersonEditor;
use crate::navigator::{NavigationHandle, NavigatorWindow, Screen}; use crate::navigator::{NavigationHandle, NavigatorWindow, Screen};
use crate::widgets; use crate::widgets;
use crate::widgets::{List, Section, Widget}; use crate::widgets::{List, Section, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -81,7 +81,7 @@ impl Screen<Person, ()> for PersonScreen {
.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| { .set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
let work = &this.works.borrow()[index]; let work = &this.works.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&work.title) .title(&work.title)
.build(); .build();
@ -109,10 +109,10 @@ impl Screen<Person, ()> for PersonScreen {
clone!(@weak this => @default-panic, move |index| { clone!(@weak this => @default-panic, move |index| {
let recording = &this.recordings.borrow()[index]; let recording = &this.recordings.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&recording.work.get_title()) .title(recording.work.get_title())
.subtitle(&recording.get_performers()) .subtitle(recording.get_performers())
.build(); .build();
let recording = recording.to_owned(); let recording = recording.to_owned();
@ -139,7 +139,7 @@ impl Screen<Person, ()> for PersonScreen {
.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| { .set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
let medium = &this.mediums.borrow()[index]; let medium = &this.mediums.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&medium.name) .title(&medium.name)
.build(); .build();

View file

@ -65,7 +65,7 @@ impl Screen<(), ()> for PlayerScreen {
content.append(&list.widget); content.append(&list.widget);
let event_controller = gtk::EventControllerLegacy::new(); let event_controller = gtk::EventControllerLegacy::new();
position_scale.add_controller(&event_controller); position_scale.add_controller(event_controller.clone());
let this = Rc::new(Self { let this = Rc::new(Self {
handle, handle,

View file

@ -2,7 +2,7 @@ use crate::editors::RecordingEditor;
use crate::navigator::{NavigationHandle, NavigatorWindow, Screen}; use crate::navigator::{NavigationHandle, NavigatorWindow, Screen};
use crate::widgets; use crate::widgets;
use crate::widgets::{List, Section, Widget}; use crate::widgets::{List, Section, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -85,8 +85,8 @@ impl Screen<Recording, ()> for RecordingScreen {
title_parts.join(", ") title_parts.join(", ")
}; };
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.title(&title) .title(title)
.build(); .build();
row.upcast() row.upcast()

View file

@ -1,9 +1,7 @@
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::{HeaderBarBuilder, StatusPageBuilder};
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use gtk::builders::{BoxBuilder, ButtonBuilder};
use gtk::prelude::*; use gtk::prelude::*;
use std::rc::Rc; use std::rc::Rc;
@ -17,23 +15,23 @@ pub struct WelcomeScreen {
impl Screen<(), ()> for WelcomeScreen { impl Screen<(), ()> for WelcomeScreen {
fn new(_: (), handle: NavigationHandle<()>) -> Rc<Self> { fn new(_: (), handle: NavigationHandle<()>) -> Rc<Self> {
let widget = BoxBuilder::new() let widget = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical) .orientation(gtk::Orientation::Vertical)
.build(); .build();
let header = HeaderBarBuilder::new() let header = gtk::HeaderBar::builder()
.title_widget(&adw::WindowTitle::new("Musicus", "")) .title_widget(&adw::WindowTitle::new("Musicus", ""))
.build(); .build();
let button = ButtonBuilder::new() let button = gtk::Button::builder()
.halign(gtk::Align::Center) .halign(gtk::Align::Center)
.label(&gettext("Select folder")) .label(gettext("Select folder"))
.build(); .build();
let welcome = StatusPageBuilder::new() let welcome = adw::StatusPage::builder()
.icon_name("folder-music-symbolic") .icon_name("folder-music-symbolic")
.title(&gettext("Welcome to Musicus!")) .title(gettext("Welcome to Musicus!"))
.description(&gettext( .description(gettext(
"Get startet by selecting the folder containing your music \ "Get startet by selecting the folder containing your music \
files! Musicus will create a new database there or open one that already exists.", files! Musicus will create a new database there or open one that already exists.",
)) ))

View file

@ -3,7 +3,7 @@ use crate::editors::WorkEditor;
use crate::navigator::{NavigationHandle, NavigatorWindow, Screen}; use crate::navigator::{NavigationHandle, NavigatorWindow, Screen};
use crate::widgets; use crate::widgets;
use crate::widgets::{List, Section, Widget}; use crate::widgets::{List, Section, Widget};
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -70,10 +70,10 @@ impl Screen<Work, ()> for WorkScreen {
clone!(@weak this => @default-panic, move |index| { clone!(@weak this => @default-panic, move |index| {
let recording = &this.recordings.borrow()[index]; let recording = &this.recordings.borrow()[index];
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&recording.work.get_title()) .title(recording.work.get_title())
.subtitle(&recording.get_performers()) .subtitle(recording.get_performers())
.build(); .build();
let recording = recording.to_owned(); let recording = recording.to_owned();

View file

@ -2,12 +2,12 @@ use super::selector::Selector;
use crate::editors::EnsembleEditor; use crate::editors::EnsembleEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use log::warn; use log::warn;
use musicus_backend::db::{Ensemble, self}; use musicus_backend::db::{self, Ensemble};
use std::rc::Rc; use std::rc::Rc;
/// A screen for selecting a ensemble. /// A screen for selecting a ensemble.
@ -42,7 +42,7 @@ impl Screen<(), Ensemble> for EnsembleSelector {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |ensemble| { .set_make_widget(clone!(@weak this => @default-panic, move |ensemble| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&ensemble.name) .title(&ensemble.name)
.build(); .build();
@ -63,8 +63,9 @@ impl Screen<(), Ensemble> for EnsembleSelector {
this.selector this.selector
.set_filter(|search, ensemble| ensemble.name.to_lowercase().contains(search)); .set_filter(|search, ensemble| ensemble.name.to_lowercase().contains(search));
this.selector this.selector.set_items(
.set_items(db::get_recent_ensembles(&mut this.handle.backend.db().lock().unwrap(), ).unwrap()); db::get_recent_ensembles(&mut this.handle.backend.db().lock().unwrap()).unwrap(),
);
this this
} }

View file

@ -2,12 +2,12 @@ use super::selector::Selector;
use crate::editors::InstrumentEditor; use crate::editors::InstrumentEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use log::warn; use log::warn;
use musicus_backend::db::{Instrument, self}; use musicus_backend::db::{self, Instrument};
use std::rc::Rc; use std::rc::Rc;
/// A screen for selecting a instrument. /// A screen for selecting a instrument.
@ -42,7 +42,7 @@ impl Screen<(), Instrument> for InstrumentSelector {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |instrument| { .set_make_widget(clone!(@weak this => @default-panic, move |instrument| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&instrument.name) .title(&instrument.name)
.build(); .build();
@ -63,8 +63,9 @@ impl Screen<(), Instrument> for InstrumentSelector {
this.selector this.selector
.set_filter(|search, instrument| instrument.name.to_lowercase().contains(search)); .set_filter(|search, instrument| instrument.name.to_lowercase().contains(search));
this.selector this.selector.set_items(
.set_items(db::get_recent_instruments(&mut this.handle.backend.db().lock().unwrap(), ).unwrap()); db::get_recent_instruments(&mut this.handle.backend.db().lock().unwrap()).unwrap(),
);
this this
} }

View file

@ -1,7 +1,7 @@
use super::selector::Selector; use super::selector::Selector;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -31,9 +31,9 @@ impl Screen<(), Medium> for MediumSelector {
})); }));
this.selector.set_make_widget(clone!(@weak this => @default-panic, move |poe| { this.selector.set_make_widget(clone!(@weak this => @default-panic, move |poe| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&poe.get_title()) .title(poe.get_title())
.build(); .build();
let poe = poe.to_owned(); let poe = poe.to_owned();
@ -106,7 +106,7 @@ impl Screen<PersonOrEnsemble, Medium> for MediumSelectorMediumScreen {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |medium| { .set_make_widget(clone!(@weak this => @default-panic, move |medium| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&medium.name) .title(&medium.name)
.build(); .build();

View file

@ -2,12 +2,12 @@ use super::selector::Selector;
use crate::editors::PersonEditor; use crate::editors::PersonEditor;
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use log::warn; use log::warn;
use musicus_backend::db::{Person, self}; use musicus_backend::db::{self, Person};
use std::rc::Rc; use std::rc::Rc;
/// A screen for selecting a person. /// A screen for selecting a person.
@ -42,9 +42,9 @@ impl Screen<(), Person> for PersonSelector {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |person| { .set_make_widget(clone!(@weak this => @default-panic, move |person| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&person.name_lf()) .title(person.name_lf())
.build(); .build();
let person = person.to_owned(); let person = person.to_owned();
@ -63,8 +63,9 @@ impl Screen<(), Person> for PersonSelector {
this.selector this.selector
.set_filter(|search, person| person.name_fl().to_lowercase().contains(search)); .set_filter(|search, person| person.name_fl().to_lowercase().contains(search));
this.selector this.selector.set_items(
.set_items(db::get_recent_persons(&mut this.handle.backend.db().lock().unwrap(), ).unwrap()); db::get_recent_persons(&mut this.handle.backend.db().lock().unwrap()).unwrap(),
);
this this
} }

View file

@ -2,7 +2,7 @@ use super::selector::Selector;
use crate::editors::{PersonEditor, RecordingEditor, WorkEditor}; use crate::editors::{PersonEditor, RecordingEditor, WorkEditor};
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
@ -53,9 +53,9 @@ impl Screen<(), Recording> for RecordingSelector {
})); }));
this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| { this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&person.name_lf()) .title(person.name_lf())
.build(); .build();
let person = person.to_owned(); let person = person.to_owned();
@ -129,7 +129,7 @@ impl Screen<Person, Work> for RecordingSelectorWorkScreen {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |work| { .set_make_widget(clone!(@weak this => @default-panic, move |work| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&work.title) .title(&work.title)
.build(); .build();
@ -197,9 +197,9 @@ impl Screen<Work, Recording> for RecordingSelectorRecordingScreen {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |recording| { .set_make_widget(clone!(@weak this => @default-panic, move |recording| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&recording.get_performers()) .title(recording.get_performers())
.build(); .build();
let recording = recording.to_owned(); let recording = recording.to_owned();

View file

@ -2,12 +2,12 @@ use super::selector::Selector;
use crate::editors::{PersonEditor, WorkEditor}; use crate::editors::{PersonEditor, WorkEditor};
use crate::navigator::{NavigationHandle, Screen}; use crate::navigator::{NavigationHandle, Screen};
use crate::widgets::Widget; use crate::widgets::Widget;
use adw::builders::ActionRowBuilder;
use adw::prelude::*; use adw::prelude::*;
use gettextrs::gettext; use gettextrs::gettext;
use glib::clone; use glib::clone;
use log::warn; use log::warn;
use musicus_backend::db::{Person, Work, self}; use musicus_backend::db::{self, Person, Work};
use std::rc::Rc; use std::rc::Rc;
/// A screen for selecting a work. /// A screen for selecting a work.
@ -47,9 +47,9 @@ impl Screen<(), Work> for WorkSelector {
})); }));
this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| { this.selector.set_make_widget(clone!(@weak this => @default-panic, move |person| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&person.name_lf()) .title(person.name_lf())
.build(); .build();
let person = person.to_owned(); let person = person.to_owned();
@ -71,8 +71,9 @@ impl Screen<(), Work> for WorkSelector {
this.selector this.selector
.set_filter(|search, person| person.name_fl().to_lowercase().contains(search)); .set_filter(|search, person| person.name_fl().to_lowercase().contains(search));
this.selector this.selector.set_items(
.set_items(db::get_recent_persons(&mut this.handle.backend.db().lock().unwrap()).unwrap()); db::get_recent_persons(&mut this.handle.backend.db().lock().unwrap()).unwrap(),
);
this this
} }
@ -118,7 +119,7 @@ impl Screen<Person, Work> for WorkSelectorWorkScreen {
this.selector this.selector
.set_make_widget(clone!(@weak this => @default-panic, move |work| { .set_make_widget(clone!(@weak this => @default-panic, move |work| {
let row = ActionRowBuilder::new() let row = adw::ActionRow::builder()
.activatable(true) .activatable(true)
.title(&work.title) .title(&work.title)
.build(); .build();
@ -138,8 +139,13 @@ impl Screen<Person, Work> for WorkSelectorWorkScreen {
this.selector this.selector
.set_filter(|search, work| work.title.to_lowercase().contains(search)); .set_filter(|search, work| work.title.to_lowercase().contains(search));
this.selector this.selector.set_items(
.set_items(db::get_works(&mut this.handle.backend.db().lock().unwrap(), &this.person.id).unwrap()); db::get_works(
&mut this.handle.backend.db().lock().unwrap(),
&this.person.id,
)
.unwrap(),
);
this this
} }

View file

@ -1,6 +1,5 @@
use super::Widget; use super::Widget;
use adw::{builders::ActionRowBuilder, prelude::*}; use adw::prelude::*;
use gtk::builders::ButtonBuilder;
/// A list box row with a single button. /// A list box row with a single button.
pub struct ButtonRow { pub struct ButtonRow {
@ -14,12 +13,12 @@ pub struct ButtonRow {
impl ButtonRow { impl ButtonRow {
/// Create a new button row. /// Create a new button row.
pub fn new(title: &str, label: &str) -> Self { pub fn new(title: &str, label: &str) -> Self {
let button = ButtonBuilder::new() let button = gtk::Button::builder()
.valign(gtk::Align::Center) .valign(gtk::Align::Center)
.label(label) .label(label)
.build(); .build();
let widget = ActionRowBuilder::new() let widget = adw::ActionRow::builder()
.focusable(false) .focusable(false)
.activatable_widget(&button) .activatable_widget(&button)
.title(title) .title(title)

View file

@ -1,6 +1,6 @@
use gio::prelude::*; use gio::prelude::*;
use gio::subclass::prelude::*; use gio::subclass::prelude::*;
use once_cell::sync::Lazy;
use std::cell::Cell; use std::cell::Cell;
glib::wrapper! { glib::wrapper! {
@ -12,24 +12,28 @@ glib::wrapper! {
impl IndexedListModel { impl IndexedListModel {
/// Set the length of the list model. /// Set the length of the list model.
pub fn set_length(&self, length: u32) { pub fn set_length(&self, length: u32) {
let old_length = self.property("length"); let old_length = self.n_items();
self.set_property("length", &length); self.set_n_items(length);
self.items_changed(0, old_length, length); self.items_changed(0, old_length, length);
} }
} }
impl Default for IndexedListModel { impl Default for IndexedListModel {
fn default() -> Self { fn default() -> Self {
glib::Object::new(&[]) glib::Object::new()
} }
} }
mod indexed_list_model_imp { mod indexed_list_model_imp {
use glib::Properties;
use super::*; use super::*;
#[derive(Debug, Default)] #[derive(Properties, Default)]
#[properties(wrapper_type = super::IndexedListModel)]
pub struct IndexedListModel { pub struct IndexedListModel {
length: Cell<u32>, #[property(get, set)]
n_items: Cell<u32>,
} }
#[glib::object_subclass] #[glib::object_subclass]
@ -42,36 +46,15 @@ mod indexed_list_model_imp {
impl ObjectImpl for IndexedListModel { impl ObjectImpl for IndexedListModel {
fn properties() -> &'static [glib::ParamSpec] { fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { Self::derived_properties()
vec![glib::ParamSpecUInt::new(
"length",
"Length",
"Length",
0,
std::u32::MAX,
0,
glib::ParamFlags::READWRITE,
)]
});
PROPERTIES.as_ref()
} }
fn set_property(&self, _: usize, value: &glib::Value, pspec: &glib::ParamSpec) { fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() { self.derived_set_property(id, value, pspec)
"length" => {
let length = value.get::<u32>().unwrap();
self.length.set(length);
}
_ => unimplemented!(),
}
} }
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() { self.derived_property(id, pspec)
"length" => self.length.get().to_value(),
_ => unimplemented!(),
}
} }
} }
@ -81,7 +64,7 @@ mod indexed_list_model_imp {
} }
fn n_items(&self) -> u32 { fn n_items(&self) -> u32 {
self.length.get() self.n_items.get()
} }
fn item(&self, position: u32) -> Option<glib::Object> { fn item(&self, position: u32) -> Option<glib::Object> {
@ -98,7 +81,9 @@ glib::wrapper! {
impl ItemIndex { impl ItemIndex {
/// Create a new item index. /// Create a new item index.
pub fn new(value: u32) -> Self { pub fn new(value: u32) -> Self {
glib::Object::new(&[("value", &value)]) let object = glib::Object::new::<Self>();
object.set_value(value);
object
} }
/// Get the value of the item index.. /// Get the value of the item index..
@ -108,10 +93,14 @@ impl ItemIndex {
} }
mod item_index_imp { mod item_index_imp {
use glib::Properties;
use super::*; use super::*;
#[derive(Debug, Default)] #[derive(Properties, Default)]
#[properties(wrapper_type = super::ItemIndex)]
pub struct ItemIndex { pub struct ItemIndex {
#[property(get, set)]
value: Cell<u32>, value: Cell<u32>,
} }
@ -125,36 +114,15 @@ mod item_index_imp {
impl ObjectImpl for ItemIndex { impl ObjectImpl for ItemIndex {
fn properties() -> &'static [glib::ParamSpec] { fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { Self::derived_properties()
vec![glib::ParamSpecUInt::new(
"value",
"Value",
"Value",
0,
std::u32::MAX,
0,
glib::ParamFlags::READWRITE,
)]
});
PROPERTIES.as_ref()
} }
fn set_property(&self, _: usize, value: &glib::Value, pspec: &glib::ParamSpec) { fn set_property(&self, id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() { self.derived_set_property(id, value, pspec)
"value" => {
let value = value.get::<u32>().unwrap();
self.value.set(value);
}
_ => unimplemented!(),
}
} }
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() { self.derived_property(id, pspec)
"value" => self.value.get().to_value(),
_ => unimplemented!(),
}
} }
} }
} }

View file

@ -1,6 +1,6 @@
use super::indexed_list_model::{IndexedListModel, ItemIndex}; use super::indexed_list_model::{IndexedListModel, ItemIndex};
use glib::clone; use glib::clone;
use gtk::{builders::ListBoxBuilder, gdk, prelude::*}; use gtk::{gdk, prelude::*};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
@ -20,14 +20,14 @@ impl List {
pub fn new() -> Rc<Self> { pub fn new() -> Rc<Self> {
let model = IndexedListModel::default(); let model = IndexedListModel::default();
let filter = gtk::CustomFilter::new(|_| true); let filter = gtk::CustomFilter::new(|_| true);
let filter_model = gtk::FilterListModel::new(Some(&model), Some(&filter)); let filter_model = gtk::FilterListModel::new(Some(model.clone()), Some(filter.clone()));
// TODO: Switch to gtk::ListView. // TODO: Switch to gtk::ListView.
// let selection = gtk::NoSelection::new(Some(&model)); // let selection = gtk::NoSelection::new(Some(&model));
// let factory = gtk::SignalListItemFactory::new(); // let factory = gtk::SignalListItemFactory::new();
// let widget = gtk::ListView::new(Some(&selection), Some(&factory)); // let widget = gtk::ListView::new(Some(&selection), Some(&factory));
let widget = ListBoxBuilder::new() let widget = gtk::ListBox::builder()
.selection_mode(gtk::SelectionMode::None) .selection_mode(gtk::SelectionMode::None)
.css_classes(vec![String::from("boxed-list")]) .css_classes(vec![String::from("boxed-list")])
.build(); .build();
@ -45,7 +45,7 @@ impl List {
this.filter this.filter
.set_filter_func(clone!(@strong this => move |index| { .set_filter_func(clone!(@strong this => move |index| {
if let Some(cb) = &*this.filter_cb.borrow() { if let Some(cb) = &*this.filter_cb.borrow() {
let index = index.downcast_ref::<ItemIndex>().unwrap().get() as usize; let index = index.downcast_ref::<ItemIndex>().unwrap().value() as usize;
cb(index) cb(index)
} else { } else {
true true
@ -81,8 +81,8 @@ impl List {
} }
})); }));
widget.add_controller(&drag_source); widget.add_controller(drag_source);
widget.add_controller(&drop_target); widget.add_controller(drop_target);
} }
widget widget
@ -109,6 +109,7 @@ impl List {
/// false, the item will not be shown. /// false, the item will not be shown.
pub fn set_filter_cb<F: Fn(usize) -> bool + 'static>(&self, cb: F) { pub fn set_filter_cb<F: Fn(usize) -> bool + 'static>(&self, cb: F) {
self.filter_cb.replace(Some(Box::new(cb))); self.filter_cb.replace(Some(Box::new(cb)));
self.invalidate_filter();
} }
/// Set the closure to be called to when the use has dragged an item to a /// Set the closure to be called to when the use has dragged an item to a

View file

@ -1,5 +1,5 @@
use super::Widget; use super::Widget;
use gtk::{builders::ButtonBuilder, prelude::*}; use gtk::prelude::*;
use gtk_macros::get_widget; use gtk_macros::get_widget;
/// A widget displaying a title, a framed child widget and, if needed, some /// A widget displaying a title, a framed child widget and, if needed, some
@ -46,7 +46,7 @@ impl Section {
/// situations where the widget is visible. The new button will be packed /// situations where the widget is visible. The new button will be packed
/// to the end of the title box. /// to the end of the title box.
pub fn add_action<F: Fn() + 'static>(&self, icon_name: &str, cb: F) { pub fn add_action<F: Fn() + 'static>(&self, icon_name: &str, cb: F) {
let button = ButtonBuilder::new() let button = gtk::Button::builder()
.has_frame(false) .has_frame(false)
.valign(gtk::Align::Center) .valign(gtk::Align::Center)
.margin_top(12) .margin_top(12)

View file

@ -1,9 +1,9 @@
use crate::navigator::Navigator; use crate::navigator::Navigator;
use crate::screens::{MainScreen, WelcomeScreen}; use crate::screens::{MainScreen, WelcomeScreen};
use adw::builders::HeaderBarBuilder;
use adw::prelude::*; use adw::prelude::*;
use glib::clone; use glib::clone;
use gtk::builders::{BoxBuilder, SpinnerBuilder};
use musicus_backend::{Backend, BackendState}; use musicus_backend::{Backend, BackendState};
use std::rc::Rc; use std::rc::Rc;
@ -23,15 +23,15 @@ impl Window {
window.set_title(Some("Musicus")); window.set_title(Some("Musicus"));
window.set_default_size(1000, 707); window.set_default_size(1000, 707);
let loading_screen = BoxBuilder::new() let loading_screen = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical) .orientation(gtk::Orientation::Vertical)
.build(); .build();
let header = HeaderBarBuilder::new() let header = gtk::HeaderBar::builder()
.title_widget(&adw::WindowTitle::new("Musicus", "")) .title_widget(&adw::WindowTitle::new("Musicus", ""))
.build(); .build();
let spinner = SpinnerBuilder::new() let spinner = gtk::Spinner::builder()
.hexpand(true) .hexpand(true)
.vexpand(true) .vexpand(true)
.halign(gtk::Align::Center) .halign(gtk::Align::Center)