From 41f27e654b578bb90e03a85fd21d6c6233e4f5e6 Mon Sep 17 00:00:00 2001 From: yggverse Date: Fri, 7 Feb 2025 15:30:54 +0200 Subject: [PATCH] implement file dialog --- .../window/tab/item/page/input/titan/file.rs | 65 +++++++++++++++++-- .../tab/item/page/input/titan/file/control.rs | 40 ++++++++---- .../page/input/titan/file/control/counter.rs | 12 ++-- 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/src/app/browser/window/tab/item/page/input/titan/file.rs b/src/app/browser/window/tab/item/page/input/titan/file.rs index 313c8c90..908db675 100644 --- a/src/app/browser/window/tab/item/page/input/titan/file.rs +++ b/src/app/browser/window/tab/item/page/input/titan/file.rs @@ -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 } } diff --git a/src/app/browser/window/tab/item/page/input/titan/file/control.rs b/src/app/browser/window/tab/item/page/input/titan/file/control.rs index 2e61a1a5..9d8b8254 100644 --- a/src/app/browser/window/tab/item/page/input/titan/file/control.rs +++ b/src/app/browser/window/tab/item/page/input/titan/file/control.rs @@ -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>) -> Self; +pub struct Control { + counter: Label, + options: Button, + upload: Button, + pub g_box: Box, } -impl Control for Box { - fn control(header: &Rc>) -> Self { - use counter::Counter; - use gtk::{Button, Label}; - use options::Options; - use upload::Upload; - +impl Control { + pub fn build(header: &Rc>) -> 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) { + 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); + } } diff --git a/src/app/browser/window/tab/item/page/input/titan/file/control/counter.rs b/src/app/browser/window/tab/item/page/input/titan/file/control/counter.rs index 72c08b8f..e30c83c1 100644 --- a/src/app/browser/window/tab/item/page/input/titan/file/control/counter.rs +++ b/src/app/browser/window/tab/item/page/input/titan/file/control/counter.rs @@ -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); } 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) { + 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