diff --git a/Base/home/anon/.config/CommonLocations.json b/Base/home/anon/.config/CommonLocations.json new file mode 100644 index 0000000000..e9b5ea2696 --- /dev/null +++ b/Base/home/anon/.config/CommonLocations.json @@ -0,0 +1,7 @@ +[ + { "name": "Root", "path": "/" }, + { "name": "Home", "path": "/home/anon" }, + { "name": "Documents", "path": "/home/anon/Documents" }, + { "name": "Desktop", "path": "/home/anon/Desktop" }, + { "name": "Downloads", "path": "/home/anon/Downloads" } +] diff --git a/Userland/Libraries/LibGUI/CMakeLists.txt b/Userland/Libraries/LibGUI/CMakeLists.txt index eba646ac93..36a6a92b5e 100644 --- a/Userland/Libraries/LibGUI/CMakeLists.txt +++ b/Userland/Libraries/LibGUI/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCES ColorInput.cpp ColorPicker.cpp ColumnsView.cpp + CommonLocationsProvider.cpp ComboBox.cpp Command.cpp Desktop.cpp diff --git a/Userland/Libraries/LibGUI/CommonLocationsProvider.cpp b/Userland/Libraries/LibGUI/CommonLocationsProvider.cpp new file mode 100644 index 0000000000..2fa1517851 --- /dev/null +++ b/Userland/Libraries/LibGUI/CommonLocationsProvider.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace GUI { + +static bool s_initialized = false; +static Vector s_common_locations; + +static void initialize_if_needed() +{ + if (s_initialized) + return; + + auto user_config = String::formatted("{}/CommonLocations.json", Core::StandardPaths::config_directory()); + if (Core::File::exists(user_config)) { + CommonLocationsProvider::load_from_json(user_config); + return; + } + + // Fallback : If the user doesn't have custom locations, use some default ones. + s_common_locations.append({ "Root", "/" }); + s_common_locations.append({ "Home", Core::StandardPaths::home_directory() }); + s_common_locations.append({ "Downloads", Core::StandardPaths::downloads_directory() }); + s_initialized = true; +} + +void CommonLocationsProvider::load_from_json(const String& json_path) +{ + auto file = Core::File::construct(json_path); + if (!file->open(Core::IODevice::ReadOnly)) { + dbgln("Unable to open {}", file->filename()); + return; + } + + auto json = JsonValue::from_string(file->read_all()); + if (!json.has_value()) { + dbgln("Common locations file {} is not a valid JSON file.", file->filename()); + return; + } + if (!json.value().is_array()) { + dbgln("Common locations file {} should contain a JSON array.", file->filename()); + return; + } + + s_common_locations.clear(); + auto contents = json.value().as_array(); + for (auto i = 0; i < contents.size(); ++i) { + auto entry_value = contents.at(i); + if (!entry_value.is_object()) + continue; + auto entry = entry_value.as_object(); + auto name = entry.get("name").to_string(); + auto path = entry.get("path").to_string(); + s_common_locations.append({ name, path }); + } + + s_initialized = true; +} + +const Vector& CommonLocationsProvider::common_locations() +{ + initialize_if_needed(); + return s_common_locations; +} + +} diff --git a/Userland/Libraries/LibGUI/CommonLocationsProvider.h b/Userland/Libraries/LibGUI/CommonLocationsProvider.h new file mode 100644 index 0000000000..b5d3faff59 --- /dev/null +++ b/Userland/Libraries/LibGUI/CommonLocationsProvider.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace GUI { + +class CommonLocationsProvider { +public: + struct CommonLocation { + String name; + String path; + }; + + static void load_from_json(const String& json_path); + static const Vector& common_locations(); +}; + +} diff --git a/Userland/Libraries/LibGUI/FilePicker.cpp b/Userland/Libraries/LibGUI/FilePicker.cpp index 2735817522..1685dcacea 100644 --- a/Userland/Libraries/LibGUI/FilePicker.cpp +++ b/Userland/Libraries/LibGUI/FilePicker.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -207,14 +208,20 @@ FilePicker::FilePicker(Window* parent_window, Mode mode, const StringView& file_ } }; - auto& common_locations_frame = *widget.find_descendant_of_type_named("common_locations_frame"); + auto& common_locations_frame = *widget.find_descendant_of_type_named("common_locations_frame"); common_locations_frame.set_background_role(Gfx::ColorRole::Tray); - auto add_common_location_button = [&](auto& name, String path) -> GUI::Button& { + m_model->on_complete = [&] { + for (auto location_button : m_common_location_buttons) + location_button.button.set_checked(m_model->root_path() == location_button.path); + }; + + for (auto& location : CommonLocationsProvider::common_locations()) { + String path = location.path; auto& button = common_locations_frame.add(); button.set_button_style(Gfx::ButtonStyle::Tray); button.set_foreground_role(Gfx::ColorRole::TrayText); button.set_text_alignment(Gfx::TextAlignment::CenterLeft); - button.set_text(move(name)); + button.set_text(location.name); button.set_icon(FileIconProvider::icon_for_path(path).bitmap_for_size(16)); button.set_fixed_height(22); button.set_checkable(true); @@ -222,26 +229,8 @@ FilePicker::FilePicker(Window* parent_window, Mode mode, const StringView& file_ button.on_click = [this, path] { set_path(path); }; - return button; - }; - - auto& root_button = add_common_location_button("Root", "/"); - auto& home_button = add_common_location_button("Home", Core::StandardPaths::home_directory()); - auto& desktop_button = add_common_location_button("Desktop", Core::StandardPaths::desktop_directory()); - - m_model->on_complete = [&] { - if (m_model->root_path() == Core::StandardPaths::home_directory()) { - home_button.set_checked(true); - } else if (m_model->root_path() == Core::StandardPaths::desktop_directory()) { - desktop_button.set_checked(true); - } else if (m_model->root_path() == "/") { - root_button.set_checked(true); - } else { - home_button.set_checked(false); - desktop_button.set_checked(false); - root_button.set_checked(false); - } - }; + m_common_location_buttons.append({ path, button }); + } set_path(path); } diff --git a/Userland/Libraries/LibGUI/FilePicker.h b/Userland/Libraries/LibGUI/FilePicker.h index eeb089d4c4..595a646522 100644 --- a/Userland/Libraries/LibGUI/FilePicker.h +++ b/Userland/Libraries/LibGUI/FilePicker.h @@ -59,12 +59,18 @@ private: } } + struct CommonLocationButton { + String path; + Button& button; + }; + RefPtr m_view; NonnullRefPtr m_model; LexicalPath m_selected_file; RefPtr m_filename_textbox; RefPtr m_location_textbox; + Vector m_common_location_buttons; RefPtr m_context_menu; Mode m_mode { Mode::Open }; };