Ladybird: Expanded toolbar with browser history and home button

This patch takes the browser history code from the Serenity browser and
wires it up to the QT interface. This is tied in with a few extra
toolbar buttons associated with each tab.
This commit is contained in:
Matthew Costa 2022-07-06 14:38:50 +01:00 committed by Andrew Kaster
parent 67ab6dd2e6
commit 7681ef25da
Notes: sideshowbarker 2024-07-18 00:41:35 +09:00
7 changed files with 194 additions and 9 deletions

View file

@ -37,6 +37,7 @@ set(SOURCES
RequestManagerQt.cpp
main.cpp
WebView.cpp
History.cpp
Tab.cpp
)

81
Ladybird/History.cpp Normal file
View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "History.h"
namespace Browser {
void History::dump() const
{
dbgln("Dump {} items(s)", m_items.size());
int i = 0;
for (auto& item : m_items) {
dbgln("[{}] {} '{}' {}", i, item.url, item.title, m_current == i ? '*' : ' ');
++i;
}
}
void History::push(const URL& url, String const& title)
{
if (!m_items.is_empty() && m_items[m_current].url == url)
return;
m_items.shrink(m_current + 1);
m_items.append(URLTitlePair {
.url = url,
.title = title,
});
m_current++;
}
History::URLTitlePair History::current() const
{
if (m_current == -1)
return {};
return m_items[m_current];
}
void History::go_back(int steps)
{
VERIFY(can_go_back(steps));
m_current -= steps;
}
void History::go_forward(int steps)
{
VERIFY(can_go_forward(steps));
m_current += steps;
}
void History::clear()
{
m_items = {};
m_current = -1;
}
void History::update_title(String const& title)
{
m_items[m_current].title = title;
}
Vector<StringView> History::get_back_title_history()
{
Vector<StringView> back_title_history;
for (int i = m_current - 1; i >= 0; i--) {
back_title_history.append(m_items[i].title);
}
return back_title_history;
}
Vector<StringView> History::get_forward_title_history()
{
Vector<StringView> forward_title_history;
for (int i = m_current + 1; i < static_cast<int>(m_items.size()); i++) {
forward_title_history.append(m_items[i].title);
}
return forward_title_history;
}
}

41
Ladybird/History.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/URL.h>
#include <AK/Vector.h>
namespace Browser {
class History {
public:
struct URLTitlePair {
URL url;
String title;
};
void dump() const;
void push(const URL& url, String const& title);
void update_title(String const& title);
URLTitlePair current() const;
Vector<StringView> get_back_title_history();
Vector<StringView> get_forward_title_history();
void go_back(int steps = 1);
void go_forward(int steps = 1);
bool can_go_back(int steps = 1) { return (m_current - steps) >= 0; }
bool can_go_forward(int steps = 1) { return (m_current + steps) < static_cast<int>(m_items.size()); }
void clear();
private:
Vector<URLTitlePair> m_items;
int m_current { -1 };
};
}

View file

@ -7,9 +7,9 @@
#include "Tab.h"
#include "BrowserWindow.h"
#include "History.h"
#include <QCoreApplication>
#include <QStatusBar>
#include <utility>
extern String s_serenity_resource_root;
@ -26,21 +26,67 @@ Tab::Tab(QMainWindow* window)
m_layout->addWidget(m_toolbar);
m_layout->addWidget(m_view);
auto back_icon_path = QString("%1/res/icons/16x16/go-back.png").arg(s_serenity_resource_root.characters());
auto forward_icon_path = QString("%1/res/icons/16x16/go-forward.png").arg(s_serenity_resource_root.characters());
auto home_icon_path = QString("%1/res/icons/16x16/go-home.png").arg(s_serenity_resource_root.characters());
auto reload_icon_path = QString("%1/res/icons/16x16/reload.png").arg(s_serenity_resource_root.characters());
auto* reload_action = new QAction(QIcon(reload_icon_path), "Reload");
reload_action->setShortcut(QKeySequence("Ctrl+R"));
m_toolbar->addAction(reload_action);
m_back_action = make<QAction>(QIcon(back_icon_path), "Back");
m_back_action->setShortcut(QKeySequence("Alt+Left"));
m_forward_action = make<QAction>(QIcon(forward_icon_path), "Forward");
m_forward_action->setShortcut(QKeySequence("Alt+Right"));
m_home_action = make<QAction>(QIcon(home_icon_path), "Home");
m_reload_action = make<QAction>(QIcon(reload_icon_path), "Reload");
m_reload_action->setShortcut(QKeySequence("Ctrl+R"));
m_toolbar->addAction(m_back_action);
m_toolbar->addAction(m_forward_action);
m_toolbar->addAction(m_reload_action);
m_toolbar->addAction(m_home_action);
m_toolbar->addWidget(m_location_edit);
QObject::connect(m_view, &WebView::linkHovered, m_window->statusBar(), &QStatusBar::showMessage);
QObject::connect(m_view, &WebView::linkUnhovered, m_window->statusBar(), &QStatusBar::clearMessage);
QObject::connect(m_view, &WebView::loadStarted, m_location_edit, &QLineEdit::setText);
QObject::connect(m_view, &WebView::loadStarted, [this](const URL& url) {
m_location_edit->setText(url.to_string().characters());
m_history.push(url, m_title.toUtf8().data());
});
QObject::connect(m_location_edit, &QLineEdit::returnPressed, this, &Tab::location_edit_return_pressed);
QObject::connect(m_view, &WebView::title_changed, this, &Tab::page_title_changed);
QObject::connect(m_view, &WebView::favicon_changed, this, &Tab::page_favicon_changed);
QObject::connect(reload_action, &QAction::triggered, this, &Tab::reload);
QObject::connect(m_back_action, &QAction::triggered, this, &Tab::back);
QObject::connect(m_forward_action, &QAction::triggered, this, &Tab::forward);
QObject::connect(m_home_action, &QAction::triggered, this, &Tab::home);
QObject::connect(m_reload_action, &QAction::triggered, this, &Tab::reload);
}
void Tab::navigate(QString const& url)
{
view().load(url.toUtf8().data());
}
void Tab::back()
{
if (!m_history.can_go_back())
return;
m_history.go_back();
view().load(m_history.current().url.to_string());
}
void Tab::forward()
{
if (!m_history.can_go_forward())
return;
m_history.go_forward();
view().load(m_history.current().url.to_string());
}
void Tab::home()
{
navigate("https://www.serenityos.org/");
}
void Tab::reload()
@ -50,11 +96,12 @@ void Tab::reload()
void Tab::location_edit_return_pressed()
{
view().load(m_location_edit->text().toUtf8().data());
navigate(m_location_edit->text());
}
void Tab::page_title_changed(QString title)
{
m_title = title;
emit title_changed(tab_index(), std::move(title));
}

View file

@ -7,6 +7,9 @@
#pragma once
#define AK_DONT_REPLACE_STD
#include "History.h"
#include "WebView.h"
#include <QBoxLayout>
#include <QLineEdit>
@ -20,10 +23,15 @@ public:
WebView& view() { return *m_view; }
void navigate(QString const&);
public slots:
void location_edit_return_pressed();
void page_title_changed(QString);
void page_favicon_changed(QIcon);
void back();
void forward();
void home();
void reload();
signals:
@ -36,6 +44,13 @@ private:
QLineEdit* m_location_edit { nullptr };
WebView* m_view { nullptr };
QMainWindow* m_window { nullptr };
Browser::History m_history;
QString m_title;
OwnPtr<QAction> m_back_action;
OwnPtr<QAction> m_forward_action;
OwnPtr<QAction> m_home_action;
OwnPtr<QAction> m_reload_action;
int tab_index();
};

View file

@ -148,7 +148,7 @@ public:
virtual void page_did_start_loading(AK::URL const& url) override
{
emit m_view.loadStarted(url.to_string().characters());
emit m_view.loadStarted(url);
}
virtual void page_did_finish_loading(AK::URL const&) override

View file

@ -33,7 +33,7 @@ public:
signals:
void linkHovered(QString, int timeout = 0);
void linkUnhovered();
void loadStarted(QString);
void loadStarted(const URL&);
void title_changed(QString);
void favicon_changed(QIcon);