Set up the welcome screen and open the database #125

Merged
savanni merged 7 commits from fitnesstrax/welcome into main 2023-12-19 22:02:41 +00:00
2 changed files with 43 additions and 8 deletions
Showing only changes of commit 104ffc5782 - Show all commits

View File

@ -25,6 +25,8 @@ use gtk::{subclass::prelude::*, STYLE_PROVIDER_PRIORITY_USER};
use std::{ use std::{
cell::RefCell, cell::RefCell,
env, env,
path::PathBuf,
rc::Rc,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use ui::FileChooserRow; use ui::FileChooserRow;
@ -72,7 +74,10 @@ glib::wrapper! {
} }
impl WelcomeView { impl WelcomeView {
pub fn new() -> Self { pub fn new<F>(on_save: F) -> Self
where
F: Fn(PathBuf) + 'static,
{
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical); s.set_orientation(gtk::Orientation::Vertical);
s.set_css_classes(&["modal"]); s.set_css_classes(&["modal"]);
@ -83,7 +88,6 @@ impl WelcomeView {
.label("Welcome to FitnessTrax") .label("Welcome to FitnessTrax")
.css_classes(["modal-title"]) .css_classes(["modal-title"])
.build(); .build();
s.append(&title);
let content = gtk::Box::builder() let content = gtk::Box::builder()
.css_classes(["model-content"]) .css_classes(["model-content"])
@ -91,17 +95,34 @@ impl WelcomeView {
.vexpand(true) .vexpand(true)
.build(); .build();
content.append(&gtk::Label::new(Some("Welcome to FitnessTrax. The application has not yet been configured, so I will walk you through that. Let's start out by selecting your database."))); let save_button = gtk::Button::builder()
.label("Save Settings")
.sensitive(false)
.build();
// The database selection row should be a box that shows a default database path, along with a // The database selection row should be a box that shows a default database path, along with a
// button that triggers a file chooser dialog. Once the dialog returns, the box should be // button that triggers a file chooser dialog. Once the dialog returns, the box should be
// updated to reflect the chosen path. // updated to reflect the chosen path.
let db_row = FileChooserRow::new(); let db_row = FileChooserRow::new({
let save_button = save_button.clone();
move |_| save_button.set_sensitive(true)
});
content.append(&gtk::Label::new(Some("Welcome to FitnessTrax. The application has not yet been configured, so I will walk you through that. Let's start out by selecting your database.")));
content.append(&db_row); content.append(&db_row);
let on_save = Box::new(on_save);
save_button.connect_clicked({
move |_| {
if let Some(path) = db_row.path() {
on_save(path)
}
}
});
s.append(&title);
s.append(&content); s.append(&content);
s.append(&gtk::Button::builder().label("Save Settings").build()); s.append(&save_button);
s s
} }
@ -167,7 +188,7 @@ impl AppWindow {
.build(); .build();
let current_view = if app.database.read().unwrap().is_none() { let current_view = if app.database.read().unwrap().is_none() {
WelcomeView::new().upcast() WelcomeView::new(&|_| {}).upcast()
} else { } else {
HistoricalView::new().upcast() HistoricalView::new().upcast()
}; };

View File

@ -16,7 +16,11 @@ You should have received a copy of the GNU General Public License along with Fit
use glib::Object; use glib::Object;
use gtk::{prelude::*, subclass::prelude::*}; use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, path::PathBuf}; use std::{
cell::RefCell,
path::{Path, PathBuf},
rc::Rc,
};
pub struct FileChooserRowPrivate { pub struct FileChooserRowPrivate {
path: RefCell<Option<PathBuf>>, path: RefCell<Option<PathBuf>>,
@ -46,7 +50,10 @@ glib::wrapper! {
} }
impl FileChooserRow { impl FileChooserRow {
pub fn new() -> Self { pub fn new<F>(on_selected: F) -> Self
where
F: Fn(PathBuf) + 'static,
{
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Horizontal); s.set_orientation(gtk::Orientation::Horizontal);
@ -57,12 +64,14 @@ impl FileChooserRow {
s.imp().label.set_text("No database selected"); s.imp().label.set_text("No database selected");
let db_file_chooser_button = gtk::Button::builder().label("Select Database").build(); let db_file_chooser_button = gtk::Button::builder().label("Select Database").build();
let on_selected = Rc::new(Box::new(on_selected));
db_file_chooser_button.connect_clicked({ db_file_chooser_button.connect_clicked({
let s = s.clone(); let s = s.clone();
move |_| { move |_| {
let no_window: Option<&gtk::Window> = None; let no_window: Option<&gtk::Window> = None;
let not_cancellable: Option<&gio::Cancellable> = None; let not_cancellable: Option<&gio::Cancellable> = None;
let s = s.clone(); let s = s.clone();
let on_selected = on_selected.clone();
gtk::FileDialog::builder().build().open( gtk::FileDialog::builder().build().open(
no_window, no_window,
not_cancellable, not_cancellable,
@ -70,6 +79,7 @@ impl FileChooserRow {
Ok(file_id) => match file_id.path() { Ok(file_id) => match file_id.path() {
Some(path) => { Some(path) => {
s.imp().label.set_text(path.to_str().unwrap()); s.imp().label.set_text(path.to_str().unwrap());
on_selected(path.clone());
*s.imp().path.borrow_mut() = Some(path); *s.imp().path.borrow_mut() = Some(path);
} }
None => { None => {
@ -88,4 +98,8 @@ impl FileChooserRow {
s s
} }
pub fn path(&self) -> Option<PathBuf> {
self.imp().path.borrow().clone()
}
} }