Skip to content

Instantly share code, notes, and snippets.

@kavanmevada
Created March 9, 2022 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kavanmevada/3d53a008008618c1e606c43b057a57ec to your computer and use it in GitHub Desktop.
Save kavanmevada/3d53a008008618c1e606c43b057a57ec to your computer and use it in GitHub Desktop.
mod model;
mod row;
mod list;
use std::path::Path;
use crate::list::DirectoryList;
use crate::model::Model;
use gtk::glib::{clone, self};
use gtk::prelude::*;
use row::Row;
fn main() {
let application = gtk::Application::new(
Some("com.github.gtk-rs.examples.apps_launcher"),
Default::default(),
);
application.connect_activate( move |app| {
let window = gtk::ApplicationWindow::builder()
.default_width(600)
.default_height(600)
.application(app)
.title("ListView: Applications Launcher")
.build();
let model = DirectoryList::new();
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
std::thread::spawn(clone!(@strong tx => move || {
visit_dirs(Path::new("/home/kavan/Downloads"), &move |entry| tx.send(entry.path().display().to_string()).expect("Error sending data!")).expect("msg");
}));
rx.attach(None, clone!(@strong model => move |data: String| {
let at = model.n_items();
model.append(Model::new(&data, None));
model.items_changed(at, 0, 1);
glib::Continue(true)
}));
let factory = gtk::SignalListItemFactory::new();
// the "setup" stage is used for creating the widgets
factory.connect_setup(move |_factory, item| {
item.set_child(Some(&Row::new()));
});
// the bind stage is used for "binding" the data to the created widgets on the "setup" stage
factory.connect_bind(move |_factory, list_item| {
let app_info = list_item
.item().and_then(|c| c.downcast::<Model>().ok())
.unwrap();
let child = list_item
.child().and_then(|c| c.downcast::<Row>().ok())
.unwrap();
child.set_model(&app_info);
});
// A sorter used to sort AppInfo in the model by their name
let sorter = gtk::CustomSorter::new(move |obj1, obj2| {
let app_info1 = obj1.downcast_ref::<Model>().unwrap();
let app_info2 = obj2.downcast_ref::<Model>().unwrap();
app_info1
.name()
.to_lowercase()
.cmp(&app_info2.name().to_lowercase())
.into()
});
let sorted_model = gtk::SortListModel::new(Some(&model), Some(&sorter));
let selection_model = gtk::SingleSelection::new(Some(&sorted_model));
let list_view = gtk::ListView::new(Some(&selection_model), Some(&factory));
let scrolled_window = gtk::ScrolledWindow::builder()
.hscrollbar_policy(gtk::PolicyType::Never) // Disable horizontal scrolling
.min_content_width(360)
.child(&list_view)
.build();
window.set_child(Some(&scrolled_window));
window.show();
});
application.run();
}
pub fn visit_dirs<P: AsRef<std::path::Path>>(dir: P, cb: &dyn Fn(&std::fs::DirEntry)) -> std::io::Result<()> {
if dir.as_ref().is_dir() {
for entry in std::fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
visit_dirs(&path, cb)?;
} else {
cb(&entry);
}
}
}
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment