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::{
|
use gtk::{
|
||||||
prelude::{BoxExt, ButtonExt, Cast, EditableExt, ListBoxRowExt},
|
prelude::{BoxExt, ButtonExt, EditableExt},
|
||||||
Button, Window,
|
Button, PositionType, Window,
|
||||||
};
|
};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
||||||
|
|
||||||
pub static mut PACKAGES_LIST: Option<ListBox> = None;
|
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 {
|
pub fn browse() -> gtk::Box {
|
||||||
let packages_box = gtk::Box::builder()
|
let packages_box = gtk::Box::builder()
|
||||||
|
@ -33,6 +36,8 @@ pub fn browse() -> gtk::Box {
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let skip_list = vec!["available", "installed", "last"];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
PACKAGES_LIST = Some(
|
PACKAGES_LIST = Some(
|
||||||
ListBox::builder()
|
ListBox::builder()
|
||||||
|
@ -54,20 +59,29 @@ pub fn browse() -> gtk::Box {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let pkg_list = pkg_list
|
unsafe {
|
||||||
|
PKG_LIST = pkg_list
|
||||||
.lines()
|
.lines()
|
||||||
.skip(1)
|
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
x.split_whitespace()
|
let y = x.to_string();
|
||||||
|
let b = y
|
||||||
|
.split_whitespace()
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.split(".")
|
.split(".")
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
b.to_string()
|
||||||
})
|
})
|
||||||
.filter(|x| !x.trim().is_empty());
|
.filter(|x| {
|
||||||
|
!x.trim().is_empty()
|
||||||
|
&& !x.contains("=")
|
||||||
|
&& !skip_list.contains(&x.to_lowercase().trim())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
for pkg in pkg_list {
|
for pkg in PKG_LIST[0..(50.min(PKG_LIST.len()))].to_vec() {
|
||||||
|
PKG_LIST_INDEX += 1;
|
||||||
let pkg_btn = Button::builder()
|
let pkg_btn = Button::builder()
|
||||||
.label(pkg)
|
.label(pkg)
|
||||||
.css_classes(["package-name"])
|
.css_classes(["package-name"])
|
||||||
|
@ -76,46 +90,64 @@ pub fn browse() -> gtk::Box {
|
||||||
pkg_btn.connect_clicked(|x| {
|
pkg_btn.connect_clicked(|x| {
|
||||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||||
});
|
});
|
||||||
unsafe { PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn) };
|
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 {
|
unsafe {
|
||||||
PACKAGES_LIST.as_ref().unwrap().set_filter_func(move |y| {
|
PKG_LISTBOX = Some(
|
||||||
y.child()
|
ScrolledWindow::builder()
|
||||||
.unwrap()
|
|
||||||
.downcast::<Button>()
|
|
||||||
.unwrap()
|
|
||||||
.label()
|
|
||||||
.map(|x| x.to_string())
|
|
||||||
.unwrap_or("".to_string())
|
|
||||||
.contains(x.text().to_string().as_str())
|
|
||||||
})
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
let pkg_listbox = ScrolledWindow::builder()
|
|
||||||
.css_classes(["package-list-scrollable"])
|
.css_classes(["package-list-scrollable"])
|
||||||
.valign(Align::Center)
|
.valign(Align::Center)
|
||||||
.halign(Align::Center)
|
.halign(Align::Center)
|
||||||
.width_request(800)
|
.width_request(800)
|
||||||
.height_request(600)
|
.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();
|
.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 f = x.clone();
|
||||||
|
|
||||||
|
// TODO: Possibly refactor to use `dnf search` instead of a filter function.
|
||||||
|
unsafe { search(&f, &skip_list) }
|
||||||
|
});
|
||||||
|
|
||||||
pkgs_search.connect_entry(&pkgs_entry);
|
pkgs_search.connect_entry(&pkgs_entry);
|
||||||
|
|
||||||
packages_box.append(&pkgs_search);
|
packages_box.append(&pkgs_search);
|
||||||
packages_box.append(&pkgs_entry);
|
packages_box.append(&pkgs_entry);
|
||||||
|
unsafe {
|
||||||
|
packages_box.append(PKG_LISTBOX.as_ref().unwrap());
|
||||||
|
|
||||||
packages_box.append(&pkg_listbox);
|
PKG_LISTBOX
|
||||||
|
.as_ref()
|
||||||
pkg_listbox.set_child(Some(unsafe { PACKAGES_LIST.as_ref().unwrap() }));
|
.unwrap()
|
||||||
|
.set_child(Some(PACKAGES_LIST.as_ref().unwrap()));
|
||||||
dbg!(&pkg_listbox);
|
};
|
||||||
|
|
||||||
packages_box
|
packages_box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,5 +156,67 @@ fn show_installed_package(pkg: String) {
|
||||||
return;
|
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::{
|
use gtk::{
|
||||||
prelude::{BoxExt, ButtonExt, Cast, EditableExt, ListBoxRowExt},
|
prelude::{BoxExt, ButtonExt, Cast, EditableExt, ListBoxRowExt},
|
||||||
Button, Window,
|
Button, PositionType, Window,
|
||||||
};
|
};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
use gtk::{Align, ListBox, ScrolledWindow, SearchBar, SearchEntry};
|
||||||
|
|
||||||
pub static mut PACKAGES_LIST: Option<ListBox> = None;
|
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 {
|
pub fn installed() -> gtk::Box {
|
||||||
let packages_box = gtk::Box::builder()
|
let packages_box = gtk::Box::builder()
|
||||||
|
@ -33,6 +35,8 @@ pub fn installed() -> gtk::Box {
|
||||||
.hexpand(true)
|
.hexpand(true)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let skip_list = vec!["available", "installed", "last"];
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
PACKAGES_LIST = Some(
|
PACKAGES_LIST = Some(
|
||||||
ListBox::builder()
|
ListBox::builder()
|
||||||
|
@ -44,6 +48,7 @@ pub fn installed() -> gtk::Box {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
// TODO: Make this part asynchronous so that the app opens faster
|
// TODO: Make this part asynchronous so that the app opens faster
|
||||||
let pkg_list = String::from_utf8(
|
let pkg_list = String::from_utf8(
|
||||||
Command::new("dnf")
|
Command::new("dnf")
|
||||||
|
@ -53,21 +58,30 @@ pub fn installed() -> gtk::Box {
|
||||||
.stdout,
|
.stdout,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
PKG_LIST = pkg_list
|
||||||
let pkg_list = pkg_list
|
|
||||||
.lines()
|
.lines()
|
||||||
.skip(1)
|
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
x.split_whitespace()
|
let y = x.to_string();
|
||||||
|
let b = y
|
||||||
|
.split_whitespace()
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.split(".")
|
.split(".")
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap();
|
||||||
|
b.to_string()
|
||||||
})
|
})
|
||||||
.filter(|x| !x.trim().is_empty());
|
.filter(|x| {
|
||||||
|
!x.trim().is_empty()
|
||||||
|
&& !x.contains("=")
|
||||||
|
&& !skip_list.contains(&x.to_lowercase().trim())
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
for pkg in pkg_list {
|
unsafe {
|
||||||
|
for pkg in PKG_LIST[0..50].to_vec() {
|
||||||
|
PKG_LIST_INDEX += 1;
|
||||||
let pkg_btn = Button::builder()
|
let pkg_btn = Button::builder()
|
||||||
.label(pkg)
|
.label(pkg)
|
||||||
.css_classes(["package-name"])
|
.css_classes(["package-name"])
|
||||||
|
@ -76,11 +90,14 @@ pub fn installed() -> gtk::Box {
|
||||||
pkg_btn.connect_clicked(|x| {
|
pkg_btn.connect_clicked(|x| {
|
||||||
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
show_installed_package(x.label().map(|x| x.to_string()).unwrap_or("".to_owned()));
|
||||||
});
|
});
|
||||||
unsafe { PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn) };
|
PACKAGES_LIST.as_ref().unwrap().append(&pkg_btn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgs_entry.connect_search_changed(move |x| {
|
pkgs_entry.connect_search_changed(move |x| {
|
||||||
let x = x.clone();
|
let x = x.clone();
|
||||||
|
|
||||||
|
// TODO: Possibly refactor to use `dnf search` instead of a filter function.
|
||||||
unsafe {
|
unsafe {
|
||||||
PACKAGES_LIST.as_ref().unwrap().set_filter_func(move |y| {
|
PACKAGES_LIST.as_ref().unwrap().set_filter_func(move |y| {
|
||||||
y.child()
|
y.child()
|
||||||
|
@ -103,6 +120,28 @@ pub fn installed() -> gtk::Box {
|
||||||
.height_request(600)
|
.height_request(600)
|
||||||
.build();
|
.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);
|
pkgs_search.connect_entry(&pkgs_entry);
|
||||||
|
|
||||||
packages_box.append(&pkgs_search);
|
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() }));
|
pkg_listbox.set_child(Some(unsafe { PACKAGES_LIST.as_ref().unwrap() }));
|
||||||
|
|
||||||
dbg!(&pkg_listbox);
|
|
||||||
|
|
||||||
packages_box
|
packages_box
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,5 +159,5 @@ fn show_installed_package(pkg: String) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pkg_window = Window::builder().build();
|
let _pkg_window = Window::builder().build();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue