From edebb8b673cccc33371f1e1f2074617c437614e3 Mon Sep 17 00:00:00 2001 From: daa84 Date: Wed, 1 Nov 2017 17:40:54 +0300 Subject: [PATCH] vimawesome search, allow to install vimawesome plugins --- src/plug_manager/manager.rs | 4 +- src/plug_manager/store.rs | 7 +- src/plug_manager/ui.rs | 122 +++++++++++++++++++++++---------- src/plug_manager/vimawesome.rs | 40 ++++++++--- 4 files changed, 122 insertions(+), 51 deletions(-) diff --git a/src/plug_manager/manager.rs b/src/plug_manager/manager.rs index 727cf1a..8b824ff 100644 --- a/src/plug_manager/manager.rs +++ b/src/plug_manager/manager.rs @@ -57,8 +57,8 @@ impl Manager { self.store.clear_removed(); } - pub fn add_plug(&mut self, plug: PlugInfo) { - self.store.add_plug(plug); + pub fn add_plug(&mut self, plug: PlugInfo) -> bool { + self.store.add_plug(plug) } } diff --git a/src/plug_manager/store.rs b/src/plug_manager/store.rs index a9cf6eb..f9e5be5 100644 --- a/src/plug_manager/store.rs +++ b/src/plug_manager/store.rs @@ -66,8 +66,13 @@ impl Store { self.settings.plugs[idx].removed = false; } - pub fn add_plug(&mut self, plug: PlugInfo) { + pub fn add_plug(&mut self, plug: PlugInfo) -> bool { + let path = plug.get_plug_path(); + if self.settings.plugs.iter().any(|p| p.get_plug_path() == path || p.name == plug.name) { + return false; + } self.settings.plugs.push(plug); + true } pub fn plugs_count(&self) -> usize { diff --git a/src/plug_manager/ui.rs b/src/plug_manager/ui.rs index 5b88918..c24d430 100644 --- a/src/plug_manager/ui.rs +++ b/src/plug_manager/ui.rs @@ -63,7 +63,10 @@ impl<'a> Ui<'a> { enable_swc.set_state(self.manager.borrow().store.is_enabled()); - let get_plugins = add_get_plugins_tab(&pages); + let plugins = gtk::Box::new(gtk::Orientation::Vertical, 3); + let plugs_panel = self.fill_plugin_list(&plugins, &self.manager.borrow().store); + + add_vimawesome_tab(&pages, &self.manager, &plugs_panel); match self.manager.borrow().plug_manage_state { manager::PlugManageState::Unknown => { @@ -83,7 +86,8 @@ impl<'a> Ui<'a> { manager::PlugManageState::NvimGtk => {} } - let plugs_panel = self.add_plugin_list_tab(&pages, &self.manager.borrow().store); + let plugins_lbl = gtk::Label::new("Plugins"); + pages.add_page(&plugins_lbl, &plugins, "plugins"); let manager_ref = self.manager.clone(); enable_swc.connect_state_set(move |_, state| { @@ -93,29 +97,12 @@ impl<'a> Ui<'a> { let manager_ref = self.manager.clone(); add_plug_btn.connect_clicked(clone!(dlg => move |_| { - add_plugin(&dlg, &manager_ref, &plugs_panel); + show_add_plug_dlg(&dlg, &manager_ref, &plugs_panel); })); content.pack_start(&*pages, true, true, 0); content.show_all(); - let get_plugins = UiMutex::new(get_plugins); - vimawesome::call(move |res| { - let panel = get_plugins.borrow(); - for child in panel.get_children() { - panel.remove(&child); - } - match res { - Ok(list) => { - let result = vimawesome::build_result_panel(&list); - panel.pack_start(&result, true, true, 0); - } - Err(e) => { - panel.pack_start(>k::Label::new(format!("{}", e).as_str()), false, true, 0); - error!("{}", e) - }, - } - }); let ok: i32 = gtk::ResponseType::Ok.into(); if dlg.run() == ok { @@ -127,15 +114,6 @@ impl<'a> Ui<'a> { dlg.destroy(); } - fn add_plugin_list_tab(&self, pages: &SettingsPages, store: &Store) -> gtk::ListBox { - let plugins = gtk::Box::new(gtk::Orientation::Vertical, 3); - let plugs_panel = self.fill_plugin_list(&plugins, store); - - let plugins_lbl = gtk::Label::new("Plugins"); - pages.add_page(&plugins_lbl, &plugins, "plugins"); - plugs_panel - } - fn fill_plugin_list(&self, panel: >k::Box, store: &Store) -> gtk::ListBox { let scroll = gtk::ScrolledWindow::new(None, None); scroll.get_style_context().map(|c| c.add_class("view")); @@ -154,6 +132,34 @@ impl<'a> Ui<'a> { } } +fn populate_get_plugins( + query: Option, + get_plugins: >k::Box, + manager: Arc>, + plugs_panel: gtk::ListBox, +) { + let plugs_panel = UiMutex::new(plugs_panel); + let get_plugins = UiMutex::new(get_plugins.clone()); + vimawesome::call(query, move |res| { + let panel = get_plugins.borrow(); + for child in panel.get_children() { + panel.remove(&child); + } + match res { + Ok(list) => { + let result = vimawesome::build_result_panel(&list, move |new_plug| { + add_plugin(&manager, &*plugs_panel.borrow(), new_plug); + }); + panel.pack_start(&result, true, true, 0); + } + Err(e) => { + panel.pack_start(>k::Label::new(format!("{}", e).as_str()), false, true, 0); + error!("{}", e) + } + } + }); +} + fn create_plug_row( plug_idx: usize, plug_info: &PlugInfo, @@ -208,17 +214,38 @@ fn create_plug_row( row } -fn add_plugin>( +fn show_add_plug_dlg>( parent: &F, manager: &Arc>, plugs_panel: >k::ListBox, ) { if let Some(new_plugin) = plugin_settings_dlg::Builder::new("Add plugin").show(parent) { - let row = create_plug_row(manager.borrow().store.plugs_count(), &new_plugin, manager); + add_plugin(manager, plugs_panel, new_plugin); + } +} + +fn add_plugin( + manager: &Arc>, + plugs_panel: >k::ListBox, + new_plugin: PlugInfo, +) -> bool { + let row = create_plug_row(manager.borrow().store.plugs_count(), &new_plugin, manager); + + if manager.borrow_mut().add_plug(new_plugin) { row.show_all(); plugs_panel.add(&row); - - manager.borrow_mut().add_plug(new_plugin); + true + } else { + let dlg = gtk::MessageDialog::new( + None::<>k::Window>, + gtk::DialogFlags::empty(), + gtk::MessageType::Error, + gtk::ButtonsType::Ok, + "Plugin with this name or path already exists", + ); + dlg.run(); + dlg.destroy(); + false } } @@ -237,7 +264,11 @@ fn create_plug_label(plug_info: &PlugInfo) -> gtk::Box { label_box } -fn add_get_plugins_tab(pages: &SettingsPages) -> gtk::Box { +fn add_vimawesome_tab( + pages: &SettingsPages, + manager: &Arc>, + plugs_panel: >k::ListBox, +) { let get_plugins = gtk::Box::new(gtk::Orientation::Vertical, 0); let spinner = gtk::Spinner::new(); let get_plugins_lbl = gtk::Label::new("Get Plugins"); @@ -245,13 +276,30 @@ fn add_get_plugins_tab(pages: &SettingsPages) -> gtk::Box { let list_panel = gtk::Box::new(gtk::Orientation::Vertical, 0); let link_button = gtk::Label::new(None); - link_button.set_markup("Plugins source: https://vimawesome.com"); - get_plugins.pack_start(&link_button, false, true, 15); + link_button.set_markup( + "Plugins are taken from: https://vimawesome.com", + ); + let search_entry = gtk::Entry::new(); + search_entry.set_icon_from_icon_name(gtk::EntryIconPosition::Primary, "edit-find"); + + get_plugins.pack_start(&link_button, false, true, 10); + get_plugins.pack_start(&search_entry, false, true, 5); get_plugins.pack_start(&list_panel, true, true, 0); list_panel.pack_start(&spinner, true, true, 0); spinner.start(); - list_panel + search_entry.connect_activate(clone!(list_panel, manager, plugs_panel => move |se| { + let spinner = gtk::Spinner::new(); + list_panel.pack_start(&spinner, false, true, 5); + spinner.show(); + spinner.start(); + populate_get_plugins(se.get_text(), &list_panel, manager.clone(), plugs_panel.clone()); + })); + + gtk::idle_add(clone!(manager, plugs_panel => move || { + populate_get_plugins(None, &list_panel, manager.clone(), plugs_panel.clone()); + Continue(false) + })); } fn add_help_tab(pages: &SettingsPages, markup: &str) { diff --git a/src/plug_manager/vimawesome.rs b/src/plug_manager/vimawesome.rs index 7bc8819..82497cc 100644 --- a/src/plug_manager/vimawesome.rs +++ b/src/plug_manager/vimawesome.rs @@ -1,5 +1,6 @@ use std::io; use std::thread; +use std::rc::Rc; use std::process::{Command, Stdio}; use serde_json; @@ -8,23 +9,28 @@ use gtk; use gtk::prelude::*; use glib; -pub fn call(cb: F) +use super::store::PlugInfo; + +pub fn call(query: Option, cb: F) where F: FnOnce(io::Result) + Send + 'static, { thread::spawn(move || { let mut cb = Some(cb); glib::idle_add(move || { - cb.take().unwrap()(request()); - glib::Continue(false) + cb.take().unwrap()(request(query.as_ref().map(|s| s.as_ref()))); + Continue(false) }) }); } -fn request() -> io::Result { +fn request(query: Option<&str>) -> io::Result { let child = Command::new("curl") .arg("-s") - .arg("https://vimawesome.com/api/plugins?query=&page=1") + .arg(format!( + "https://vimawesome.com/api/plugins?query={}&page=1", + query.unwrap_or("") + )) .stdout(Stdio::piped()) .spawn()?; @@ -49,13 +55,17 @@ fn request() -> io::Result { } } -pub fn build_result_panel(list: &DescriptionList) -> gtk::ScrolledWindow { +pub fn build_result_panel( + list: &DescriptionList, + add_cb: F, +) -> gtk::ScrolledWindow { let scroll = gtk::ScrolledWindow::new(None, None); scroll.get_style_context().map(|c| c.add_class("view")); let panel = gtk::ListBox::new(); + let cb_ref = Rc::new(add_cb); for plug in list.plugins.iter() { - let row = create_plug_row(plug); + let row = create_plug_row(plug, cb_ref.clone()); panel.add(&row); } @@ -65,7 +75,10 @@ pub fn build_result_panel(list: &DescriptionList) -> gtk::ScrolledWindow { scroll } -fn create_plug_row(plug: &Description) -> gtk::ListBoxRow { +fn create_plug_row( + plug: &Description, + add_cb: Rc, +) -> gtk::ListBoxRow { let row = gtk::ListBoxRow::new(); let row_container = gtk::Box::new(gtk::Orientation::Vertical, 5); row_container.set_border_width(5); @@ -86,7 +99,12 @@ fn create_plug_row(plug: &Description) -> gtk::ListBoxRow { row.add(&row_container); - add_btn.connect_clicked(clone!(button_box => move |_| { })); + add_btn.connect_clicked(clone!(plug => move |btn| { + if let Some(ref github_url) = plug.github_url { + btn.set_sensitive(false); + add_cb(PlugInfo::new(plug.name.clone(), github_url.clone())); + } + })); row } @@ -116,12 +134,12 @@ fn create_plug_label(plug: &Description) -> gtk::Box { label_box } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Deserialize, Debug)] pub struct DescriptionList { pub plugins: Box<[Description]>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Deserialize, Debug, Clone)] pub struct Description { pub name: String, pub github_url: Option,