Added max_entries
to limit amount of total entries
This commit is contained in:
@@ -25,6 +25,7 @@ struct Config {
|
|||||||
hide_plugin_info: bool,
|
hide_plugin_info: bool,
|
||||||
ignore_exclusive_zones: bool,
|
ignore_exclusive_zones: bool,
|
||||||
close_on_click: bool,
|
close_on_click: bool,
|
||||||
|
max_entries: Option<usize>,
|
||||||
layer: Layer,
|
layer: Layer,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ impl Default for Config {
|
|||||||
hide_plugin_info: false,
|
hide_plugin_info: false,
|
||||||
ignore_exclusive_zones: false,
|
ignore_exclusive_zones: false,
|
||||||
close_on_click: false,
|
close_on_click: false,
|
||||||
|
max_entries: None,
|
||||||
layer: Layer::Overlay,
|
layer: Layer::Overlay,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +76,6 @@ struct PluginView {
|
|||||||
|
|
||||||
struct Args {
|
struct Args {
|
||||||
override_plugins: Option<Vec<String>>,
|
override_plugins: Option<Vec<String>>,
|
||||||
config_dir: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@@ -96,6 +97,10 @@ struct RuntimeData {
|
|||||||
exclusive: Option<PluginView>,
|
exclusive: Option<PluginView>,
|
||||||
plugins: Vec<PluginView>,
|
plugins: Vec<PluginView>,
|
||||||
post_run_action: PostRunAction,
|
post_run_action: PostRunAction,
|
||||||
|
config: Config,
|
||||||
|
/// Used for displaying errors later on
|
||||||
|
error_label: String,
|
||||||
|
config_dir: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The naming scheme for CSS styling
|
/// The naming scheme for CSS styling
|
||||||
@@ -148,14 +153,49 @@ fn main() {
|
|||||||
let override_plugins = dict.lookup::<Vec<String>>("override-plugins").unwrap();
|
let override_plugins = dict.lookup::<Vec<String>>("override-plugins").unwrap();
|
||||||
let config_dir = dict.lookup::<String>("config-dir").unwrap();
|
let config_dir = dict.lookup::<String>("config-dir").unwrap();
|
||||||
|
|
||||||
|
// Figure out the config dir
|
||||||
|
let user_dir = format!(
|
||||||
|
"{}/.config/anyrun",
|
||||||
|
env::var("HOME").expect("Could not determine home directory! Is $HOME set?")
|
||||||
|
);
|
||||||
|
let config_dir = config_dir.unwrap_or_else(|| {
|
||||||
|
if PathBuf::from(&user_dir).exists() {
|
||||||
|
user_dir
|
||||||
|
} else {
|
||||||
|
DEFAULT_CONFIG_DIR.to_string()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load config, if unable to then read default config. If an error occurs the message will be displayed.
|
||||||
|
let (config, error_label) = match fs::read_to_string(format!("{}/config.ron", config_dir)) {
|
||||||
|
Ok(content) => ron::from_str(&content)
|
||||||
|
.map(|config| (config, String::new()))
|
||||||
|
.unwrap_or_else(|why| {
|
||||||
|
(
|
||||||
|
Config::default(),
|
||||||
|
format!(
|
||||||
|
"Failed to parse Anyrun config file, using default config: {}",
|
||||||
|
why
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
Err(why) => (
|
||||||
|
Config::default(),
|
||||||
|
format!(
|
||||||
|
"Failed to read Anyrun config file, using default config: {}",
|
||||||
|
why
|
||||||
|
),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
*runtime_data_clone.borrow_mut() = Some(RuntimeData {
|
*runtime_data_clone.borrow_mut() = Some(RuntimeData {
|
||||||
args: Args {
|
args: Args { override_plugins },
|
||||||
override_plugins,
|
|
||||||
config_dir,
|
|
||||||
},
|
|
||||||
exclusive: None,
|
exclusive: None,
|
||||||
plugins: Vec::new(),
|
plugins: Vec::new(),
|
||||||
post_run_action: PostRunAction::None,
|
post_run_action: PostRunAction::None,
|
||||||
|
error_label,
|
||||||
|
config,
|
||||||
|
config_dir,
|
||||||
});
|
});
|
||||||
-1 // Magic GTK number to continue running
|
-1 // Magic GTK number to continue running
|
||||||
});
|
});
|
||||||
@@ -193,42 +233,6 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>>>) {
|
fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>>>) {
|
||||||
// Figure out the config dir
|
|
||||||
let user_dir = format!(
|
|
||||||
"{}/.config/anyrun",
|
|
||||||
env::var("HOME").expect("Could not determine home directory! Is $HOME set?")
|
|
||||||
);
|
|
||||||
let config_dir =
|
|
||||||
if let Some(config_dir) = &runtime_data.borrow().as_ref().unwrap().args.config_dir {
|
|
||||||
config_dir.clone()
|
|
||||||
} else if PathBuf::from(&user_dir).exists() {
|
|
||||||
user_dir
|
|
||||||
} else {
|
|
||||||
DEFAULT_CONFIG_DIR.to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load config, if unable to then read default config. If an error occurs the message will be displayed.
|
|
||||||
let (config, error_label) = match fs::read_to_string(format!("{}/config.ron", config_dir)) {
|
|
||||||
Ok(content) => ron::from_str(&content)
|
|
||||||
.map(|config| (config, None))
|
|
||||||
.unwrap_or_else(|why| {
|
|
||||||
(
|
|
||||||
Config::default(),
|
|
||||||
Some(format!(
|
|
||||||
"Failed to parse Anyrun config file, using default config: {}",
|
|
||||||
why
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
Err(why) => (
|
|
||||||
Config::default(),
|
|
||||||
Some(format!(
|
|
||||||
"Failed to read Anyrun config file, using default config: {}",
|
|
||||||
why
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the main window
|
// Create the main window
|
||||||
let window = gtk::ApplicationWindow::builder()
|
let window = gtk::ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
@@ -246,13 +250,19 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
|
|
||||||
gtk_layer_shell::set_namespace(&window, "anyrun");
|
gtk_layer_shell::set_namespace(&window, "anyrun");
|
||||||
|
|
||||||
if config.ignore_exclusive_zones {
|
if runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config
|
||||||
|
.ignore_exclusive_zones
|
||||||
|
{
|
||||||
gtk_layer_shell::set_exclusive_zone(&window, -1);
|
gtk_layer_shell::set_exclusive_zone(&window, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_layer_shell::set_keyboard_mode(&window, gtk_layer_shell::KeyboardMode::Exclusive);
|
gtk_layer_shell::set_keyboard_mode(&window, gtk_layer_shell::KeyboardMode::Exclusive);
|
||||||
|
|
||||||
match config.layer {
|
match runtime_data.borrow().as_ref().unwrap().config.layer {
|
||||||
Layer::Background => {
|
Layer::Background => {
|
||||||
gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background)
|
gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background)
|
||||||
}
|
}
|
||||||
@@ -263,7 +273,10 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
|
|
||||||
// Try to load custom CSS, if it fails load the default CSS
|
// Try to load custom CSS, if it fails load the default CSS
|
||||||
let provider = gtk::CssProvider::new();
|
let provider = gtk::CssProvider::new();
|
||||||
if let Err(why) = provider.load_from_path(&format!("{}/style.css", config_dir)) {
|
if let Err(why) = provider.load_from_path(&format!(
|
||||||
|
"{}/style.css",
|
||||||
|
runtime_data.borrow().as_ref().unwrap().config_dir
|
||||||
|
)) {
|
||||||
eprintln!("Failed to load custom CSS: {}", why);
|
eprintln!("Failed to load custom CSS: {}", why);
|
||||||
provider
|
provider
|
||||||
.load_from_data(include_bytes!("../res/style.css"))
|
.load_from_data(include_bytes!("../res/style.css"))
|
||||||
@@ -284,7 +297,13 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
.override_plugins
|
.override_plugins
|
||||||
{
|
{
|
||||||
Some(plugins) => plugins.iter().map(PathBuf::from).collect(),
|
Some(plugins) => plugins.iter().map(PathBuf::from).collect(),
|
||||||
None => config.plugins,
|
None => runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config
|
||||||
|
.plugins
|
||||||
|
.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure at least one plugin is specified
|
// Make sure at least one plugin is specified
|
||||||
@@ -306,7 +325,11 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
};
|
};
|
||||||
|
|
||||||
plugin_paths.append(&mut vec![
|
plugin_paths.append(&mut vec![
|
||||||
format!("{}/plugins", config_dir).into(),
|
format!(
|
||||||
|
"{}/plugins",
|
||||||
|
runtime_data.borrow().as_ref().unwrap().config_dir
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
format!("{}/plugins", DEFAULT_CONFIG_DIR).into(),
|
format!("{}/plugins", DEFAULT_CONFIG_DIR).into(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -315,7 +338,10 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|plugin_path| {
|
.map(|plugin_path| {
|
||||||
// Load the plugin's dynamic library.
|
// Load the plugin's dynamic library.
|
||||||
let mut user_path = PathBuf::from(&format!("{}/plugins", config_dir));
|
let mut user_path = PathBuf::from(&format!(
|
||||||
|
"{}/plugins",
|
||||||
|
runtime_data.borrow().as_ref().unwrap().config_dir
|
||||||
|
));
|
||||||
let mut global_path = PathBuf::from("/etc/anyrun/plugins");
|
let mut global_path = PathBuf::from("/etc/anyrun/plugins");
|
||||||
user_path.extend(plugin_path.iter());
|
user_path.extend(plugin_path.iter());
|
||||||
global_path.extend(plugin_path.iter());
|
global_path.extend(plugin_path.iter());
|
||||||
@@ -341,15 +367,32 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
.expect("Failed to load plugin");
|
.expect("Failed to load plugin");
|
||||||
|
|
||||||
// Run the plugin's init code to init static resources etc.
|
// Run the plugin's init code to init static resources etc.
|
||||||
plugin.init()(config_dir.clone().into());
|
plugin.init()(
|
||||||
|
runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config_dir
|
||||||
|
.clone()
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
let plugin_box = gtk::Box::builder()
|
let plugin_box = gtk::Box::builder()
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.name(style_names::PLUGIN)
|
.name(style_names::PLUGIN)
|
||||||
.build();
|
.build();
|
||||||
if !config.hide_plugin_info {
|
if !runtime_data
|
||||||
plugin_box.add(&create_info_box(&plugin.info()(), config.hide_icons));
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config
|
||||||
|
.hide_plugin_info
|
||||||
|
{
|
||||||
|
plugin_box.add(&create_info_box(
|
||||||
|
&plugin.info()(),
|
||||||
|
runtime_data.borrow().as_ref().unwrap().config.hide_icons,
|
||||||
|
));
|
||||||
plugin_box.add(
|
plugin_box.add(
|
||||||
>k::Separator::builder()
|
>k::Separator::builder()
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
.orientation(gtk::Orientation::Horizontal)
|
||||||
@@ -409,15 +452,13 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
// Refresh the matches when text input changes
|
// Refresh the matches when text input changes
|
||||||
let runtime_data_clone = runtime_data.clone();
|
let runtime_data_clone = runtime_data.clone();
|
||||||
entry.connect_changed(move |entry| {
|
entry.connect_changed(move |entry| {
|
||||||
refresh_matches(
|
refresh_matches(entry.text().to_string(), runtime_data_clone.clone())
|
||||||
entry.text().to_string(),
|
|
||||||
runtime_data_clone.clone(),
|
|
||||||
config.hide_icons,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle other key presses for selection control and all other things that may be needed
|
// Handle other key presses for selection control and all other things that may be needed
|
||||||
let entry_clone = entry.clone();
|
let entry_clone = entry.clone();
|
||||||
|
let runtime_data_clone = runtime_data.clone();
|
||||||
|
|
||||||
window.connect_key_press_event(move |window, event| {
|
window.connect_key_press_event(move |window, event| {
|
||||||
use gdk::keys::constants;
|
use gdk::keys::constants;
|
||||||
match event.keyval() {
|
match event.keyval() {
|
||||||
@@ -429,7 +470,7 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
// Handle selections
|
// Handle selections
|
||||||
constants::Down | constants::Tab | constants::Up => {
|
constants::Down | constants::Tab | constants::Up => {
|
||||||
// Combine all of the matches into a `Vec` to allow for easier handling of the selection
|
// Combine all of the matches into a `Vec` to allow for easier handling of the selection
|
||||||
let combined_matches = runtime_data
|
let combined_matches = runtime_data_clone
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -447,7 +488,7 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
.collect::<Vec<(gtk::ListBoxRow, gtk::ListBox)>>();
|
.collect::<Vec<(gtk::ListBoxRow, gtk::ListBox)>>();
|
||||||
|
|
||||||
// Get the selected match
|
// Get the selected match
|
||||||
let (selected_match, selected_list) = match runtime_data
|
let (selected_match, selected_list) = match runtime_data_clone
|
||||||
.borrow()
|
.borrow()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -515,9 +556,9 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
}
|
}
|
||||||
// Handle when the selected match is "activated"
|
// Handle when the selected match is "activated"
|
||||||
constants::Return => {
|
constants::Return => {
|
||||||
let mut _runtime_data = runtime_data.borrow_mut();
|
let mut _runtime_data_clone = runtime_data_clone.borrow_mut();
|
||||||
|
|
||||||
let (selected_match, plugin_view) = match _runtime_data
|
let (selected_match, plugin_view) = match _runtime_data_clone
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.plugins
|
.plugins
|
||||||
@@ -540,20 +581,17 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
}
|
}
|
||||||
HandleResult::Refresh(exclusive) => {
|
HandleResult::Refresh(exclusive) => {
|
||||||
if exclusive {
|
if exclusive {
|
||||||
_runtime_data.as_mut().unwrap().exclusive = Some(plugin_view.clone());
|
_runtime_data_clone.as_mut().unwrap().exclusive =
|
||||||
|
Some(plugin_view.clone());
|
||||||
} else {
|
} else {
|
||||||
_runtime_data.as_mut().unwrap().exclusive = None;
|
_runtime_data_clone.as_mut().unwrap().exclusive = None;
|
||||||
}
|
}
|
||||||
mem::drop(_runtime_data); // Drop the mutable borrow
|
mem::drop(_runtime_data_clone); // Drop the mutable borrow
|
||||||
refresh_matches(
|
refresh_matches(entry_clone.text().into(), runtime_data_clone.clone());
|
||||||
entry_clone.text().into(),
|
|
||||||
runtime_data.clone(),
|
|
||||||
config.hide_icons,
|
|
||||||
);
|
|
||||||
Inhibit(false)
|
Inhibit(false)
|
||||||
}
|
}
|
||||||
HandleResult::Copy(bytes) => {
|
HandleResult::Copy(bytes) => {
|
||||||
_runtime_data.as_mut().unwrap().post_run_action =
|
_runtime_data_clone.as_mut().unwrap().post_run_action =
|
||||||
PostRunAction::Copy(bytes.into());
|
PostRunAction::Copy(bytes.into());
|
||||||
window.close();
|
window.close();
|
||||||
Inhibit(true)
|
Inhibit(true)
|
||||||
@@ -573,7 +611,13 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
|
|
||||||
// If the option is enabled, close the window when any click is received
|
// If the option is enabled, close the window when any click is received
|
||||||
// that is outside the bounds of the main box
|
// that is outside the bounds of the main box
|
||||||
if config.close_on_click {
|
if runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config
|
||||||
|
.close_on_click
|
||||||
|
{
|
||||||
window.connect_button_press_event(move |window, event| {
|
window.connect_button_press_event(move |window, event| {
|
||||||
if event.window() == window.window() {
|
if event.window() == window.window() {
|
||||||
window.close();
|
window.close();
|
||||||
@@ -586,7 +630,7 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
|
|
||||||
// Create widgets here for proper positioning
|
// Create widgets here for proper positioning
|
||||||
window.connect_configure_event(move |window, event| {
|
window.connect_configure_event(move |window, event| {
|
||||||
let width = match config.width {
|
let width = match runtime_data.borrow().as_ref().unwrap().config.width {
|
||||||
RelativeNum::Absolute(width) => width,
|
RelativeNum::Absolute(width) => width,
|
||||||
RelativeNum::Fraction(fraction) => (event.size().0 as f32 * fraction) as i32,
|
RelativeNum::Fraction(fraction) => (event.size().0 as f32 * fraction) as i32,
|
||||||
};
|
};
|
||||||
@@ -602,16 +646,31 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
main_vbox.add(&entry);
|
main_vbox.add(&entry);
|
||||||
|
|
||||||
// Display the error message
|
// Display the error message
|
||||||
if let Some(error_label) = &error_label {
|
if !runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.error_label
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
main_vbox.add(
|
main_vbox.add(
|
||||||
>k::Label::builder()
|
>k::Label::builder()
|
||||||
.label(&format!(r#"<span foreground="red">{}</span>"#, error_label))
|
.label(&format!(
|
||||||
|
r#"<span foreground="red">{}</span>"#,
|
||||||
|
runtime_data.borrow().as_ref().unwrap().error_label
|
||||||
|
))
|
||||||
.use_markup(true)
|
.use_markup(true)
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertical_offset = match config.vertical_offset {
|
let vertical_offset = match runtime_data
|
||||||
|
.borrow()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.config
|
||||||
|
.vertical_offset
|
||||||
|
{
|
||||||
RelativeNum::Absolute(offset) => offset,
|
RelativeNum::Absolute(offset) => offset,
|
||||||
RelativeNum::Fraction(fraction) => (event.size().1 as f32 * fraction) as i32,
|
RelativeNum::Fraction(fraction) => (event.size().1 as f32 * fraction) as i32,
|
||||||
};
|
};
|
||||||
@@ -619,7 +678,7 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
fixed.put(
|
fixed.put(
|
||||||
&main_vbox,
|
&main_vbox,
|
||||||
(event.size().0 as i32 - width) / 2,
|
(event.size().0 as i32 - width) / 2,
|
||||||
match config.position {
|
match runtime_data.borrow().as_ref().unwrap().config.position {
|
||||||
Position::Top => vertical_offset,
|
Position::Top => vertical_offset,
|
||||||
Position::Center => {
|
Position::Center => {
|
||||||
(event.size().1 as i32 - entry.allocated_height()) / 2 + vertical_offset
|
(event.size().1 as i32 - entry.allocated_height()) / 2 + vertical_offset
|
||||||
@@ -640,12 +699,7 @@ fn activate(app: >k::Application, runtime_data: Rc<RefCell<Option<RuntimeData>
|
|||||||
window.show_all();
|
window.show_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_matches(
|
fn handle_matches(plugin_view: PluginView, runtime_data: &RuntimeData, matches: RVec<Match>) {
|
||||||
plugin_view: PluginView,
|
|
||||||
runtime_data: Rc<RefCell<Option<RuntimeData>>>,
|
|
||||||
matches: RVec<Match>,
|
|
||||||
hide_icons: bool,
|
|
||||||
) {
|
|
||||||
// Clear out the old matches from the list
|
// Clear out the old matches from the list
|
||||||
for widget in plugin_view.list.children() {
|
for widget in plugin_view.list.children() {
|
||||||
plugin_view.list.remove(&widget);
|
plugin_view.list.remove(&widget);
|
||||||
@@ -664,7 +718,7 @@ fn handle_matches(
|
|||||||
.name(style_names::MATCH)
|
.name(style_names::MATCH)
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
if !hide_icons {
|
if !runtime_data.config.hide_icons {
|
||||||
if let ROption::RSome(icon) = &_match.icon {
|
if let ROption::RSome(icon) = &_match.icon {
|
||||||
let mut builder = gtk::Image::builder()
|
let mut builder = gtk::Image::builder()
|
||||||
.name(style_names::MATCH)
|
.name(style_names::MATCH)
|
||||||
@@ -742,23 +796,32 @@ fn handle_matches(
|
|||||||
plugin_view.row.show_all();
|
plugin_view.row.show_all();
|
||||||
|
|
||||||
let combined_matches = runtime_data
|
let combined_matches = runtime_data
|
||||||
.borrow()
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.plugins
|
.plugins
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|view| {
|
.flat_map(|view| {
|
||||||
view.list.children().into_iter().map(|child| {
|
view.list
|
||||||
(
|
.children()
|
||||||
child.dynamic_cast::<gtk::ListBoxRow>().unwrap(),
|
.into_iter()
|
||||||
view.list.clone(),
|
.map(move |child| (child.dynamic_cast::<gtk::ListBoxRow>().unwrap(), view))
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<(gtk::ListBoxRow, gtk::ListBox)>>();
|
.collect::<Vec<(gtk::ListBoxRow, &PluginView)>>();
|
||||||
|
|
||||||
if let Some((row, list)) = combined_matches.get(0) {
|
// If `max_entries` is set, truncate the amount of entries
|
||||||
list.select_row(Some(row));
|
if let Some(max_matches) = runtime_data.config.max_entries {
|
||||||
|
for (row, view) in combined_matches.iter().skip(max_matches) {
|
||||||
|
view.list.remove(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the plugins that no longer have any entries
|
||||||
|
for (_, view) in &combined_matches {
|
||||||
|
if view.list.children().is_empty() {
|
||||||
|
view.row.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((row, view)) = combined_matches.get(0) {
|
||||||
|
view.list.select_row(Some(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,45 +871,34 @@ fn create_info_box(info: &PluginInfo, hide_icons: bool) -> gtk::Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Refresh the matches from the plugins
|
/// Refresh the matches from the plugins
|
||||||
fn refresh_matches(
|
fn refresh_matches(input: String, runtime_data: Rc<RefCell<Option<RuntimeData>>>) {
|
||||||
input: String,
|
|
||||||
runtime_data: Rc<RefCell<Option<RuntimeData>>>,
|
|
||||||
hide_icons: bool,
|
|
||||||
) {
|
|
||||||
for plugin_view in runtime_data.borrow().as_ref().unwrap().plugins.iter() {
|
for plugin_view in runtime_data.borrow().as_ref().unwrap().plugins.iter() {
|
||||||
let id = plugin_view.plugin.get_matches()(input.clone().into());
|
let id = plugin_view.plugin.get_matches()(input.clone().into());
|
||||||
let plugin_view = plugin_view.clone();
|
let plugin_view = plugin_view.clone();
|
||||||
let runtime_data_clone = runtime_data.clone();
|
let runtime_data_clone = runtime_data.clone();
|
||||||
// If the input is empty, skip getting matches and just clear everything out.
|
// If the input is empty, skip getting matches and just clear everything out.
|
||||||
if input.is_empty() {
|
if input.is_empty() {
|
||||||
handle_matches(plugin_view, runtime_data_clone, RVec::new(), hide_icons);
|
handle_matches(
|
||||||
|
plugin_view,
|
||||||
|
runtime_data.borrow().as_ref().unwrap(),
|
||||||
|
RVec::new(),
|
||||||
|
);
|
||||||
// If a plugin has requested exclusivity, respect it
|
// If a plugin has requested exclusivity, respect it
|
||||||
} else if let Some(exclusive) = &runtime_data.borrow().as_ref().unwrap().exclusive {
|
} else if let Some(exclusive) = &runtime_data.borrow().as_ref().unwrap().exclusive {
|
||||||
if plugin_view.plugin.info() == exclusive.plugin.info() {
|
if plugin_view.plugin.info() == exclusive.plugin.info() {
|
||||||
glib::timeout_add_local(Duration::from_micros(1000), move || {
|
glib::timeout_add_local(Duration::from_micros(1000), move || {
|
||||||
async_match(
|
async_match(plugin_view.clone(), runtime_data_clone.clone(), id)
|
||||||
plugin_view.clone(),
|
|
||||||
runtime_data_clone.clone(),
|
|
||||||
id,
|
|
||||||
hide_icons,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
handle_matches(
|
handle_matches(
|
||||||
plugin_view.clone(),
|
plugin_view.clone(),
|
||||||
runtime_data_clone,
|
runtime_data.borrow().as_ref().unwrap(),
|
||||||
RVec::new(),
|
RVec::new(),
|
||||||
hide_icons,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glib::timeout_add_local(Duration::from_micros(1000), move || {
|
glib::timeout_add_local(Duration::from_micros(1000), move || {
|
||||||
async_match(
|
async_match(plugin_view.clone(), runtime_data_clone.clone(), id)
|
||||||
plugin_view.clone(),
|
|
||||||
runtime_data_clone.clone(),
|
|
||||||
id,
|
|
||||||
hide_icons,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -857,11 +909,14 @@ fn async_match(
|
|||||||
plugin_view: PluginView,
|
plugin_view: PluginView,
|
||||||
runtime_data: Rc<RefCell<Option<RuntimeData>>>,
|
runtime_data: Rc<RefCell<Option<RuntimeData>>>,
|
||||||
id: u64,
|
id: u64,
|
||||||
hide_icons: bool,
|
|
||||||
) -> glib::Continue {
|
) -> glib::Continue {
|
||||||
match plugin_view.plugin.poll_matches()(id) {
|
match plugin_view.plugin.poll_matches()(id) {
|
||||||
PollResult::Ready(matches) => {
|
PollResult::Ready(matches) => {
|
||||||
handle_matches(plugin_view, runtime_data, matches, hide_icons);
|
handle_matches(
|
||||||
|
plugin_view,
|
||||||
|
runtime_data.borrow().as_ref().unwrap(),
|
||||||
|
matches,
|
||||||
|
);
|
||||||
glib::Continue(false)
|
glib::Continue(false)
|
||||||
}
|
}
|
||||||
PollResult::Pending => glib::Continue(true),
|
PollResult::Pending => glib::Continue(true),
|
||||||
|
Reference in New Issue
Block a user