Make packages scroll incrementally instead of using 1.4GB of ram
This commit is contained in:
parent
55d9f15afd
commit
f0ae517e46
2 changed files with 216 additions and 85 deletions
|
@ -1,12 +1,15 @@
|
|||
use gtk::{
|
||||
prelude::{BoxExt, ButtonExt, Cast, EditableExt, ListBoxRowExt},
|
||||
Button, Window,
|
||||
prelude::{BoxExt, ButtonExt, EditableExt},
|
||||
Button, PositionType, Window,
|
||||
};
|
||||
use std::process::Command;
|
||||
|
||||
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
||||
|
||||
pub static mut PACKAGES_LIST: Option<ListBox> = None;
|
||||
pub static mut PKG_LIST: Vec<String> = vec![];
|
||||
pub static mut PKG_LIST_INDEX: usize = 0;
|
||||
pub static mut PKG_LISTBOX: Option<ScrolledWindow> = None;
|
||||
|
||||
pub fn browse() -> gtk::Box {
|
||||
let packages_box = gtk::Box::builder()
|
||||
|
@ -33,6 +36,8 @@ pub fn browse() -> gtk::Box {
|
|||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let skip_list = vec!["available", "installed", "last"];
|
||||
|
||||
unsafe {
|
||||
PACKAGES_LIST = Some(
|
||||
ListBox::builder()
|
||||
|
@ -54,68 +59,95 @@ pub fn browse() -> gtk::Box {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let pkg_list = pkg_list
|
||||
.lines()
|
||||
.skip(1)
|
||||
.map(|x| {
|
||||
x.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap()
|
||||
})
|
||||
.filter(|x| !x.trim().is_empty());
|
||||
unsafe {
|
||||
PKG_LIST = pkg_list
|
||||
.lines()
|
||||
.map(|x| {
|
||||
let y = x.to_string();
|
||||
let b = y
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap();
|
||||
b.to_string()
|
||||
})
|
||||
.filter(|x| {
|
||||
!x.trim().is_empty()
|
||||
&& !x.contains("=")
|
||||
&& !skip_list.contains(&x.to_lowercase().trim())
|
||||
})
|
||||
.collect();
|
||||
|
||||
for pkg in pkg_list {
|
||||
let pkg_btn = Button::builder()
|
||||
.label(pkg)
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
for pkg in PKG_LIST[0..(50.min(PKG_LIST.len()))].to_vec() {
|
||||
PKG_LIST_INDEX += 1;
|
||||
let pkg_btn = Button::builder()
|
||||
.label(pkg)
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||
});
|
||||
unsafe { PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn) };
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||
});
|
||||
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
PKG_LISTBOX = Some(
|
||||
ScrolledWindow::builder()
|
||||
.css_classes(["package-list-scrollable"])
|
||||
.valign(Align::Center)
|
||||
.halign(Align::Center)
|
||||
.width_request(800)
|
||||
.height_request(600)
|
||||
.build(),
|
||||
);
|
||||
|
||||
PKG_LISTBOX
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.connect_edge_reached(|_, edge| {
|
||||
if edge == PositionType::Bottom {
|
||||
for i in PKG_LIST_INDEX..((PKG_LIST_INDEX + 50).min(PKG_LIST.len())) {
|
||||
let pkg_btn = Button::builder()
|
||||
.label(PKG_LIST[i].as_str())
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(
|
||||
x.label().map(|x| x.to_string()).unwrap_or("".to_owned()),
|
||||
);
|
||||
});
|
||||
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn);
|
||||
|
||||
PKG_LIST_INDEX += 1;
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
pkgs_entry.connect_search_changed(move |x| {
|
||||
let x = x.clone();
|
||||
let f = x.clone();
|
||||
|
||||
// TODO: Possibly refactor to use `dnf search` instead of a filter function.
|
||||
unsafe {
|
||||
PACKAGES_LIST.as_ref().unwrap().set_filter_func(move |y| {
|
||||
y.child()
|
||||
.unwrap()
|
||||
.downcast::<Button>()
|
||||
.unwrap()
|
||||
.label()
|
||||
.map(|x| x.to_string())
|
||||
.unwrap_or("".to_string())
|
||||
.contains(x.text().to_string().as_str())
|
||||
})
|
||||
};
|
||||
unsafe { search(&f, &skip_list) }
|
||||
});
|
||||
|
||||
let pkg_listbox = ScrolledWindow::builder()
|
||||
.css_classes(["package-list-scrollable"])
|
||||
.valign(Align::Center)
|
||||
.halign(Align::Center)
|
||||
.width_request(800)
|
||||
.height_request(600)
|
||||
.build();
|
||||
|
||||
pkgs_search.connect_entry(&pkgs_entry);
|
||||
|
||||
packages_box.append(&pkgs_search);
|
||||
packages_box.append(&pkgs_entry);
|
||||
unsafe {
|
||||
packages_box.append(PKG_LISTBOX.as_ref().unwrap());
|
||||
|
||||
packages_box.append(&pkg_listbox);
|
||||
|
||||
pkg_listbox.set_child(Some(unsafe { PACKAGES_LIST.as_ref().unwrap() }));
|
||||
|
||||
dbg!(&pkg_listbox);
|
||||
|
||||
PKG_LISTBOX
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_child(Some(PACKAGES_LIST.as_ref().unwrap()));
|
||||
};
|
||||
packages_box
|
||||
}
|
||||
|
||||
|
@ -124,5 +156,67 @@ fn show_installed_package(pkg: String) {
|
|||
return;
|
||||
}
|
||||
|
||||
let pkg_window = Window::builder().build();
|
||||
let _pkg_window = Window::builder().build();
|
||||
}
|
||||
|
||||
unsafe fn search(f: &SearchEntry, skip_list: &Vec<&str>) {
|
||||
let pkg_list = String::from_utf8(
|
||||
Command::new("dnf")
|
||||
.args(["search", f.text().to_string().as_str()])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
PKG_LIST = pkg_list
|
||||
.lines()
|
||||
.map(|x| {
|
||||
let y = x.to_string();
|
||||
let b = y
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap();
|
||||
b.to_string()
|
||||
})
|
||||
.filter(|x| {
|
||||
!x.trim().is_empty()
|
||||
&& !x.contains("=")
|
||||
&& !skip_list.contains(&x.to_lowercase().trim())
|
||||
})
|
||||
.collect();
|
||||
|
||||
std::mem::drop(PACKAGES_LIST.take());
|
||||
|
||||
PACKAGES_LIST = Some(
|
||||
ListBox::builder()
|
||||
.css_classes(["packages-list"])
|
||||
.valign(Align::Center)
|
||||
.halign(Align::Fill)
|
||||
.hexpand(true)
|
||||
.build(),
|
||||
);
|
||||
|
||||
PKG_LIST_INDEX = 0;
|
||||
|
||||
for pkg in PKG_LIST[0..(50.min(PKG_LIST.len()))].to_vec() {
|
||||
PKG_LIST_INDEX += 1;
|
||||
let pkg_btn = Button::builder()
|
||||
.label(pkg)
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||
});
|
||||
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn)
|
||||
}
|
||||
|
||||
PKG_LISTBOX
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_child(Some(PACKAGES_LIST.as_ref().unwrap()));
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use gtk::{
|
||||
prelude::{BoxExt, ButtonExt, Cast, EditableExt, ListBoxRowExt},
|
||||
Button, Window,
|
||||
Button, PositionType, Window,
|
||||
};
|
||||
use std::process::Command;
|
||||
|
||||
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
||||
|
||||
pub static mut PACKAGES_LIST: Option<ListBox> = None;
|
||||
pub static mut PKG_LIST: Vec<String> = vec![];
|
||||
pub static mut PKG_LIST_INDEX: usize = 0;
|
||||
|
||||
pub fn installed() -> gtk::Box {
|
||||
let packages_box = gtk::Box::builder()
|
||||
|
@ -33,6 +35,8 @@ pub fn installed() -> gtk::Box {
|
|||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
let skip_list = vec!["available", "installed", "last"];
|
||||
|
||||
unsafe {
|
||||
PACKAGES_LIST = Some(
|
||||
ListBox::builder()
|
||||
|
@ -44,43 +48,56 @@ pub fn installed() -> gtk::Box {
|
|||
)
|
||||
};
|
||||
|
||||
// TODO: Make this part asynchronous so that the app opens faster
|
||||
let pkg_list = String::from_utf8(
|
||||
Command::new("dnf")
|
||||
.args(["list", "--installed"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let pkg_list = pkg_list
|
||||
.lines()
|
||||
.skip(1)
|
||||
.map(|x| {
|
||||
x.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split(".")
|
||||
.next()
|
||||
unsafe {
|
||||
// TODO: Make this part asynchronous so that the app opens faster
|
||||
let pkg_list = String::from_utf8(
|
||||
Command::new("dnf")
|
||||
.args(["list", "--installed"])
|
||||
.output()
|
||||
.unwrap()
|
||||
})
|
||||
.filter(|x| !x.trim().is_empty());
|
||||
.stdout,
|
||||
)
|
||||
.unwrap();
|
||||
PKG_LIST = pkg_list
|
||||
.lines()
|
||||
.map(|x| {
|
||||
let y = x.to_string();
|
||||
let b = y
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap();
|
||||
b.to_string()
|
||||
})
|
||||
.filter(|x| {
|
||||
!x.trim().is_empty()
|
||||
&& !x.contains("=")
|
||||
&& !skip_list.contains(&x.to_lowercase().trim())
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
for pkg in pkg_list {
|
||||
let pkg_btn = Button::builder()
|
||||
.label(pkg)
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
unsafe {
|
||||
for pkg in PKG_LIST[0..50].to_vec() {
|
||||
PKG_LIST_INDEX += 1;
|
||||
let pkg_btn = Button::builder()
|
||||
.label(pkg)
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||
});
|
||||
unsafe { PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn) };
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||
});
|
||||
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn)
|
||||
}
|
||||
}
|
||||
|
||||
pkgs_entry.connect_search_changed(move |x| {
|
||||
let x = x.clone();
|
||||
|
||||
// TODO: Possibly refactor to use `dnf search` instead of a filter function.
|
||||
unsafe {
|
||||
PACKAGES_LIST.as_ref().unwrap().set_filter_func(move |y| {
|
||||
y.child()
|
||||
|
@ -103,6 +120,28 @@ pub fn installed() -> gtk::Box {
|
|||
.height_request(600)
|
||||
.build();
|
||||
|
||||
pkg_listbox.connect_edge_reached(|_, edge| {
|
||||
if edge == PositionType::Bottom {
|
||||
unsafe {
|
||||
for i in PKG_LIST_INDEX..(PKG_LIST_INDEX + 50) {
|
||||
let pkg_btn = Button::builder()
|
||||
.label(PKG_LIST[i].as_str())
|
||||
.css_classes(["package-name"])
|
||||
.build();
|
||||
|
||||
pkg_btn.connect_clicked(|x| {
|
||||
show_installed_package(
|
||||
x.label().map(|x| x.to_string()).unwrap_or("".to_owned()),
|
||||
);
|
||||
});
|
||||
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn);
|
||||
|
||||
PKG_LIST_INDEX += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pkgs_search.connect_entry(&pkgs_entry);
|
||||
|
||||
packages_box.append(&pkgs_search);
|
||||
|
@ -112,8 +151,6 @@ pub fn installed() -> gtk::Box {
|
|||
|
||||
pkg_listbox.set_child(Some(unsafe { PACKAGES_LIST.as_ref().unwrap() }));
|
||||
|
||||
dbg!(&pkg_listbox);
|
||||
|
||||
packages_box
|
||||
}
|
||||
|
||||
|
@ -122,5 +159,5 @@ fn show_installed_package(pkg: String) {
|
|||
return;
|
||||
}
|
||||
|
||||
let pkg_window = Window::builder().build();
|
||||
let _pkg_window = Window::builder().build();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue