diff --git a/Userland/Applications/Browser/BookmarksBarWidget.cpp b/Userland/Applications/Browser/BookmarksBarWidget.cpp index ef9af48a60..a84975debe 100644 --- a/Userland/Applications/Browser/BookmarksBarWidget.cpp +++ b/Userland/Applications/Browser/BookmarksBarWidget.cpp @@ -25,19 +25,93 @@ */ #include "BookmarksBarWidget.h" +#include #include #include #include +#include #include #include #include #include +#include #include #include #include namespace Browser { +namespace { + +class BookmarkEditor final : public GUI::Dialog { + C_OBJECT(BookmarkEditor) + +public: + static Vector + edit_bookmark(Window* parent_window, const StringView& title, const StringView& url) + { + auto editor = BookmarkEditor::construct(parent_window, title, url); + editor->set_title("Edit Bookmark"); + + if (editor->exec() == Dialog::ExecOK) { + return Vector { editor->title(), editor->url() }; + } + + return {}; + } + +private: + BookmarkEditor(Window* parent_window, const StringView& title, const StringView& url) + : Dialog(parent_window) + { + auto& widget = set_main_widget(); + if (!widget.load_from_gml(edit_bookmark_gml)) + VERIFY_NOT_REACHED(); + + set_resizable(false); + resize(260, 85); + + m_title_textbox = *widget.find_descendant_of_type_named("title_textbox"); + m_title_textbox->set_text(title); + m_title_textbox->set_focus(true); + m_title_textbox->select_all(); + m_title_textbox->on_return_pressed = [this] { + done(Dialog::ExecOK); + }; + + m_url_textbox = *widget.find_descendant_of_type_named("url_textbox"); + m_url_textbox->set_text(url); + m_url_textbox->on_return_pressed = [this] { + done(Dialog::ExecOK); + }; + + auto& ok_button = *widget.find_descendant_of_type_named("ok_button"); + ok_button.on_click = [this](auto) { + done(Dialog::ExecOK); + }; + + auto& cancel_button = *widget.find_descendant_of_type_named("cancel_button"); + cancel_button.on_click = [this](auto) { + done(Dialog::ExecCancel); + }; + } + + String title() const + { + return m_title_textbox->text(); + } + + String url() const + { + return m_url_textbox->text(); + } + + RefPtr m_title_textbox; + RefPtr m_url_textbox; +}; + +} + static BookmarksBarWidget* s_the; BookmarksBarWidget& BookmarksBarWidget::the() @@ -80,6 +154,10 @@ BookmarksBarWidget::BookmarksBarWidget(const String& bookmarks_file, bool enable if (on_bookmark_click) on_bookmark_click(m_context_menu_url, Mod_Ctrl); })); + m_context_menu->add_separator(); + m_context_menu->add_action(GUI::Action::create("Edit", [this](auto&) { + edit_bookmark(m_context_menu_url); + })); m_context_menu->add_action(GUI::Action::create("Delete", [this](auto&) { remove_bookmark(m_context_menu_url); })); @@ -224,6 +302,7 @@ bool BookmarksBarWidget::remove_bookmark(const String& url) return false; } + bool BookmarksBarWidget::add_bookmark(const String& url, const String& title) { Vector values; @@ -238,4 +317,29 @@ bool BookmarksBarWidget::add_bookmark(const String& url, const String& title) return false; } +bool BookmarksBarWidget::edit_bookmark(const String& url) +{ + for (int item_index = 0; item_index < model()->row_count(); ++item_index) { + auto item_title = model()->index(item_index, 0).data().to_string(); + auto item_url = model()->index(item_index, 1).data().to_string(); + + if (item_url == url) { + auto values = BookmarkEditor::edit_bookmark(window(), item_title, item_url); + bool item_replaced = false; + + if (!values.is_empty()) { + auto& json_model = *static_cast(model()); + item_replaced = json_model.set(item_index, move(values)); + + if (item_replaced) + json_model.store(); + } + + return item_replaced; + } + } + + return false; +} + } diff --git a/Userland/Applications/Browser/BookmarksBarWidget.h b/Userland/Applications/Browser/BookmarksBarWidget.h index 2eeed8fec5..99fa4af97e 100644 --- a/Userland/Applications/Browser/BookmarksBarWidget.h +++ b/Userland/Applications/Browser/BookmarksBarWidget.h @@ -52,6 +52,7 @@ public: bool contains_bookmark(const String& url); bool remove_bookmark(const String& url); bool add_bookmark(const String& url, const String& title); + bool edit_bookmark(const String& url); private: BookmarksBarWidget(const String&, bool enabled); diff --git a/Userland/Applications/Browser/CMakeLists.txt b/Userland/Applications/Browser/CMakeLists.txt index 4652ec8b11..7e7016a4cf 100644 --- a/Userland/Applications/Browser/CMakeLists.txt +++ b/Userland/Applications/Browser/CMakeLists.txt @@ -1,4 +1,5 @@ compile_gml(BrowserWindow.gml BrowserWindowGML.h browser_window_gml) +compile_gml(EditBookmark.gml EditBookmarkGML.h edit_bookmark_gml) compile_gml(Tab.gml TabGML.h tab_gml) set(SOURCES @@ -12,6 +13,7 @@ set(SOURCES Tab.cpp WindowActions.cpp BrowserWindowGML.h + EditBookmarkGML.h TabGML.h ) diff --git a/Userland/Applications/Browser/EditBookmark.gml b/Userland/Applications/Browser/EditBookmark.gml new file mode 100644 index 0000000000..e7f7dd7169 --- /dev/null +++ b/Userland/Applications/Browser/EditBookmark.gml @@ -0,0 +1,67 @@ +@GUI::Widget { + fixed_width: 260 + fixed_height: 85 + fill_with_background_color: true + + layout: @GUI::VerticalBoxLayout { + margins: [4, 4, 4, 4] + } + + + @GUI::Widget { + fixed_height: 24 + + layout: @GUI::HorizontalBoxLayout { + } + + @GUI::Label { + text: "Title:" + text_alignment: "CenterLeft" + fixed_width: 30 + } + + @GUI::TextBox { + name: "title_textbox" + } + } + + @GUI::Widget { + fixed_height: 24 + + layout: @GUI::HorizontalBoxLayout { + } + + @GUI::Label { + text: "URL:" + text_alignment: "CenterLeft" + fixed_width: 30 + } + + @GUI::TextBox { + name: "url_textbox" + } + } + + + @GUI::Widget { + fixed_height: 24 + + layout: @GUI::HorizontalBoxLayout { + } + + @GUI::Widget { + } + + @GUI::Button { + name: "ok_button" + text: "OK" + fixed_width: 75 + } + + @GUI::Button { + name: "cancel_button" + text: "Cancel" + fixed_width: 75 + } + } +}