mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:07:35 +00:00
FileManager: Added context menu for right-clicks on desktop icons.
Moved the same copy/paste/properties/delete functionality used in the run_in_windowed_mode() method to the run_in_desktop_mode() method.
This commit is contained in:
parent
dea399ff08
commit
1851da9c93
1 changed files with 125 additions and 58 deletions
|
@ -72,6 +72,9 @@ using namespace FileManager;
|
||||||
|
|
||||||
static int run_in_desktop_mode(RefPtr<Core::ConfigFile>);
|
static int run_in_desktop_mode(RefPtr<Core::ConfigFile>);
|
||||||
static int run_in_windowed_mode(RefPtr<Core::ConfigFile>, String initial_location);
|
static int run_in_windowed_mode(RefPtr<Core::ConfigFile>, String initial_location);
|
||||||
|
static void do_copy(const Vector<String>& selected_file_paths);
|
||||||
|
static void do_paste(const String& target_directory, GUI::Window* window);
|
||||||
|
static void show_properties(const String& container_dir_path, const String& path, const Vector<String>& selected, GUI::Window* window);
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
@ -123,6 +126,61 @@ int main(int argc, char** argv)
|
||||||
return run_in_windowed_mode(move(config), initial_location);
|
return run_in_windowed_mode(move(config), initial_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_copy(const Vector<String>& selected_file_paths)
|
||||||
|
{
|
||||||
|
if (selected_file_paths.is_empty())
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
|
StringBuilder copy_text;
|
||||||
|
for (auto& path : selected_file_paths) {
|
||||||
|
auto url = URL::create_with_file_protocol(path);
|
||||||
|
copy_text.appendff("{}\n", url);
|
||||||
|
}
|
||||||
|
GUI::Clipboard::the().set_data(copy_text.build().bytes(), "text/uri-list");
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_paste(const String& target_directory, GUI::Window* window)
|
||||||
|
{
|
||||||
|
auto data_and_type = GUI::Clipboard::the().data_and_type();
|
||||||
|
if (data_and_type.mime_type != "text/uri-list") {
|
||||||
|
dbgln("Cannot paste clipboard type {}", data_and_type.mime_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto copied_lines = String::copy(data_and_type.data).split('\n');
|
||||||
|
if (copied_lines.is_empty()) {
|
||||||
|
dbgln("No files to paste");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& uri_as_string : copied_lines) {
|
||||||
|
if (uri_as_string.is_empty())
|
||||||
|
continue;
|
||||||
|
URL url = uri_as_string;
|
||||||
|
if (!url.is_valid() || url.protocol() != "file") {
|
||||||
|
dbgln("Cannot paste URI {}", uri_as_string);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto new_path = String::formatted("{}/{}", target_directory, url.basename());
|
||||||
|
if (!FileUtils::copy_file_or_directory(url.path(), new_path)) {
|
||||||
|
auto error_message = String::formatted("Could not paste {}.", url.path());
|
||||||
|
GUI::MessageBox::show(window, error_message, "File Manager", GUI::MessageBox::Type::Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_properties(const String& container_dir_path, const String& path, const Vector<String>& selected, GUI::Window* window)
|
||||||
|
{
|
||||||
|
RefPtr<PropertiesDialog> properties;
|
||||||
|
if (selected.is_empty()) {
|
||||||
|
properties = window->add<PropertiesDialog>(path, true);
|
||||||
|
} else {
|
||||||
|
properties = window->add<PropertiesDialog>(selected.first(), access(container_dir_path.characters(), W_OK) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
properties->exec();
|
||||||
|
}
|
||||||
|
|
||||||
int run_in_desktop_mode(RefPtr<Core::ConfigFile> config)
|
int run_in_desktop_mode(RefPtr<Core::ConfigFile> config)
|
||||||
{
|
{
|
||||||
static constexpr const char* process_name = "FileManager (Desktop)";
|
static constexpr const char* process_name = "FileManager (Desktop)";
|
||||||
|
@ -141,6 +199,43 @@ int run_in_desktop_mode(RefPtr<Core::ConfigFile> config)
|
||||||
auto& directory_view = desktop_widget.add<DirectoryView>(DirectoryView::Mode::Desktop);
|
auto& directory_view = desktop_widget.add<DirectoryView>(DirectoryView::Mode::Desktop);
|
||||||
(void)directory_view;
|
(void)directory_view;
|
||||||
|
|
||||||
|
auto copy_action = GUI::CommonActions::make_copy_action(
|
||||||
|
[&](auto&) {
|
||||||
|
auto paths = directory_view.selected_file_paths();
|
||||||
|
|
||||||
|
if (paths.is_empty())
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
|
do_copy(paths);
|
||||||
|
},
|
||||||
|
window);
|
||||||
|
copy_action->set_enabled(false);
|
||||||
|
|
||||||
|
directory_view.on_selection_change = [&](const GUI::AbstractView& view) {
|
||||||
|
copy_action->set_enabled(!view.selection().is_empty());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto properties_action
|
||||||
|
= GUI::Action::create(
|
||||||
|
"Properties...", { Mod_Alt, Key_Return }, Gfx::Bitmap::load_from_file("/res/icons/16x16/properties.png"), [&](const GUI::Action&) {
|
||||||
|
String path = directory_view.path();
|
||||||
|
Vector<String> selected = directory_view.selected_file_paths();
|
||||||
|
|
||||||
|
show_properties(path, path, selected, directory_view.window());
|
||||||
|
},
|
||||||
|
window);
|
||||||
|
|
||||||
|
auto paste_action = GUI::CommonActions::make_paste_action(
|
||||||
|
[&](const GUI::Action&) {
|
||||||
|
do_paste(directory_view.path(), directory_view.window());
|
||||||
|
},
|
||||||
|
window);
|
||||||
|
paste_action->set_enabled(GUI::Clipboard::the().mime_type() == "text/uri-list" && access(directory_view.path().characters(), W_OK) == 0);
|
||||||
|
|
||||||
|
GUI::Clipboard::the().on_change = [&](const String& data_type) {
|
||||||
|
paste_action->set_enabled(data_type == "text/uri-list" && access(directory_view.path().characters(), W_OK) == 0);
|
||||||
|
};
|
||||||
|
|
||||||
auto desktop_view_context_menu = GUI::Menu::construct("Directory View");
|
auto desktop_view_context_menu = GUI::Menu::construct("Directory View");
|
||||||
|
|
||||||
auto file_manager_action = GUI::Action::create("Show in FileManager...", {}, Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-folder.png"), [&](const GUI::Action&) {
|
auto file_manager_action = GUI::Action::create("Show in FileManager...", {}, Gfx::Bitmap::load_from_file("/res/icons/16x16/filetype-folder.png"), [&](const GUI::Action&) {
|
||||||
|
@ -153,17 +248,25 @@ int run_in_desktop_mode(RefPtr<Core::ConfigFile> config)
|
||||||
|
|
||||||
desktop_view_context_menu->add_action(directory_view.mkdir_action());
|
desktop_view_context_menu->add_action(directory_view.mkdir_action());
|
||||||
desktop_view_context_menu->add_action(directory_view.touch_action());
|
desktop_view_context_menu->add_action(directory_view.touch_action());
|
||||||
|
desktop_view_context_menu->add_action(paste_action);
|
||||||
desktop_view_context_menu->add_separator();
|
desktop_view_context_menu->add_separator();
|
||||||
|
|
||||||
desktop_view_context_menu->add_action(file_manager_action);
|
desktop_view_context_menu->add_action(file_manager_action);
|
||||||
desktop_view_context_menu->add_action(directory_view.open_terminal_action());
|
desktop_view_context_menu->add_action(directory_view.open_terminal_action());
|
||||||
desktop_view_context_menu->add_separator();
|
desktop_view_context_menu->add_separator();
|
||||||
desktop_view_context_menu->add_action(display_properties_action);
|
desktop_view_context_menu->add_action(display_properties_action);
|
||||||
|
|
||||||
|
auto desktop_context_menu = GUI::Menu::construct("Directory View Directory");
|
||||||
|
desktop_context_menu->add_action(copy_action);
|
||||||
|
desktop_context_menu->add_action(paste_action);
|
||||||
|
desktop_context_menu->add_action(directory_view.delete_action());
|
||||||
|
desktop_context_menu->add_separator();
|
||||||
|
desktop_context_menu->add_action(properties_action);
|
||||||
|
|
||||||
directory_view.on_context_menu_request = [&](const GUI::ModelIndex& index, const GUI::ContextMenuEvent& event) {
|
directory_view.on_context_menu_request = [&](const GUI::ModelIndex& index, const GUI::ContextMenuEvent& event) {
|
||||||
if (!index.is_valid())
|
if (!index.is_valid())
|
||||||
desktop_view_context_menu->popup(event.screen_position());
|
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");
|
auto wm_config = Core::ConfigFile::get_for_app("WindowManager");
|
||||||
|
@ -325,18 +428,14 @@ int run_in_windowed_mode(RefPtr<Core::ConfigFile> config, String initial_locatio
|
||||||
[&](auto&) {
|
[&](auto&) {
|
||||||
auto paths = directory_view.selected_file_paths();
|
auto paths = directory_view.selected_file_paths();
|
||||||
|
|
||||||
if (!paths.size())
|
if (paths.is_empty())
|
||||||
paths = tree_view_selected_file_paths();
|
paths = tree_view_selected_file_paths();
|
||||||
|
|
||||||
if (paths.is_empty())
|
if (paths.is_empty())
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
StringBuilder copy_text;
|
do_copy(paths);
|
||||||
for (auto& path : paths) {
|
refresh_tree_view();
|
||||||
auto url = URL::create_with_file_protocol(path);
|
|
||||||
copy_text.appendff("{}\n", url);
|
|
||||||
}
|
|
||||||
GUI::Clipboard::the().set_data(copy_text.build().bytes(), "text/uri-list");
|
|
||||||
},
|
},
|
||||||
window);
|
window);
|
||||||
copy_action->set_enabled(false);
|
copy_action->set_enabled(false);
|
||||||
|
@ -357,63 +456,31 @@ int run_in_windowed_mode(RefPtr<Core::ConfigFile> config, String initial_locatio
|
||||||
selected = tree_view_selected_file_paths();
|
selected = tree_view_selected_file_paths();
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<PropertiesDialog> properties;
|
show_properties(container_dir_path, path, selected, directory_view.window());
|
||||||
if (selected.is_empty()) {
|
|
||||||
properties = window->add<PropertiesDialog>(path, true);
|
|
||||||
} else {
|
|
||||||
properties = window->add<PropertiesDialog>(selected.first(), access(container_dir_path.characters(), W_OK) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
properties->exec();
|
|
||||||
},
|
},
|
||||||
window);
|
window);
|
||||||
|
|
||||||
auto do_paste = [&](const GUI::Action& action) {
|
auto paste_action = GUI::CommonActions::make_paste_action(
|
||||||
auto data_and_type = GUI::Clipboard::the().data_and_type();
|
[&](const GUI::Action& action) {
|
||||||
if (data_and_type.mime_type != "text/uri-list") {
|
String target_directory;
|
||||||
dbgln("Cannot paste clipboard type {}", data_and_type.mime_type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto copied_lines = String::copy(data_and_type.data).split('\n');
|
|
||||||
if (copied_lines.is_empty()) {
|
|
||||||
dbgln("No files to paste");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AK::String target_directory;
|
|
||||||
if (action.activator() == directory_context_menu)
|
if (action.activator() == directory_context_menu)
|
||||||
target_directory = directory_view.selected_file_paths()[0];
|
target_directory = directory_view.selected_file_paths()[0];
|
||||||
else
|
else
|
||||||
target_directory = directory_view.path();
|
target_directory = directory_view.path();
|
||||||
|
do_paste(target_directory, directory_view.window());
|
||||||
for (auto& uri_as_string : copied_lines) {
|
|
||||||
if (uri_as_string.is_empty())
|
|
||||||
continue;
|
|
||||||
URL url = uri_as_string;
|
|
||||||
if (!url.is_valid() || url.protocol() != "file") {
|
|
||||||
dbgln("Cannot paste URI {}", uri_as_string);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto new_path = String::formatted("{}/{}", target_directory, url.basename());
|
|
||||||
if (!FileUtils::copy_file_or_directory(url.path(), new_path)) {
|
|
||||||
auto error_message = String::formatted("Could not paste {}.", url.path());
|
|
||||||
GUI::MessageBox::show(window, error_message, "File Manager", GUI::MessageBox::Type::Error);
|
|
||||||
} else {
|
|
||||||
refresh_tree_view();
|
refresh_tree_view();
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto paste_action = GUI::CommonActions::make_paste_action(
|
|
||||||
[&](const GUI::Action& action) {
|
|
||||||
do_paste(action);
|
|
||||||
},
|
},
|
||||||
window);
|
window);
|
||||||
|
|
||||||
auto folder_specific_paste_action = GUI::CommonActions::make_paste_action(
|
auto folder_specific_paste_action = GUI::CommonActions::make_paste_action(
|
||||||
[&](const GUI::Action& action) {
|
[&](const GUI::Action& action) {
|
||||||
do_paste(action);
|
String target_directory;
|
||||||
|
if (action.activator() == directory_context_menu)
|
||||||
|
target_directory = directory_view.selected_file_paths()[0];
|
||||||
|
else
|
||||||
|
target_directory = directory_view.path();
|
||||||
|
do_paste(target_directory, directory_view.window());
|
||||||
|
refresh_tree_view();
|
||||||
},
|
},
|
||||||
window);
|
window);
|
||||||
|
|
||||||
|
@ -697,7 +764,7 @@ int run_in_windowed_mode(RefPtr<Core::ConfigFile> config, String initial_locatio
|
||||||
directory_view.delete_action().set_enabled(!tree_view.selection().is_empty());
|
directory_view.delete_action().set_enabled(!tree_view.selection().is_empty());
|
||||||
};
|
};
|
||||||
|
|
||||||
tree_view.on_focus_change = [&]([[ maybe_unused ]] const bool has_focus, [[ maybe_unused ]] const GUI::FocusSource source) {
|
tree_view.on_focus_change = [&]([[maybe_unused]] const bool has_focus, [[maybe_unused]] const GUI::FocusSource source) {
|
||||||
focus_dependent_delete_action->set_enabled((!tree_view.selection().is_empty() && has_focus)
|
focus_dependent_delete_action->set_enabled((!tree_view.selection().is_empty() && has_focus)
|
||||||
|| !directory_view.current_view().selection().is_empty());
|
|| !directory_view.current_view().selection().is_empty());
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue