Created
March 9, 2022 13:43
-
-
Save kavan-mevada/3d53a008008618c1e606c43b057a57ec to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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