From 6d68ae45b4fff9ecf4f3444d35d6b9f5eca08c8f Mon Sep 17 00:00:00 2001 From: Zac Date: Wed, 3 Mar 2021 21:00:32 +1000 Subject: [PATCH] FileManager: Add launch handler actions to desktop context menu Extracted a method from the code in the File Manager application which added actions for activating launch handlers found for the selected file from the context menu. Applied this method to desktop files and shortcuts. Note: made some launch handler related methods in the DirectoryView static or const which allows passing const DirectoryView& to certain methods. --- .../FileManager/DirectoryView.cpp | 2 +- .../Applications/FileManager/DirectoryView.h | 6 +- Userland/Applications/FileManager/main.cpp | 104 +++++++++++------- 3 files changed, 70 insertions(+), 42 deletions(-) diff --git a/Userland/Applications/FileManager/DirectoryView.cpp b/Userland/Applications/FileManager/DirectoryView.cpp index 39cc184f6c..ceb27dce10 100644 --- a/Userland/Applications/FileManager/DirectoryView.cpp +++ b/Userland/Applications/FileManager/DirectoryView.cpp @@ -444,7 +444,7 @@ void DirectoryView::set_should_show_dotfiles(bool show_dotfiles) m_model->set_should_show_dotfiles(show_dotfiles); } -void DirectoryView::launch(const URL&, const LauncherHandler& launcher_handler) +void DirectoryView::launch(const URL&, const LauncherHandler& launcher_handler) const { pid_t child; if (launcher_handler.details().launcher_type == Desktop::Launcher::LauncherType::Application) { diff --git a/Userland/Applications/FileManager/DirectoryView.h b/Userland/Applications/FileManager/DirectoryView.h index eb972167f2..1ac3b7417b 100644 --- a/Userland/Applications/FileManager/DirectoryView.h +++ b/Userland/Applications/FileManager/DirectoryView.h @@ -74,12 +74,12 @@ public: int path_history_size() const { return m_path_history.size(); } int path_history_position() const { return m_path_history_position; } static RefPtr get_default_launch_handler(const NonnullRefPtrVector& handlers); - NonnullRefPtrVector get_launch_handlers(const URL& url); - NonnullRefPtrVector get_launch_handlers(const String& path); + static NonnullRefPtrVector get_launch_handlers(const URL& url); + static NonnullRefPtrVector get_launch_handlers(const String& path); void refresh(); - void launch(const URL&, const LauncherHandler&); + void launch(const URL&, const LauncherHandler&) const; Function on_path_change; Function on_selection_change; diff --git a/Userland/Applications/FileManager/main.cpp b/Userland/Applications/FileManager/main.cpp index d93059bf18..6b8128c32a 100644 --- a/Userland/Applications/FileManager/main.cpp +++ b/Userland/Applications/FileManager/main.cpp @@ -78,6 +78,7 @@ static void do_copy(const Vector& selected_file_paths, FileUtils::FileOp static void do_paste(const String& target_directory, GUI::Window* window); static void do_create_link(const Vector& selected_file_paths, GUI::Window* window); static void show_properties(const String& container_dir_path, const String& path, const Vector& selected, GUI::Window* window); +static bool add_launch_handler_actions_to_menu(RefPtr& menu, const DirectoryView& directory_view, const String& full_path, RefPtr& default_action, NonnullRefPtrVector& current_file_launch_handlers); int main(int argc, char** argv) { @@ -211,6 +212,44 @@ void show_properties(const String& container_dir_path, const String& path, const properties->show(); } +bool add_launch_handler_actions_to_menu(RefPtr& menu, const DirectoryView& directory_view, const String& full_path, RefPtr& default_action, NonnullRefPtrVector& current_file_launch_handlers) +{ + current_file_launch_handlers = directory_view.get_launch_handlers(full_path); + + bool added_open_menu_items = false; + auto default_file_handler = directory_view.get_default_launch_handler(current_file_launch_handlers); + if (default_file_handler) { + auto file_open_action = default_file_handler->create_launch_action([&, full_path = move(full_path)](auto& launcher_handler) { + directory_view.launch(URL::create_with_file_protocol(full_path), launcher_handler); + }); + if (default_file_handler->details().launcher_type == Desktop::Launcher::LauncherType::Application) + file_open_action->set_text(String::formatted("Run {}", file_open_action->text())); + else + file_open_action->set_text(String::formatted("Open in {}", file_open_action->text())); + + default_action = file_open_action; + + menu->add_action(move(file_open_action)); + added_open_menu_items = true; + } else { + default_action.clear(); + } + + if (current_file_launch_handlers.size() > 1) { + added_open_menu_items = true; + auto& file_open_with_menu = menu->add_submenu("Open with"); + for (auto& handler : current_file_launch_handlers) { + if (&handler == default_file_handler.ptr()) + continue; + file_open_with_menu.add_action(handler.create_launch_action([&, full_path = move(full_path)](auto& launcher_handler) { + directory_view.launch(URL::create_with_file_protocol(full_path), launcher_handler); + })); + } + } + + return added_open_menu_items; +} + int run_in_desktop_mode([[maybe_unused]] RefPtr config) { static constexpr const char* process_name = "FileManager (Desktop)"; @@ -304,11 +343,33 @@ int run_in_desktop_mode([[maybe_unused]] RefPtr config) desktop_context_menu->add_separator(); desktop_context_menu->add_action(properties_action); + RefPtr file_context_menu; + NonnullRefPtrVector current_file_handlers; + RefPtr file_context_menu_action_default_action; + directory_view.on_context_menu_request = [&](const GUI::ModelIndex& index, const GUI::ContextMenuEvent& event) { - if (!index.is_valid()) + if (index.is_valid()) { + auto& node = directory_view.node(index); + if (node.is_directory()) { + desktop_context_menu->popup(event.screen_position()); + } else { + file_context_menu = GUI::Menu::construct("Directory View File"); + file_context_menu->add_action(copy_action); + file_context_menu->add_action(cut_action); + file_context_menu->add_action(paste_action); + file_context_menu->add_action(directory_view.delete_action()); + file_context_menu->add_separator(); + + bool added_open_menu_items = add_launch_handler_actions_to_menu(file_context_menu, directory_view, node.full_path(), file_context_menu_action_default_action, current_file_handlers); + if (added_open_menu_items) + file_context_menu->add_separator(); + + file_context_menu->add_action(properties_action); + file_context_menu->popup(event.screen_position()); + } + } else { desktop_view_context_menu->popup(event.screen_position()); - else - desktop_context_menu->popup(event.screen_position()); + } }; auto wm_config = Core::ConfigFile::get_for_app("WindowManager"); @@ -889,49 +950,16 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio folder_specific_paste_action->set_enabled(should_get_enabled); directory_context_menu->popup(event.screen_position()); } else { - auto full_path = node.full_path(); - current_file_handlers = directory_view.get_launch_handlers(full_path); - file_context_menu = GUI::Menu::construct("Directory View File"); file_context_menu->add_action(copy_action); file_context_menu->add_action(cut_action); file_context_menu->add_action(paste_action); file_context_menu->add_action(directory_view.delete_action()); file_context_menu->add_action(shortcut_action); - file_context_menu->add_separator(); - bool added_open_menu_items = false; - auto default_file_handler = directory_view.get_default_launch_handler(current_file_handlers); - if (default_file_handler) { - auto file_open_action = default_file_handler->create_launch_action([&, full_path = move(full_path)](auto& launcher_handler) { - directory_view.launch(URL::create_with_file_protocol(full_path), launcher_handler); - }); - if (default_file_handler->details().launcher_type == Desktop::Launcher::LauncherType::Application) - file_open_action->set_text(String::formatted("Run {}", file_open_action->text())); - else - file_open_action->set_text(String::formatted("Open in {}", file_open_action->text())); - file_context_menu_action_default_action = file_open_action; - - file_context_menu->add_action(move(file_open_action)); - added_open_menu_items = true; - } else { - file_context_menu_action_default_action.clear(); - } - - if (current_file_handlers.size() > 1) { - added_open_menu_items = true; - auto& file_open_with_menu = file_context_menu->add_submenu("Open with"); - for (auto& handler : current_file_handlers) { - if (&handler == default_file_handler.ptr()) - continue; - file_open_with_menu.add_action(handler.create_launch_action([&, full_path = move(full_path)](auto& launcher_handler) { - directory_view.launch(URL::create_with_file_protocol(full_path), launcher_handler); - })); - } - } - - if (added_open_menu_items) + bool added_launch_file_handlers = add_launch_handler_actions_to_menu(file_context_menu, directory_view, node.full_path(), file_context_menu_action_default_action, current_file_handlers); + if (added_launch_file_handlers) file_context_menu->add_separator(); file_context_menu->add_action(properties_action);