diff options
-rw-r--r-- | Userland/Services/Taskbar/QuickLaunchWidget.cpp | 101 | ||||
-rw-r--r-- | Userland/Services/Taskbar/QuickLaunchWidget.h | 28 |
2 files changed, 89 insertions, 40 deletions
diff --git a/Userland/Services/Taskbar/QuickLaunchWidget.cpp b/Userland/Services/Taskbar/QuickLaunchWidget.cpp index f968a27786..f18685b86f 100644 --- a/Userland/Services/Taskbar/QuickLaunchWidget.cpp +++ b/Userland/Services/Taskbar/QuickLaunchWidget.cpp @@ -7,8 +7,10 @@ #include "QuickLaunchWidget.h" #include <LibConfig/Client.h> #include <LibCore/MimeData.h> +#include <LibCore/System.h> #include <LibGUI/BoxLayout.h> #include <LibGUI/Menu.h> +#include <LibGUI/MessageBox.h> #include <serenity.h> namespace Taskbar { @@ -16,6 +18,27 @@ namespace Taskbar { constexpr auto quick_launch = "QuickLaunch"sv; constexpr int quick_launch_button_size = 24; +ErrorOr<void> QuickLaunchEntryAppFile::launch() const +{ + auto executable = m_app_file->executable(); + + pid_t pid = TRY(Core::System::fork()); + if (pid == 0) { + if (chdir(Core::StandardPaths::home_directory().characters()) < 0) { + perror("chdir"); + exit(1); + } + if (m_app_file->run_in_terminal()) + execl("/bin/Terminal", "Terminal", "-e", executable.characters(), nullptr); + else + execl(executable.characters(), executable.characters(), nullptr); + perror("execl"); + VERIFY_NOT_REACHED(); + } else + TRY(Core::System::disown(pid)); + return {}; +} + QuickLaunchWidget::QuickLaunchWidget() { set_shrink_to_fit(true); @@ -36,10 +59,11 @@ QuickLaunchWidget::QuickLaunchWidget() auto keys = Config::list_keys("Taskbar", quick_launch); for (auto& name : keys) { - auto af_name = Config::read_string("Taskbar", quick_launch, name); - auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, af_name); - auto af = Desktop::AppFile::open(af_path); - add_or_adjust_button(name, af); + auto value = Config::read_string("Taskbar", quick_launch, name); + auto entry = QuickLaunchEntry::create_from_config_value(value); + if (!entry) + continue; + add_or_adjust_button(name, entry.release_nonnull()); } } @@ -47,40 +71,38 @@ QuickLaunchWidget::~QuickLaunchWidget() { } -void QuickLaunchWidget::add_or_adjust_button(String const& button_name, NonnullRefPtr<Desktop::AppFile> app_file) +OwnPtr<QuickLaunchEntry> QuickLaunchEntry::create_from_config_value(StringView value) +{ + if (value.ends_with(".af")) { + auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, value); + return make<QuickLaunchEntryAppFile>(Desktop::AppFile::open(af_path)); + } + return {}; +} + +OwnPtr<QuickLaunchEntry> QuickLaunchEntry::create_from_path(StringView path) +{ + if (path.ends_with(".af")) + return make<QuickLaunchEntryAppFile>(Desktop::AppFile::open(path)); + return {}; +} + +void QuickLaunchWidget::add_or_adjust_button(String const& button_name, NonnullOwnPtr<QuickLaunchEntry>&& entry) { - if (!app_file->is_valid()) - return; auto button = find_child_of_type_named<GUI::Button>(button_name); - if (!button) { + if (!button) button = &add<GUI::Button>(); - } - auto app_executable = app_file->executable(); - auto app_run_in_terminal = app_file->run_in_terminal(); + button->set_fixed_size(quick_launch_button_size, quick_launch_button_size); button->set_button_style(Gfx::ButtonStyle::Coolbar); - button->set_icon(app_file->icon().bitmap_for_size(16)); - button->set_tooltip(app_file->name()); + auto icon = entry->icon(); + button->set_icon(icon.bitmap_for_size(16)); + button->set_tooltip(entry->name()); button->set_name(button_name); - button->on_click = [app_executable, app_run_in_terminal](auto) { - pid_t pid = fork(); - if (pid < 0) { - perror("fork"); - } else if (pid == 0) { - if (chdir(Core::StandardPaths::home_directory().characters()) < 0) { - perror("chdir"); - exit(1); - } - if (app_run_in_terminal) - execl("/bin/Terminal", "Terminal", "-e", app_executable.characters(), nullptr); - else - execl(app_executable.characters(), app_executable.characters(), nullptr); - perror("execl"); - VERIFY_NOT_REACHED(); - } else { - if (disown(pid) < 0) - perror("disown"); - } + button->on_click = [entry = move(entry), this](auto) { + auto result = entry->launch(); + if (result.is_error()) + GUI::MessageBox::show_error(window(), String::formatted("Failed to open quick launch entry: {}", result.release_error())); }; button->on_context_menu_request = [this, button_name](auto& context_menu_event) { m_context_menu_app_name = button_name; @@ -100,9 +122,10 @@ void QuickLaunchWidget::config_key_was_removed(String const& domain, String cons void QuickLaunchWidget::config_string_did_change(String const& domain, String const& group, String const& key, String const& value) { if (domain == "Taskbar" && group == quick_launch) { - auto af_path = String::formatted("{}/{}", Desktop::AppFile::APP_FILES_DIRECTORY, value); - auto af = Desktop::AppFile::open(af_path); - add_or_adjust_button(key, af); + auto entry = QuickLaunchEntry::create_from_config_value(value); + if (!entry) + return; + add_or_adjust_button(key, entry.release_nonnull()); } } @@ -113,10 +136,10 @@ void QuickLaunchWidget::drop_event(GUI::DropEvent& event) if (event.mime_data().has_urls()) { auto urls = event.mime_data().urls(); for (auto& url : urls) { - auto af = Desktop::AppFile::open(url.path()); - if (af->is_valid()) { - auto item_name = af->name().replace(" ", "", true); - add_or_adjust_button(item_name, af); + auto entry = QuickLaunchEntry::create_from_path(url.path()); + if (entry) { + auto item_name = entry->name().replace(" ", "", true); + add_or_adjust_button(item_name, entry.release_nonnull()); Config::write_string("Taskbar", quick_launch, item_name, url.basename()); } } diff --git a/Userland/Services/Taskbar/QuickLaunchWidget.h b/Userland/Services/Taskbar/QuickLaunchWidget.h index 6f90c67c2f..fccecf88d9 100644 --- a/Userland/Services/Taskbar/QuickLaunchWidget.h +++ b/Userland/Services/Taskbar/QuickLaunchWidget.h @@ -13,6 +13,32 @@ namespace Taskbar { +class QuickLaunchEntry { +public: + virtual ~QuickLaunchEntry() = default; + virtual ErrorOr<void> launch() const = 0; + virtual GUI::Icon icon() const = 0; + virtual String name() const = 0; + + static OwnPtr<QuickLaunchEntry> create_from_config_value(StringView path); + static OwnPtr<QuickLaunchEntry> create_from_path(StringView path); +}; + +class QuickLaunchEntryAppFile : public QuickLaunchEntry { +public: + explicit QuickLaunchEntryAppFile(NonnullRefPtr<Desktop::AppFile> file) + : m_app_file(move(file)) + { + } + + virtual ErrorOr<void> launch() const override; + virtual GUI::Icon icon() const override { return m_app_file->icon(); } + virtual String name() const override { return m_app_file->name(); } + +private: + NonnullRefPtr<Desktop::AppFile> m_app_file; +}; + class QuickLaunchWidget : public GUI::Frame , public Config::Listener { C_OBJECT(QuickLaunchWidget); @@ -27,7 +53,7 @@ public: private: QuickLaunchWidget(); - void add_or_adjust_button(String const&, NonnullRefPtr<Desktop::AppFile>); + void add_or_adjust_button(String const&, NonnullOwnPtr<QuickLaunchEntry>&&); RefPtr<GUI::Menu> m_context_menu; RefPtr<GUI::Action> m_context_menu_default_action; String m_context_menu_app_name; |