From e6760885c493ca70258b364c77c2460b2a142ae0 Mon Sep 17 00:00:00 2001 From: Joakim Soderlund Date: Sat, 17 Aug 2019 23:14:19 +0200 Subject: [PATCH] Add minimal functionality glue --- .gitignore | 1 + Cargo.toml | 5 ++ gtk/src/components/app.rs | 82 +++++++++++++++++++ gtk/src/components/app.ui | 160 ++++++++++++++++++++++++++++++++++++++ gtk/src/components/mod.rs | 5 ++ gtk/src/main.rs | 19 ++++- 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 gtk/src/components/app.rs create mode 100644 gtk/src/components/app.ui create mode 100644 gtk/src/components/mod.rs diff --git a/.gitignore b/.gitignore index 53eaa21..93a9d35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target **/*.rs.bk +**/*~ diff --git a/Cargo.toml b/Cargo.toml index c18a812..fd7c50b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,11 @@ members = [ "gtk", ] +default-members = [ + "cli", + "gtk", +] + [profile.release] lto = true diff --git a/gtk/src/components/app.rs b/gtk/src/components/app.rs new file mode 100644 index 0000000..567a757 --- /dev/null +++ b/gtk/src/components/app.rs @@ -0,0 +1,82 @@ +//! Application window. + +use std::fs::File; +use std::io::BufReader; +use std::rc::Rc; +use std::sync::Mutex; + +use gtk::*; + +use fimfareader::archive::Fetcher; +use fimfareader::archive::Story; +use fimfareader::query::parse; + +pub struct AppWindow { + fetcher: Fetcher>, + window: ApplicationWindow, + search: ToggleButton, + result: Mutex, + entry: Entry, +} + +impl AppWindow { + pub fn new(fetcher: Fetcher>) -> Option> { + let ui = include_str!("app.ui"); + let builder = Builder::new_from_string(ui); + + let this = Rc::new(Self { + fetcher: fetcher, + window: builder.get_object("app")?, + search: builder.get_object("search")?, + result: Mutex::new(builder.get_object("result")?), + entry: builder.get_object("entry")?, + }); + + this.apply(this.fetcher.iter().collect()); + Some(Self::connect(this)) + } + + fn connect(self: Rc) -> Rc { + self.window.connect_destroy(move |_| gtk::main_quit()); + + let clone = self.clone(); + self.entry.connect_activate(move |entry| { + let text = entry.get_text().unwrap(); + clone.filter(text.as_str().trim()); + }); + + self + } + + fn apply(&self, stories: Vec<&Story>) { + let store = ListStore::new(&[ + i64::static_type(), + String::static_type(), + String::static_type(), + ]); + + for (i, story) in stories.iter().enumerate() { + store.insert_with_values( + Some(i as u32), + &[0, 1, 2], + &[&story.id, &story.title, &story.author.name], + ); + } + + let result = self.result.lock().unwrap(); + result.set_model(Some(&store)); + } + + pub fn filter(&self, query: &str) { + let filter = parse(query); + + if filter.is_err() { + return; + } + + let filter = filter.unwrap(); + let vector = self.fetcher.filter(&filter); + + self.apply(vector); + } +} diff --git a/gtk/src/components/app.ui b/gtk/src/components/app.ui new file mode 100644 index 0000000..0f1ae8d --- /dev/null +++ b/gtk/src/components/app.ui @@ -0,0 +1,160 @@ + + + + + + + + + + + 800 + 600 + True + False + application-archive + + + True + False + True + + + 500 + True + True + True + none + False + search-symbolic + Search... + + + + + True + True + False + True + + + True + False + open-menu-symbolic + + + + + end + 1 + + + + + True + False + True + + + True + False + gtk-find + + + + + end + 2 + + + + + + + True + True + in + + + True + True + False + False + + + + + + True + fixed + 100 + 75 + 200 + ID + + + + 0 + + + + + + + True + fixed + 300 + 100 + 400 + Title + + + + 1 + + + + + + + True + autosize + 300 + 100 + 500 + Author + + + + 2 + + + + + + + + + + diff --git a/gtk/src/components/mod.rs b/gtk/src/components/mod.rs new file mode 100644 index 0000000..e4a8daf --- /dev/null +++ b/gtk/src/components/mod.rs @@ -0,0 +1,5 @@ +// UI module. + +mod app; + +pub use self::app::AppWindow; diff --git a/gtk/src/main.rs b/gtk/src/main.rs index 74783fe..bb83a8d 100644 --- a/gtk/src/main.rs +++ b/gtk/src/main.rs @@ -2,6 +2,23 @@ use fimfareader::prelude::*; +use components::AppWindow; + +mod components; + fn main() -> Result<()> { - Err(Error::usage("Not implemented")) + gtk::init().map_err(|e| match e { + _ => Error::usage("Could not initialize GTK"), + })?; + + let fetcher = Fetcher::from("fimfarchive.zip")?; + + let _window = match AppWindow::new(fetcher) { + Some(window) => Ok(window), + None => Err(Error::usage("Could not create main window")), + }?; + + gtk::main(); + + Ok(()) }