diff options
author | Tommy Nguyen <remyabel@gmail.com> | 2019-12-12 04:49:17 -0500 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-12-12 11:19:02 +0100 |
commit | 17f3948b153e50db6226834ac34d22ca88f6d7c5 (patch) | |
tree | ada194cbb0e77c065c8e661c922381f11686ffe7 | |
parent | f26548395e919c69e6332952672f0633aa9f33df (diff) | |
download | serenity-17f3948b153e50db6226834ac34d22ca88f6d7c5.zip |
FileManager: Add a context menu to the TreeView
This adds a context menu to the TreeView with the ability to copy/paste, create
new directories, etc. This does not address the issue mentioned above where
using the global application shortcut does not apply to whatever view has
focus.
-rw-r--r-- | Applications/FileManager/main.cpp | 109 |
1 files changed, 84 insertions, 25 deletions
diff --git a/Applications/FileManager/main.cpp b/Applications/FileManager/main.cpp index ccbd71e013..53e20ab85b 100644 --- a/Applications/FileManager/main.cpp +++ b/Applications/FileManager/main.cpp @@ -89,18 +89,21 @@ int main(int argc, char** argv) directory_view->open(location_textbox->text()); }; - tree_view->on_selection_change = [&] { - auto path = file_system_model->path(tree_view->selection().first()); - if (directory_view->path() == path) - return; - directory_view->open(path); - }; - auto refresh_tree_view = [&] { file_system_model->update(); auto current_path = directory_view->path(); + struct stat st; + // If the directory no longer exists, we find a parent that does. + while (lstat(current_path.characters(), &st) != 0) { + directory_view->open_parent_directory(); + current_path = directory_view->path(); + if (current_path == file_system_model->root_path()) { + break; + } + } + // not exactly sure why i have to reselect the root node first, but the index() fails if I dont auto root_index = file_system_model->index(file_system_model->root_path()); tree_view->selection().set(root_index); @@ -114,6 +117,12 @@ int main(int argc, char** argv) directory_view->refresh(); }; + auto directory_context_menu = GMenu::construct("Directory View Directory"); + auto file_context_menu = GMenu::construct("Directory View File"); + auto directory_view_context_menu = GMenu::construct("Directory View"); + auto tree_view_directory_context_menu = GMenu::construct("Tree View Directory"); + auto tree_view_context_menu = GMenu::construct("Tree View"); + auto open_parent_directory_action = GAction::create("Open parent directory", { Mod_Alt, Key_Up }, GraphicsBitmap::load_from_file("/res/icons/16x16/open-parent-directory.png"), [&](const GAction&) { directory_view->open_parent_directory(); }); @@ -172,8 +181,22 @@ int main(int argc, char** argv) return paths; }; - auto copy_action = GCommonActions::make_copy_action([&](const GAction&) { - auto paths = selected_file_paths(); + auto tree_view_selected_file_paths = [&] { + Vector<String> paths; + auto& view = tree_view; + view->selection().for_each_index([&](const GModelIndex& index) { + paths.append(file_system_model->path(index)); + }); + return paths; + }; + + auto copy_action = GCommonActions::make_copy_action([&](const GAction& action) { + Vector<String> paths; + if (action.activator() == directory_context_menu) { + paths = selected_file_paths(); + } else { + paths = tree_view_selected_file_paths(); + } if (paths.is_empty()) return; StringBuilder copy_text; @@ -206,6 +229,8 @@ int main(int argc, char** argv) auto error_message = String::format("Could not paste %s.", current_path.characters()); GMessageBox::show(error_message, "File Manager", GMessageBox::Type::Error); + } else { + refresh_tree_view(); } } }); @@ -216,13 +241,20 @@ int main(int argc, char** argv) }; auto properties_action - = GAction::create("Properties...", { Mod_Alt, Key_Return }, GraphicsBitmap::load_from_file("/res/icons/16x16/properties.png"), [&](auto&) { + = GAction::create("Properties...", { Mod_Alt, Key_Return }, GraphicsBitmap::load_from_file("/res/icons/16x16/properties.png"), [&](const GAction& action) { auto& model = directory_view->model(); - auto selected = selected_file_paths(); - + String path; + Vector<String> selected; + if (action.activator() == directory_context_menu) { + path = directory_view->path(); + selected = selected_file_paths(); + } else { + path = file_system_model->path(tree_view->selection().first()); + selected = tree_view_selected_file_paths(); + } RefPtr<PropertiesDialog> properties; if (selected.is_empty()) { - properties = PropertiesDialog::construct(model, directory_view->path(), true, window); + properties = PropertiesDialog::construct(model, path, true, window); } else { properties = PropertiesDialog::construct(model, selected.first(), false, window); } @@ -233,8 +265,13 @@ int main(int argc, char** argv) enum class ConfirmBeforeDelete { No, Yes }; - auto do_delete = [&](ConfirmBeforeDelete confirm) { - auto paths = selected_file_paths(); + auto do_delete = [&](ConfirmBeforeDelete confirm, const GAction& action) { + Vector<String> paths; + if (action.activator() == directory_context_menu) { + paths = selected_file_paths(); + } else { + paths = tree_view_selected_file_paths(); + } if (paths.is_empty()) return; { @@ -299,12 +336,12 @@ int main(int argc, char** argv) } }; - auto force_delete_action = GAction::create("Delete without confirmation", { Mod_Shift, Key_Delete }, [&](const GAction&) { - do_delete(ConfirmBeforeDelete::No); + auto force_delete_action = GAction::create("Delete without confirmation", { Mod_Shift, Key_Delete }, [&](const GAction& action) { + do_delete(ConfirmBeforeDelete::No, action); }); - auto delete_action = GCommonActions::make_delete_action([&](const GAction&) { - do_delete(ConfirmBeforeDelete::Yes); + auto delete_action = GCommonActions::make_delete_action([&](const GAction& action) { + do_delete(ConfirmBeforeDelete::Yes, action); }); delete_action->set_enabled(false); @@ -372,9 +409,11 @@ int main(int argc, char** argv) window->set_title(String::format("File Manager: %s", new_path.characters())); location_textbox->set_text(new_path); auto new_index = file_system_model->index(new_path); - tree_view->selection().set(new_index); - tree_view->scroll_into_view(new_index, Orientation::Vertical); - tree_view->update(); + if (new_index.is_valid()) { + tree_view->selection().set(new_index); + tree_view->scroll_into_view(new_index, Orientation::Vertical); + tree_view->update(); + } go_forward_action->set_enabled(directory_view->path_history_position() < directory_view->path_history_size() - 1); @@ -412,14 +451,12 @@ int main(int argc, char** argv) } }); - auto directory_context_menu = GMenu::construct(); directory_context_menu->add_action(copy_action); directory_context_menu->add_action(paste_action); directory_context_menu->add_action(delete_action); directory_context_menu->add_separator(); directory_context_menu->add_action(properties_action); - auto file_context_menu = GMenu::construct(); file_context_menu->add_action(copy_action); file_context_menu->add_action(paste_action); file_context_menu->add_action(delete_action); @@ -428,9 +465,16 @@ int main(int argc, char** argv) file_context_menu->add_separator(); file_context_menu->add_action(properties_action); - auto directory_view_context_menu = GMenu::construct(); directory_view_context_menu->add_action(mkdir_action); + tree_view_directory_context_menu->add_action(copy_action); + tree_view_directory_context_menu->add_action(paste_action); + tree_view_directory_context_menu->add_action(delete_action); + tree_view_directory_context_menu->add_separator(); + tree_view_directory_context_menu->add_action(properties_action); + tree_view_directory_context_menu->add_separator(); + tree_view_directory_context_menu->add_action(mkdir_action); + directory_view->on_context_menu_request = [&](const GAbstractView&, const GModelIndex& index, const GContextMenuEvent& event) { if (index.is_valid()) { auto& entry = directory_view->model().entry(index.row()); @@ -445,6 +489,21 @@ int main(int argc, char** argv) } }; + tree_view->on_selection_change = [&] { + auto path = file_system_model->path(tree_view->selection().first()); + if (directory_view->path() == path) + return; + directory_view->open(path); + copy_action->set_enabled(!tree_view->selection().is_empty()); + delete_action->set_enabled(!tree_view->selection().is_empty()); + }; + + tree_view->on_context_menu_request = [&](const GModelIndex& index, const GContextMenuEvent& event) { + if (index.is_valid()) { + tree_view_directory_context_menu->popup(event.screen_position()); + } + }; + // our initial location is defined as, in order of precedence: // 1. the first command-line argument (e.g. FileManager /bin) // 2. the user's home directory |