UI/Qt: Add functionality for reopening recently-closed tabs
Record when we close a tab, and map Ctrl+Shift+T to an action that opens the most recently closed one.
This commit is contained in:
parent
9b53baa652
commit
f0cb7d9a6f
4 changed files with 85 additions and 2 deletions
|
|
@ -254,6 +254,14 @@ void Application::update_bookmarks_bar_display(bool show_bookmarks_bar) const
|
|||
}
|
||||
}
|
||||
|
||||
void Application::update_reopen_recently_closed_actions() const
|
||||
{
|
||||
for (auto* widget : QApplication::topLevelWidgets()) {
|
||||
if (auto* window = as_if<BrowserWindow>(widget))
|
||||
window->update_reopen_recently_closed_action();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::show_bookmark_context_menu(Gfx::IntPoint content_position, Optional<WebView::BookmarkItem const&> item, Optional<String const&> target_folder_id)
|
||||
{
|
||||
if (auto* active_tab = this->active_tab()) {
|
||||
|
|
@ -423,4 +431,9 @@ void Application::on_devtools_disabled() const
|
|||
m_active_window->on_devtools_disabled();
|
||||
}
|
||||
|
||||
void Application::on_recently_closed_entries_changed() const
|
||||
{
|
||||
update_reopen_recently_closed_actions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public:
|
|||
void set_active_window(BrowserWindow& w) { m_active_window = &w; }
|
||||
|
||||
Tab* active_tab() const { return m_active_window ? m_active_window->current_tab() : nullptr; }
|
||||
void update_reopen_recently_closed_actions() const;
|
||||
|
||||
private:
|
||||
explicit Application();
|
||||
|
|
@ -59,6 +60,7 @@ private:
|
|||
|
||||
virtual void on_devtools_enabled() const override;
|
||||
virtual void on_devtools_disabled() const override;
|
||||
virtual void on_recently_closed_entries_changed() const override;
|
||||
|
||||
OwnPtr<QApplication> m_application;
|
||||
BrowserWindow* m_active_window { nullptr };
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
* Copyright (c) 2022, Matthew Costa <ucosty@gmail.com>
|
||||
* Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
|
||||
* Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2024-2025, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2024-2026, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2025, Simon Farre <simon.farre.cx@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#include <AK/RefPtr.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibWebView/Application.h>
|
||||
#include <LibWebView/HistoryStore.h>
|
||||
#include <UI/Qt/Application.h>
|
||||
#include <UI/Qt/BrowserWindow.h>
|
||||
#include <UI/Qt/Icon.h>
|
||||
|
|
@ -42,6 +43,25 @@
|
|||
|
||||
namespace Ladybird {
|
||||
|
||||
static QString reopen_recently_closed_action_text(Optional<WebView::RecentlyClosedEntry const&> entry)
|
||||
{
|
||||
if (entry.has_value() && entry->was_window)
|
||||
return "&Reopen Recently Closed Window";
|
||||
|
||||
return "&Reopen Recently Closed Tab";
|
||||
}
|
||||
|
||||
static Vector<URL::URL> recently_closed_urls_for_window(TabWidget const& tabs_container)
|
||||
{
|
||||
Vector<URL::URL> urls;
|
||||
urls.ensure_capacity(tabs_container.count());
|
||||
|
||||
for (int index = 0; index < tabs_container.count(); ++index)
|
||||
urls.append(tabs_container.tab(index)->view().url());
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
FullscreenMode::FullscreenMode(BrowserWindow* window, ExitFullscreenButton* exit_button)
|
||||
: QObject(window)
|
||||
, m_window(window)
|
||||
|
|
@ -216,6 +236,12 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
|
|||
m_hamburger_menu->addAction(m_new_window_action);
|
||||
file_menu->addAction(m_new_window_action);
|
||||
|
||||
m_reopen_recently_closed_tab_action = new QAction("&Reopen Recently Closed Tab", this);
|
||||
m_reopen_recently_closed_tab_action->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_T));
|
||||
m_hamburger_menu->addAction(m_reopen_recently_closed_tab_action);
|
||||
file_menu->addAction(m_reopen_recently_closed_tab_action);
|
||||
update_reopen_recently_closed_action();
|
||||
|
||||
auto* close_current_tab_action = new QAction("&Close Current Tab", this);
|
||||
close_current_tab_action->setIcon(load_icon_from_uri("resource://icons/16x16/close-tab.png"sv));
|
||||
close_current_tab_action->setShortcuts(QKeySequence::keyBindings(QKeySequence::StandardKey::Close));
|
||||
|
|
@ -328,6 +354,18 @@ BrowserWindow::BrowserWindow(Vector<URL::URL> const& initial_urls, IsPopupWindow
|
|||
QObject::connect(m_new_window_action, &QAction::triggered, this, [] {
|
||||
(void)Application::the().new_window({ WebView::Application::settings().new_tab_page_url() });
|
||||
});
|
||||
QObject::connect(m_reopen_recently_closed_tab_action, &QAction::triggered, this, [this] {
|
||||
auto recently_closed_entry = Application::history_store().pop_most_recently_closed_entry();
|
||||
if (recently_closed_entry.has_value()) {
|
||||
if (recently_closed_entry->was_window) {
|
||||
auto& window = Application::the().new_window(recently_closed_entry->urls);
|
||||
window.activate_tab(static_cast<int>(recently_closed_entry->active_tab_index));
|
||||
} else if (!recently_closed_entry->urls.is_empty()) {
|
||||
new_tab_from_url(recently_closed_entry->urls[0], Web::HTML::ActivateTab::Yes);
|
||||
}
|
||||
}
|
||||
Application::the().update_reopen_recently_closed_actions();
|
||||
});
|
||||
QObject::connect(open_file_action, &QAction::triggered, this, &BrowserWindow::open_file);
|
||||
|
||||
m_exit_button = new ExitFullscreenButton { this };
|
||||
|
|
@ -520,11 +558,26 @@ void BrowserWindow::activate_tab(int index)
|
|||
void BrowserWindow::definitely_close_tab(int index)
|
||||
{
|
||||
auto* tab = m_tabs_container->tab(index);
|
||||
auto url = tab->view().url();
|
||||
m_tabs_container->remove_tab(index);
|
||||
Application::history_store().record_closed_tab(url);
|
||||
Application::the().update_reopen_recently_closed_actions();
|
||||
tab->deleteLater();
|
||||
|
||||
if (m_tabs_container->count() == 0)
|
||||
if (m_tabs_container->count() == 0) {
|
||||
m_should_record_closed_window_on_close = false;
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::update_reopen_recently_closed_action()
|
||||
{
|
||||
if (!m_reopen_recently_closed_tab_action)
|
||||
return;
|
||||
|
||||
auto recently_closed_entry = Application::history_store().most_recently_closed_entry();
|
||||
m_reopen_recently_closed_tab_action->setText(reopen_recently_closed_action_text(recently_closed_entry));
|
||||
m_reopen_recently_closed_tab_action->setEnabled(recently_closed_entry.has_value());
|
||||
}
|
||||
|
||||
void BrowserWindow::move_tab(int old_index, int new_index)
|
||||
|
|
@ -804,6 +857,13 @@ void BrowserWindow::wheelEvent(QWheelEvent* event)
|
|||
|
||||
void BrowserWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
Optional<Vector<URL::URL>> recently_closed_window_urls;
|
||||
size_t recently_closed_window_active_tab_index { 0 };
|
||||
if (m_should_record_closed_window_on_close && m_tabs_container->count() > 0) {
|
||||
recently_closed_window_urls = recently_closed_urls_for_window(*m_tabs_container);
|
||||
recently_closed_window_active_tab_index = static_cast<size_t>(m_tabs_container->current_index());
|
||||
}
|
||||
|
||||
if (m_is_popup_window == IsPopupWindow::No) {
|
||||
Settings::the()->set_last_position(pos());
|
||||
Settings::the()->set_last_size(size());
|
||||
|
|
@ -813,6 +873,11 @@ void BrowserWindow::closeEvent(QCloseEvent* event)
|
|||
QObject::deleteLater();
|
||||
|
||||
QMainWindow::closeEvent(event);
|
||||
|
||||
if (event->isAccepted() && recently_closed_window_urls.has_value()) {
|
||||
Application::history_store().record_closed_window(recently_closed_window_urls.release_value(), recently_closed_window_active_tab_index);
|
||||
Application::the().update_reopen_recently_closed_actions();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ public:
|
|||
|
||||
void rebuild_bookmarks_menu();
|
||||
void update_bookmarks_bar_display(bool show_bookmarks_bar);
|
||||
void update_reopen_recently_closed_action();
|
||||
|
||||
double refresh_rate() const { return m_refresh_rate; }
|
||||
|
||||
|
|
@ -170,6 +171,7 @@ private:
|
|||
|
||||
QAction* m_new_tab_action { nullptr };
|
||||
QAction* m_new_window_action { nullptr };
|
||||
QAction* m_reopen_recently_closed_tab_action { nullptr };
|
||||
QAction* m_find_in_page_action { nullptr };
|
||||
|
||||
IsPopupWindow m_is_popup_window { IsPopupWindow::No };
|
||||
|
|
@ -178,6 +180,7 @@ private:
|
|||
FullscreenMode* m_fullscreen_mode { nullptr };
|
||||
// Determine if window should restore to maximized or normal, when exiting fullscreen.
|
||||
bool m_restore_to_maximized { false };
|
||||
bool m_should_record_closed_window_on_close { true };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue