Skip to content

Commit 8df5e99

Browse files
authored
Enable drag/drop for folder selection (#1106)
1 parent 99277b9 commit 8df5e99

File tree

1 file changed

+54
-17
lines changed

1 file changed

+54
-17
lines changed

czkawka_gui/src/connect_things/connect_selection_of_directories.rs

+54-17
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
use gdk4::{DragAction, FileList};
2+
use std::collections::HashSet;
13
use std::path::PathBuf;
24

35
use gtk4::prelude::*;
4-
use gtk4::{FileChooserNative, Notebook, Orientation, ResponseType, TreeView, Window};
6+
use gtk4::{DropTarget, FileChooserNative, Notebook, Orientation, ResponseType, TreeView, Window};
57

68
#[cfg(target_family = "windows")]
79
use czkawka_core::common::Common;
@@ -61,6 +63,11 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) {
6163
notebook_upper,
6264
);
6365
}
66+
// Drag and drop
67+
{
68+
configure_directory_drop(&gui_data.upper_notebook.tree_view_included_directories, false);
69+
configure_directory_drop(&gui_data.upper_notebook.tree_view_excluded_directories, true);
70+
}
6471
// Remove Excluded Folder
6572
{
6673
let buttons_remove_excluded_directory = gui_data.upper_notebook.buttons_remove_excluded_directory.clone();
@@ -93,6 +100,32 @@ pub fn connect_selection_of_directories(gui_data: &GuiData) {
93100
}
94101
}
95102

103+
fn configure_directory_drop(tree_view: &TreeView, excluded_items: bool) {
104+
let tv = tree_view.clone();
105+
let drop_target = DropTarget::builder().name("file-drop-target").actions(DragAction::COPY).build();
106+
drop_target.set_types(&[FileList::static_type()]);
107+
drop_target.connect_drop(move |_, value, _, _| {
108+
if let Ok(file_list) = value.get::<FileList>() {
109+
let mut folders: HashSet<PathBuf> = HashSet::new();
110+
for f in file_list.files() {
111+
if let Some(path) = f.path() {
112+
if path.is_dir() {
113+
folders.insert(path);
114+
} else if let Some(parent) = path.parent() {
115+
if parent.is_dir() {
116+
folders.insert(parent.to_path_buf());
117+
}
118+
}
119+
}
120+
}
121+
add_directories(&tv, &folders.into_iter().collect(), excluded_items);
122+
}
123+
true
124+
});
125+
126+
tree_view.add_controller(drop_target);
127+
}
128+
96129
fn connect_file_dialog(file_dialog_include_exclude_folder_selection: &FileChooserNative, include_tree_view: TreeView, exclude_tree_view: TreeView, notebook_upper: Notebook) {
97130
file_dialog_include_exclude_folder_selection.connect_response(move |file_chooser, response_type| {
98131
if response_type == ResponseType::Accept {
@@ -121,26 +154,30 @@ fn connect_file_dialog(file_dialog_include_exclude_folder_selection: &FileChoose
121154
}
122155
}
123156

124-
let list_store = get_list_store(tree_view);
125-
126-
if excluded_items {
127-
for file_entry in &folders {
128-
let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &file_entry.to_string_lossy().to_string())];
129-
list_store.set(&list_store.append(), &values);
130-
}
131-
} else {
132-
for file_entry in &folders {
133-
let values: [(u32, &dyn ToValue); 2] = [
134-
(ColumnsIncludedDirectory::Path as u32, &file_entry.to_string_lossy().to_string()),
135-
(ColumnsIncludedDirectory::ReferenceButton as u32, &false),
136-
];
137-
list_store.set(&list_store.append(), &values);
138-
}
139-
}
157+
add_directories(tree_view, &folders, excluded_items);
140158
}
141159
});
142160
}
143161

162+
fn add_directories(tree_view: &TreeView, folders: &Vec<PathBuf>, excluded_items: bool) {
163+
let list_store = get_list_store(tree_view);
164+
165+
if excluded_items {
166+
for file_entry in folders {
167+
let values: [(u32, &dyn ToValue); 1] = [(ColumnsExcludedDirectory::Path as u32, &file_entry.to_string_lossy().to_string())];
168+
list_store.set(&list_store.append(), &values);
169+
}
170+
} else {
171+
for file_entry in folders {
172+
let values: [(u32, &dyn ToValue); 2] = [
173+
(ColumnsIncludedDirectory::Path as u32, &file_entry.to_string_lossy().to_string()),
174+
(ColumnsIncludedDirectory::ReferenceButton as u32, &false),
175+
];
176+
list_store.set(&list_store.append(), &values);
177+
}
178+
}
179+
}
180+
144181
fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded_items: bool) {
145182
let dialog = gtk4::Dialog::builder()
146183
.title(flg!("include_manually_directories_dialog_title"))

0 commit comments

Comments
 (0)