diff options
Diffstat (limited to 'src/gui/search.rs')
| -rw-r--r-- | src/gui/search.rs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/gui/search.rs b/src/gui/search.rs new file mode 100644 index 0000000..a1c6ff3 --- /dev/null +++ b/src/gui/search.rs @@ -0,0 +1,133 @@ +use gtk::gdk::keys::constants::Return as RETURN; +use gtk::glib; +use gtk::prelude::*; +use super::state::{View, ViewManager}; +use std::rc::Rc; +use std::thread; + +pub struct Search { + vm : Rc<ViewManager> +} + +impl View for Search { + fn name(&self) -> &str { + "search" + } + + fn set_vm(&mut self, vm : Rc<ViewManager>) { + self.vm = vm + } + + fn make_current(&self) -> Option<gtk::Box> { + let main = gtk::Box::new(gtk::Orientation::Vertical, 0); + let scroll = gtk::ScrolledWindow::new(gtk::Adjustment::NONE, gtk::Adjustment::NONE); + let search = gtk::SearchEntry::new(); + let progress = gtk::ProgressBar::new(); + search.set_widget_name("search_entry"); + main.pack_start(&search, false, false, 0); + main.pack_start(&progress, false, false, 0); + let list = gtk::ListBox::new(); + scroll.add(&list); + + let empty_container = gtk::Box::new(gtk::Orientation::Vertical, 0); + + let bt = include_bytes!("icon.svg"); + let loader = gtk::gdk_pixbuf::PixbufLoader::new(); + loader.write(bt).ok(); + loader.set_size(200, 200); + loader.close().ok(); + let pixbuf = loader.pixbuf().unwrap(); + let image = gtk::Image::from_pixbuf(Some(&pixbuf)); + + empty_container.pack_start(&image, true, true, 0); + main.pack_start(&empty_container, true, true, 0); + + let vm = Rc::clone(&self.vm); + search.connect_key_press_event(glib::clone!( + @strong scroll, + @strong list, + @weak progress, + @weak main, + @weak empty_container => @default-return gtk::Inhibit(false), move |entry, event| { + match event.keyval() { + RETURN => { + let query = entry.text().to_string(); + + if query.is_empty() { + main.remove(&scroll); + main.remove(&empty_container); + main.pack_start(&empty_container, true, true, 0); + return gtk::Inhibit(false); + } + + let (tx, rx) = glib::MainContext::channel(glib::Priority::default()); + let (status_tx, status_rx) = glib::MainContext::channel(glib::Priority::default()); + + let index = vm.get_index(); + thread::spawn(move || { + let searchvec = crate::splitter::split_to_words(query); + let results = index.lock().unwrap().search(searchvec, |p| { + status_tx.send(p).ok(); + }); + tx.send(results).ok(); + }); + + status_rx.attach(None, glib::clone!( + @weak progress => @default-return glib::Continue(true), move |p| { + progress.set_fraction(f64::from(p) / 100.0); + + if p == 100 { + glib::Continue(false) + } else { + glib::Continue(true) + } + })); + + rx.attach(None, glib::clone!( + @weak progress, + @weak list, + @weak scroll => @default-return glib::Continue(false), move |results| { + main.remove(&scroll); + main.remove(&empty_container); + + progress.set_fraction(0.0); + + if results.is_empty() { + main.pack_start(&empty_container, true, true, 0); + return glib::Continue(false); + } else { + for child in list.children() { + list.remove(&child); + } + + for result in results.iter().rev().take(1000) { + let entry = gtk::Box::new(gtk::Orientation::Horizontal, 0); + entry.set_margin(10); + let path_label = gtk::Label::new(Some(&result.path)); + let prio_label = gtk::Label::new(Some(&result.priority.to_string())); + entry.pack_start(&prio_label, false, false, 10); + entry.pack_start(&path_label, true, true, 10); + list.prepend(&entry) + } + + main.pack_start(&scroll, true, true, 0); + } + main.show_all(); + + glib::Continue(false) + })); + } + _ => {} + } + gtk::Inhibit(false) + })); + + Some(main) + } +} + +impl Search { + pub fn new() -> Self { + Self { vm : Rc::new(ViewManager::empty()) } + } +} |