implement file dialog

This commit is contained in:
yggverse 2025-02-07 15:30:54 +02:00
parent a8f3e4fe2e
commit 41f27e654b
3 changed files with 93 additions and 24 deletions

View file

@ -2,6 +2,7 @@ mod control;
mod form;
use super::Header;
use control::Control;
use gtk::Box;
pub trait File {
@ -10,9 +11,12 @@ pub trait File {
impl File for Box {
fn file() -> Self {
use control::Control;
use form::Form;
use gtk::Button;
use gtk::{
gio::Cancellable,
prelude::{ButtonExt, FileExt, WidgetExt},
Button, FileDialog, Window,
};
use std::{cell::Cell, rc::Rc};
// Init components
@ -20,11 +24,11 @@ impl File for Box {
mime: None,
token: None,
}));
let control = Box::control(&header);
let control = Rc::new(Control::build(&header));
let form = Button::form();
// Init main widget
{
let g_box = {
use gtk::{prelude::BoxExt, Orientation};
const MARGIN: i32 = 8;
@ -38,8 +42,57 @@ impl File for Box {
.build();
g_box.append(&form);
g_box.append(&control);
g_box.append(&control.g_box);
g_box
}
};
// Init events
form.connect_clicked(move |form| {
const CLASS: (&str, &str, &str) = ("error", "warning", "success");
// reset
control.update(None);
form.set_sensitive(false);
form.remove_css_class(CLASS.0);
form.remove_css_class(CLASS.1);
form.remove_css_class(CLASS.2);
FileDialog::builder()
.build()
.open(Window::NONE, Cancellable::NONE, {
let control = control.clone();
let form = form.clone();
move |result| match result {
Ok(file) => match file.path() {
Some(path) => {
form.set_label("Buffering, please wait..");
file.load_bytes_async(Cancellable::NONE, move |result| match result
{
Ok((bytes, _)) => {
control.update(Some(bytes.len()));
form.set_label(path.to_str().unwrap());
form.set_css_classes(&[CLASS.2]);
form.set_sensitive(true);
}
Err(e) => {
form.set_css_classes(&[CLASS.0]);
form.set_label(e.message());
form.set_sensitive(true);
}
})
}
None => todo!(),
},
Err(e) => {
form.set_css_classes(&[CLASS.1]);
form.set_label(e.message());
form.set_sensitive(true);
}
}
});
});
g_box
}
}

View file

@ -3,27 +3,28 @@ mod options;
mod upload;
use super::Header;
use gtk::Box;
use counter::Counter;
use gtk::{Box, Button, Label};
use options::Options;
use std::{cell::Cell, rc::Rc};
use upload::Upload;
pub trait Control {
fn control(header: &Rc<Cell<Header>>) -> Self;
pub struct Control {
counter: Label,
options: Button,
upload: Button,
pub g_box: Box,
}
impl Control for Box {
fn control(header: &Rc<Cell<Header>>) -> Self {
use counter::Counter;
use gtk::{Button, Label};
use options::Options;
use upload::Upload;
impl Control {
pub fn build(header: &Rc<Cell<Header>>) -> Self {
// Init components
let counter = Label::counter();
let options = Button::options(header);
let upload = Button::upload();
// Init main widget
{
let g_box = {
use gtk::{prelude::BoxExt, Align, Orientation};
let g_box = Box::builder()
.halign(Align::End)
@ -35,6 +36,23 @@ impl Control for Box {
g_box.append(&options);
g_box.append(&upload);
g_box
};
Self {
counter,
options,
upload,
g_box,
}
}
pub fn update(&self, bytes_total: Option<usize>) {
use gtk::prelude::WidgetExt;
self.counter.update(bytes_total);
let is_some = bytes_total.is_some();
self.options.set_sensitive(is_some);
self.upload.set_sensitive(is_some);
}
}

View file

@ -1,9 +1,8 @@
use gtk::{prelude::WidgetExt, Label};
use plurify::Plurify;
pub trait Counter {
fn counter() -> Self;
fn update(&self, bytes_total: usize);
fn update(&self, bytes_total: Option<usize>);
}
impl Counter for Label {
@ -15,11 +14,10 @@ impl Counter for Label {
// Actions
fn update(&self, bytes_total: usize) {
self.set_visible(if bytes_total > 0 {
let format = bytes_total.plurify(&["byte", "bytes", "bytes"]);
self.set_label(format);
self.set_tooltip_text(Some(format));
fn update(&self, bytes_total: Option<usize>) {
self.set_visible(if let Some(bytes_total) = bytes_total {
use crate::tool::Format;
self.set_tooltip_text(Some(&bytes_total.bytes()));
true
} else {
false