Skip to content

Commit

Permalink
Implement right-click preview windows (#26)
Browse files Browse the repository at this point in the history
* Implement right-click preview windows

* open the preview on release

fixes a bug with buttons staying in the clicked state

* semi optimize functionality

* run fmt

* fix clippy

* move loading to new window to prevent gui freezing

* add onto benefits

* use :

---------

Co-authored-by: Adam Perkowski <[email protected]>
  • Loading branch information
nnyyxxxx and adamperkowski authored Oct 27, 2024
1 parent 08c4514 commit d0b6e31
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ An unofficial GUI for setting wallpapers with multiple backends, built with GTK4
- **Cli args** - Hyprwall supports command line arguments, to view these type **`hyprwall --help`**, **--restore** is one of them, if you wish you can restore your last used wallpaper in the gui with this argument.
- **GIF support** - Hyprwall supports GIFs, but only if the **swww** backend is used.
- **Search functionality** - Hyprwall has search functionality that can filter through your wallpapers in real time.
- **Previewable images** - Hyprwall can preview images at a much larger scale via right clicking on an image: it will bring up a preview window.
- **Supports swaybg, swww, wallutils, feh, and hyprpaper** - Hyprwall supports a variety of wallpaper backends, so you can use it with your preferred wallpaper tool.

<div align='center'>
Expand Down
90 changes: 90 additions & 0 deletions src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,16 @@ fn load_images(
});
button.add_controller(motion_controller);

let gesture = gtk::GestureClick::new();
gesture.set_button(3);
let path_clone_preview = path_clone.clone();
gesture.connect_released(move |gesture, _, _, _| {
if let Some(widget) = gesture.widget() {
show_preview_window(&path_clone_preview, &widget);
}
});
button.add_controller(gesture);

let file_name = Path::new(&path_clone)
.file_name()
.and_then(|name| name.to_str())
Expand Down Expand Up @@ -687,3 +697,83 @@ fn filter_wallpapers(flowbox: &Rc<RefCell<FlowBox>>, search_text: impl AsRef<str

flowbox.set_filter_func(Box::new(filter));
}

fn show_preview_window(path: &str, parent_widget: &impl IsA<gtk::Widget>) {
let path = path.to_string();
let parent = parent_widget.root().and_downcast::<gtk::Window>();

glib::spawn_future_local(async move {
let window = gtk::Window::new();
window.set_title(Some("Preview"));
window.set_default_size(800, 600);
window.set_modal(true);
window.set_transient_for(parent.as_ref());

let spinner = gtk::Spinner::new();
spinner.set_hexpand(true);
spinner.set_vexpand(true);
spinner.start();
window.set_child(Some(&spinner));

let window_weak = window.downgrade();
let key_controller = gtk::EventControllerKey::new();
key_controller.connect_key_pressed(move |_, key, _, _| {
if key == gdk::Key::Escape {
if let Some(window) = window_weak.upgrade() {
window.close();
}
glib::Propagation::Stop
} else {
glib::Propagation::Proceed
}
});
window.add_controller(key_controller);

window.present();

let path_buf = PathBuf::from(&path);
let window_weak = window.downgrade();

let (sender, receiver) = crossbeam_channel::unbounded::<Result<Texture, String>>();

std::thread::spawn(move || {
let file = gio::File::for_path(&path_buf);
match Texture::from_file(&file) {
Ok(texture) => {
let _ = sender.send(Ok(texture));
}
Err(e) => {
let _ = sender.send(Err(e.to_string()));
}
}
});

glib::source::idle_add_local(move || match receiver.try_recv() {
Ok(result) => {
if let Some(window) = window_weak.upgrade() {
match result {
Ok(texture) => {
let picture = gtk::Picture::for_paintable(&texture);
picture.set_can_shrink(true);
picture.set_keep_aspect_ratio(true);
picture.set_hexpand(true);
picture.set_vexpand(true);
window.set_child(Some(&picture));
}
Err(error) => {
let error_label =
gtk::Label::new(Some(&format!("Failed to load image: {}", error)));
error_label.set_wrap(true);
error_label.set_margin_start(10);
error_label.set_margin_end(10);
window.set_child(Some(&error_label));
}
}
}
ControlFlow::Break
}
Err(crossbeam_channel::TryRecvError::Empty) => ControlFlow::Continue,
Err(crossbeam_channel::TryRecvError::Disconnected) => ControlFlow::Break,
});
});
}

0 comments on commit d0b6e31

Please sign in to comment.