diff --git a/data/res/home_page.blp b/data/res/home_page.blp
new file mode 100644
index 0000000..ae202c9
--- /dev/null
+++ b/data/res/home_page.blp
@@ -0,0 +1,107 @@
+using Gtk 4.0;
+using Adw 1;
+
+template $MusicusHomePage : Adw.NavigationPage {
+ title: _("Musicus");
+ tag: "home";
+
+ Adw.ToolbarView {
+ [top]
+ Adw.HeaderBar header_bar {
+ [end]
+ MenuButton {
+ icon-name: "open-menu-symbolic";
+ menu-model: primary_menu;
+ }
+ }
+
+ [top]
+ Adw.Clamp {
+ maximum-size: 1000;
+ tightening-threshold: 600;
+
+ Adw.Bin {
+ styles ["searchbar"]
+
+ Gtk.SearchEntry search_entry {
+ placeholder-text: _("Enter composers, performers, works…");
+ }
+ }
+ }
+
+ Gtk.ScrolledWindow {
+ hscrollbar-policy: never;
+
+ Adw.Clamp {
+ maximum-size: 1000;
+ tightening-threshold: 600;
+
+ Gtk.Box {
+ orientation: vertical;
+ margin-start: 12;
+ margin-end: 12;
+ margin-top: 24;
+
+ Gtk.Label {
+ styles ["heading"]
+ visible: bind persons_flow_box.visible;
+ halign: start;
+ label: _("Composers and performers");
+ }
+
+ Gtk.FlowBox persons_flow_box {
+ margin-top: 12;
+ margin-bottom: 24;
+ column-spacing: 14;
+ row-spacing: 14;
+ homogeneous: true;
+ selection-mode: none;
+ }
+
+ Gtk.Label {
+ styles ["heading"]
+ visible: bind works_flow_box.visible;
+ halign: start;
+ label: _("Works");
+ }
+
+ Gtk.FlowBox works_flow_box {
+ margin-top: 12;
+ margin-bottom: 24;
+ column-spacing: 14;
+ row-spacing: 14;
+ homogeneous: true;
+ selection-mode: none;
+ }
+
+ Gtk.Label {
+ styles ["heading"]
+ visible: bind recordings_flow_box.visible;
+ halign: start;
+ label: _("Recordings");
+ }
+
+ Gtk.FlowBox recordings_flow_box {
+ margin-top: 12;
+ margin-bottom: 24;
+ column-spacing: 14;
+ row-spacing: 14;
+ homogeneous: true;
+ selection-mode: none;
+ }
+ }
+ }
+ }
+ }
+}
+
+menu primary_menu {
+ item {
+ label: _("_Preferences");
+ action: "app.preferences";
+ }
+ item {
+ label: _("_About Musicus");
+ action: "app.about";
+ }
+}
\ No newline at end of file
diff --git a/data/res/meson.build b/data/res/meson.build
index 8c497f2..910b91b 100644
--- a/data/res/meson.build
+++ b/data/res/meson.build
@@ -3,6 +3,8 @@ gnome = import('gnome')
blueprints = custom_target('blueprints',
input: files(
+ 'home_page.blp',
+ 'tile.blp',
'welcome_page.blp',
'window.blp'
),
diff --git a/data/res/musicus.gresource.xml b/data/res/musicus.gresource.xml
index fbd2760..2417a98 100644
--- a/data/res/musicus.gresource.xml
+++ b/data/res/musicus.gresource.xml
@@ -1,7 +1,10 @@
+ home_page.ui
+ tile.ui
welcome_page.ui
window.ui
+ style.css
diff --git a/data/res/style.css b/data/res/style.css
new file mode 100644
index 0000000..82485bf
--- /dev/null
+++ b/data/res/style.css
@@ -0,0 +1,3 @@
+.searchbar {
+ padding: 6px 6px 7px 6px;
+}
\ No newline at end of file
diff --git a/data/res/tile.blp b/data/res/tile.blp
new file mode 100644
index 0000000..531490c
--- /dev/null
+++ b/data/res/tile.blp
@@ -0,0 +1,39 @@
+using Gtk 4.0;
+using Adw 1;
+
+template $MusicusTile : Gtk.FlowBoxChild {
+ styles ["card", "activatable"]
+ width-request: 200;
+
+ Gtk.Box {
+ orientation: vertical;
+ margin-start: 6;
+ margin-end: 6;
+ margin-top: 6;
+ margin-bottom: 6;
+
+ Gtk.Label title_label {
+ styles ["caption-heading"]
+ halign: start;
+ label: _("Title");
+ }
+
+ Gtk.Label subtitle_label {
+ styles ["caption"]
+ halign: start;
+ label: _("Subtitle");
+ }
+ }
+}
+
+menu item_menu {
+ item {
+ label: _("_Play");
+ }
+ item {
+ label: _("_Edit");
+ }
+ item {
+ label: _("_Delete");
+ }
+}
\ No newline at end of file
diff --git a/data/res/window.blp b/data/res/window.blp
index 274a1d3..47e97e2 100644
--- a/data/res/window.blp
+++ b/data/res/window.blp
@@ -10,5 +10,7 @@ template $MusicusWindow : Adw.ApplicationWindow {
$MusicusWelcomePage {
folder-selected => $set_library_folder() swapped;
}
+
+ $MusicusHomePage {}
}
}
\ No newline at end of file
diff --git a/po/POTFILES b/po/POTFILES
index bf7baed..e4d06c8 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -1,3 +1,5 @@
+data/res/home_page.blp
+data/res/tile.blp
data/res/welcome_page.blp
data/res/window.blp
data/de.johrpan.musicus.desktop.in
diff --git a/src/home_page.rs b/src/home_page.rs
new file mode 100644
index 0000000..66ceece
--- /dev/null
+++ b/src/home_page.rs
@@ -0,0 +1,64 @@
+use adw::subclass::{navigation_page::NavigationPageImpl, prelude::*};
+use gtk::glib;
+
+mod imp {
+ use crate::tile::MusicusTile;
+
+ use super::*;
+
+ #[derive(Debug, Default, gtk::CompositeTemplate)]
+ #[template(resource = "/de/johrpan/musicus/home_page.ui")]
+ pub struct MusicusHomePage {
+ #[template_child]
+ pub search_entry: TemplateChild,
+ #[template_child]
+ pub persons_flow_box: TemplateChild,
+ #[template_child]
+ pub works_flow_box: TemplateChild,
+ #[template_child]
+ pub recordings_flow_box: TemplateChild,
+ }
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for MusicusHomePage {
+ const NAME: &'static str = "MusicusHomePage";
+ type Type = super::MusicusHomePage;
+ type ParentType = adw::NavigationPage;
+
+ fn class_init(klass: &mut Self::Class) {
+ klass.bind_template();
+ }
+
+ fn instance_init(obj: &glib::subclass::InitializingObject) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for MusicusHomePage {
+ fn constructed(&self) {
+ self.parent_constructed();
+ self.search_entry
+ .set_key_capture_widget(Some(self.obj().as_ref()));
+
+ for _ in 0..9 {
+ self.persons_flow_box.append(&MusicusTile::new());
+ self.works_flow_box.append(&MusicusTile::new());
+ self.recordings_flow_box.append(&MusicusTile::new());
+ }
+ }
+ }
+
+ impl WidgetImpl for MusicusHomePage {}
+ impl NavigationPageImpl for MusicusHomePage {}
+}
+
+glib::wrapper! {
+ pub struct MusicusHomePage(ObjectSubclass)
+ @extends gtk::Widget, adw::NavigationPage;
+}
+
+impl MusicusHomePage {
+ pub fn new() -> Self {
+ glib::Object::new()
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index d2afe79..58cf09f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,7 @@
mod application;
mod config;
+mod home_page;
+mod tile;
mod welcome_page;
mod window;
diff --git a/src/tile.rs b/src/tile.rs
new file mode 100644
index 0000000..399a117
--- /dev/null
+++ b/src/tile.rs
@@ -0,0 +1,39 @@
+use gtk::{glib, subclass::prelude::*};
+
+mod imp {
+ use super::*;
+
+ #[derive(Debug, Default, gtk::CompositeTemplate)]
+ #[template(resource = "/de/johrpan/musicus/tile.ui")]
+ pub struct MusicusTile {}
+
+ #[glib::object_subclass]
+ impl ObjectSubclass for MusicusTile {
+ const NAME: &'static str = "MusicusTile";
+ type Type = super::MusicusTile;
+ type ParentType = gtk::FlowBoxChild;
+
+ fn class_init(klass: &mut Self::Class) {
+ klass.bind_template();
+ }
+
+ fn instance_init(obj: &glib::subclass::InitializingObject) {
+ obj.init_template();
+ }
+ }
+
+ impl ObjectImpl for MusicusTile {}
+ impl WidgetImpl for MusicusTile {}
+ impl FlowBoxChildImpl for MusicusTile {}
+}
+
+glib::wrapper! {
+ pub struct MusicusTile(ObjectSubclass)
+ @extends gtk::Widget, gtk::FlowBoxChild;
+}
+
+impl MusicusTile {
+ pub fn new() -> Self {
+ glib::Object::new()
+ }
+}
diff --git a/src/window.rs b/src/window.rs
index c00fa4c..31bca63 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -1,4 +1,4 @@
-use crate::welcome_page::MusicusWelcomePage;
+use crate::{welcome_page::MusicusWelcomePage, home_page::MusicusHomePage};
use adw::subclass::prelude::*;
use gtk::{gio, glib, prelude::*};
@@ -20,6 +20,7 @@ mod imp {
type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) {
+ MusicusHomePage::static_type();
MusicusWelcomePage::static_type();
klass.bind_template();
klass.bind_template_instance_callbacks();
@@ -60,5 +61,6 @@ impl MusicusWindow {
async fn set_library_folder(&self, folder: &gio::File) {
let path = folder.path();
log::info!("{path:?}");
+ self.imp().navigation_view.replace_with_tags(&["home"]);
}
}