38#include <QStackedWidget>
39#include <QWebEngineHistory>
41#include <QStyleOption>
43static QString titleForUrl(QString title,
const QUrl &url)
45 if (title.isEmpty()) {
46 title = url.toString(QUrl::RemoveFragment);
48 if (title.isEmpty()) {
49 return NavigationBar::tr(
"Empty Page");
54static QIcon iconForPage(
const QUrl &url,
const QIcon &sIcon)
58 icon.addPixmap(sIcon.pixmap(16), QIcon::Active);
66 setObjectName(
QSL(
"navigationbar"));
68 m_layout =
new QHBoxLayout(
this);
69 auto contentsMargin = style()->pixelMetric(QStyle::PM_ToolBarItemMargin,
nullptr,
this)
70 + style()->pixelMetric(QStyle::PM_ToolBarFrameWidth,
nullptr,
this);
71 m_layout->setContentsMargins(contentsMargin, contentsMargin, contentsMargin, contentsMargin);
72 m_layout->setSpacing(style()->pixelMetric(QStyle::PM_ToolBarItemSpacing,
nullptr,
this));
76 m_buttonBack->setObjectName(
"navigation-button-back");
77 m_buttonBack->setToolTip(tr(
"Back"));
78 m_buttonBack->setToolButtonStyle(Qt::ToolButtonIconOnly);
81 m_buttonBack->setAutoRaise(
true);
82 m_buttonBack->setEnabled(
false);
83 m_buttonBack->setFocusPolicy(Qt::NoFocus);
86 m_buttonForward->setObjectName(
"navigation-button-next");
87 m_buttonForward->setToolTip(tr(
"Forward"));
88 m_buttonForward->setToolButtonStyle(Qt::ToolButtonIconOnly);
91 m_buttonForward->setAutoRaise(
true);
92 m_buttonForward->setEnabled(
false);
93 m_buttonForward->setFocusPolicy(Qt::NoFocus);
95 auto* backNextLayout =
new QHBoxLayout();
96 backNextLayout->setContentsMargins(0, 0, 0, 0);
97 backNextLayout->setSpacing(0);
98 backNextLayout->addWidget(m_buttonBack);
99 backNextLayout->addWidget(m_buttonForward);
100 auto *backNextWidget =
new QWidget(
this);
101 backNextWidget->setLayout(backNextLayout);
106 buttonHome->setObjectName(
"navigation-button-home");
107 buttonHome->setToolTip(tr(
"Home"));
108 buttonHome->setToolButtonStyle(Qt::ToolButtonIconOnly);
109 buttonHome->setToolbarButtonLook(
true);
110 buttonHome->setAutoRaise(
true);
111 buttonHome->setFocusPolicy(Qt::NoFocus);
114 buttonAddTab->setObjectName(
"navigation-button-addtab");
115 buttonAddTab->setToolTip(tr(
"New Tab"));
116 buttonAddTab->setToolButtonStyle(Qt::ToolButtonIconOnly);
117 buttonAddTab->setToolbarButtonLook(
true);
118 buttonAddTab->setAutoRaise(
true);
119 buttonAddTab->setFocusPolicy(Qt::NoFocus);
121 m_menuBack =
new Menu(
this);
123 m_buttonBack->
setMenu(m_menuBack);
126 m_menuForward =
new Menu(
this);
128 m_buttonForward->
setMenu(m_menuForward);
132 buttonTools->setObjectName(
"navigation-button-tools");
133 buttonTools->setPopupMode(QToolButton::InstantPopup);
134 buttonTools->setToolbarButtonLook(
true);
135 buttonTools->setToolTip(tr(
"Tools"));
136 buttonTools->setAutoRaise(
true);
137 buttonTools->setFocusPolicy(Qt::NoFocus);
138 buttonTools->setShowMenuInside(
true);
140 m_menuTools =
new Menu(
this);
141 buttonTools->setMenu(m_menuTools);
145 m_supMenu->setObjectName(
"navigation-button-supermenu");
146 m_supMenu->setPopupMode(QToolButton::InstantPopup);
148 m_supMenu->setToolTip(tr(
"Main Menu"));
149 m_supMenu->setAutoRaise(
true);
150 m_supMenu->setFocusPolicy(Qt::NoFocus);
156 m_navigationSplitter =
new QSplitter(
this);
158 m_navigationSplitter->addWidget(m_searchLine);
160 m_navigationSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
161 m_navigationSplitter->setCollapsible(0,
false);
164 m_exitFullscreen->setObjectName(
"navigation-button-exitfullscreen");
165 m_exitFullscreen->setToolTip(tr(
"Exit Fullscreen"));
166 m_exitFullscreen->setToolButtonStyle(Qt::ToolButtonIconOnly);
168 m_exitFullscreen->setFocusPolicy(Qt::NoFocus);
169 m_exitFullscreen->setAutoRaise(
true);
170 m_exitFullscreen->setVisible(
false);
172 setContextMenuPolicy(Qt::CustomContextMenu);
173 connect(
this, &QWidget::customContextMenuRequested,
this, &NavigationBar::contextMenuRequested);
191 addWidget(backNextWidget,
QSL(
"button-backforward"), tr(
"Back and Forward buttons"));
192 addWidget(m_reloadStop,
QSL(
"button-reloadstop"), tr(
"Reload button"));
193 addWidget(buttonHome,
QSL(
"button-home"), tr(
"Home button"));
194 addWidget(buttonAddTab,
QSL(
"button-addtab"), tr(
"Add tab button"));
195 addWidget(m_navigationSplitter,
QSL(
"locationbar"), tr(
"Address and Search bar"));
196 addWidget(buttonTools,
QSL(
"button-tools"), tr(
"Tools button"));
197 addWidget(m_exitFullscreen,
QSL(
"button-exitfullscreen"), tr(
"Exit Fullscreen button"));
211 if (locationBar == 0) {
212 int splitterWidth = m_navigationSplitter->width();
213 sizes << (int)((
double)splitterWidth * .80) << (
int)((double)splitterWidth * .20);
216 sizes << locationBar << websearchBar;
219 m_navigationSplitter->setSizes(sizes);
224 for (
const WidgetData &data : std::as_const(m_widgets)) {
226 data.button->setWebView(view);
234 auto connectPageActions = [
this](QWebEnginePage *page) {
235 auto updateButton = [](
ToolButton *button, QAction *action) {
236 button->setEnabled(action->isEnabled());
238 auto updateBackButton = std::bind(updateButton, m_buttonBack, page->action(QWebEnginePage::Back));
239 auto updateForwardButton = std::bind(updateButton, m_buttonForward, page->action(QWebEnginePage::Forward));
242 updateForwardButton();
244 disconnect(m_backConnection);
245 disconnect(m_forwardConnection);
246 m_backConnection = connect(page->action(QWebEnginePage::Back), &QAction::changed,
this, updateBackButton);
247 m_forwardConnection = connect(page->action(QWebEnginePage::Forward), &QAction::changed,
this, updateForwardButton);
250 connectPageActions(view->
page());
266 if (m_layout->indexOf(m_exitFullscreen) != -1) {
267 m_exitFullscreen->show();
273 if (m_layout->indexOf(m_exitFullscreen) != -1) {
274 m_exitFullscreen->hide();
280 m_supMenu->setVisible(visible);
286 return m_layout->contentsMargins().left();
291 m_layout->setContentsMargins(margin, margin, margin, margin);
296 return m_layout->spacing();
301 m_layout->setSpacing(spacing);
306 if (!widget ||
id.isEmpty() || name.isEmpty()) {
313 data.widget = widget;
314 m_widgets[id] = data;
321 if (!m_widgets.contains(
id)) {
325 m_widgets.remove(
id);
331 if (!button || !button->
isValid()) {
336 toolButton->setProperty(
"button-id", button->
id());
338 if (m_layout->indexOf(toolButton) != -1) {
339 toolButton->updateVisibility();
344 data.id = button->
id();
345 data.name = button->
name();
346 data.widget = toolButton;
347 data.button = button;
348 m_widgets[data.id] = data;
350 data.button->setWebView(m_window->
weView());
357 if (!button || !m_widgets.contains(button->
id())) {
361 delete m_widgets.take(button->
id()).widget;
364void NavigationBar::aboutToShowHistoryBackMenu()
366 if (!m_menuBack || !m_window->
weView()) {
370 QWebEngineHistory* history = m_window->
weView()->history();
372 int curindex = history->currentItemIndex();
375 for (
int i = curindex - 1;
i >= 0;
i--) {
376 QWebEngineHistoryItem item = history->itemAt(
i);
377 if (item.isValid()) {
378 QString title = titleForUrl(item.title(), item.url());
381 auto* act =
new Action(icon, title);
383 connect(act, &QAction::triggered,
this, &NavigationBar::loadHistoryIndex);
384 connect(act, SIGNAL(ctrlTriggered()),
this, SLOT(loadHistoryIndexInNewTab()));
385 m_menuBack->addAction(act);
394 m_menuBack->addSeparator();
395 m_menuBack->addAction(QIcon::fromTheme(
QSL(
"edit-clear")), tr(
"Clear history"),
this, &NavigationBar::clearHistory);
398void NavigationBar::aboutToShowHistoryNextMenu()
400 if (!m_menuForward || !m_window->
weView()) {
403 m_menuForward->clear();
405 QWebEngineHistory* history = m_window->
weView()->history();
406 int curindex = history->currentItemIndex();
409 for (
int i = curindex + 1;
i < history->count();
i++) {
410 QWebEngineHistoryItem item = history->itemAt(
i);
411 if (item.isValid()) {
412 QString title = titleForUrl(item.title(), item.url());
415 auto* act =
new Action(icon, title);
417 connect(act, &QAction::triggered,
this, &NavigationBar::loadHistoryIndex);
418 connect(act, SIGNAL(ctrlTriggered()),
this, SLOT(loadHistoryIndexInNewTab()));
419 m_menuForward->addAction(act);
428 m_menuForward->addSeparator();
429 m_menuForward->addAction(QIcon::fromTheme(
QSL(
"edit-clear")), tr(
"Clear history"),
this, &NavigationBar::clearHistory);
432void NavigationBar::aboutToShowToolsMenu()
434 m_menuTools->clear();
438 m_menuTools->addSeparator();
440 for (
const WidgetData &data : std::as_const(m_widgets)) {
442 if (button && (!button->
isVisible() || !m_layoutIds.contains(data.id))) {
443 QString title = button->
title();
447 m_menuTools->addAction(button->
icon(), title,
this, &NavigationBar::toolActionActivated)->setData(data.id);
451 m_menuTools->addSeparator();
455void NavigationBar::clearHistory()
457 QWebEngineHistory* history = m_window->
weView()->
page()->history();
461void NavigationBar::contextMenuRequested(
const QPoint &pos)
467 menu.exec(mapToGlobal(pos));
470void NavigationBar::openConfigurationDialog()
476void NavigationBar::toolActionActivated()
478 auto *act = qobject_cast<QAction*>(sender());
482 const QString
id = act->data().toString();
483 if (!m_widgets.contains(
id)) {
486 WidgetData data = m_widgets.value(
id);
490 auto *buttonTools = qobject_cast<ToolButton*>(m_widgets.value(
QSL(
"button-tools")).widget);
497 c->popupPosition = [=](
const QSize &size) {
498 QPoint pos = buttonTools->mapToGlobal(buttonTools->rect().bottomRight());
499 if (QApplication::isRightToLeft()) {
500 pos.setX(pos.x() - buttonTools->rect().width());
502 pos.setX(pos.x() - size.width());
504 c->popupOpened =
true;
507 c->popupClosed = [=]() {
508 buttonTools->setDown(
false);
511 Q_EMIT data.button->clicked(c);
512 if (c->popupOpened) {
513 buttonTools->setDown(
true);
519void NavigationBar::loadSettings()
521 const QStringList defaultIds = {
522 QSL(
"button-backforward"),
523 QSL(
"button-reloadstop"),
526 QSL(
"button-downloads"),
533 m_layoutIds = settings.
value(
QSL(
"Layout"), defaultIds).toStringList();
534 m_searchLine->setVisible(settings.
value(
QSL(
"ShowSearchBar"),
true).toBool());
537 m_layoutIds.removeDuplicates();
538 m_layoutIds.removeAll(QString());
539 if (!m_layoutIds.contains(
QSL(
"locationbar"))) {
540 m_layoutIds.append(
QSL(
"locationbar"));
546void NavigationBar::reloadLayout()
548 if (m_widgets.isEmpty()) {
552 setUpdatesEnabled(
false);
555 while (m_layout->count() != 0) {
556 QLayoutItem *item = m_layout->takeAt(0);
560 QWidget *widget = item->widget();
564 widget->setParent(
nullptr);
568 for (
const WidgetData &data : m_widgets) {
573 for (
const QString &
id : std::as_const(m_layoutIds)) {
574 const WidgetData data = m_widgets.value(
id);
576 m_layout->addWidget(data.widget);
577 auto *button = qobject_cast<NavigationBarToolButton*>(data.widget);
579 button->updateVisibility();
586 m_layout->addWidget(m_supMenu);
589 if (m_searchLine->isVisible() && m_navigationSplitter->sizes().at(1) == 0) {
590 const int locationBarSize = m_navigationSplitter->sizes().at(0);
594 if (m_window->isFullScreen()) {
600 setUpdatesEnabled(
true);
603void NavigationBar::loadHistoryIndex()
605 QWebEngineHistory* history = m_window->
weView()->
page()->history();
607 if (
auto* action = qobject_cast<QAction*>(sender())) {
608 loadHistoryItem(history->itemAt(action->data().toInt()));
612void NavigationBar::loadHistoryIndexInNewTab(
int index)
614 if (
auto* action = qobject_cast<QAction*>(sender())) {
615 index = action->data().toInt();
622 QWebEngineHistory* history = m_window->
weView()->
page()->history();
623 loadHistoryItemInNewTab(history->itemAt(index));
628 m_window->
action(
QSL(
"View/Stop"))->trigger();
633 m_window->
action(
QSL(
"View/Reload"))->trigger();
638 auto view = m_window->
weView();
645 QWebEngineHistory* history = m_window->
weView()->
page()->history();
647 if (!history->canGoBack()) {
651 loadHistoryItemInNewTab(history->backItem());
656 auto view = m_window->
weView();
663 QWebEngineHistory* history = m_window->
weView()->
page()->history();
665 if (!history->canGoForward()) {
669 loadHistoryItemInNewTab(history->forwardItem());
672void NavigationBar::loadHistoryItem(
const QWebEngineHistoryItem &item)
674 m_window->
weView()->
page()->history()->goToItem(item);
677void NavigationBar::loadHistoryItemInNewTab(
const QWebEngineHistoryItem &item)
682 QWebEngineHistory* history = m_window->
weView(tabIndex)->
page()->history();
683 history->goToItem(item);
QAction * action(const QString &name) const
TabWidget * tabWidget() const
void createSidebarsMenu(QMenu *menu)
QMenu * superMenu() const
TabbedWebView * weView() const
void createToolbarsMenu(QMenu *menu)
static QIcon settingsIcon()
static QIcon iconForUrl(const QUrl &url, bool allowNull=false)
static QIcon standardIcon(QStyle::StandardPixmap icon)
void removeWidget(const QString &id)
void removeToolButton(AbstractButtonInterface *button)
void setLayoutSpacing(int spacing)
void setLayoutMargin(int margin)
void setSplitterSizes(int locationBar, int websearchBar)
void addWidget(QWidget *widget, const QString &id, const QString &name)
void setSuperMenuVisible(bool visible)
friend class NavigationBarConfigDialog
void setCurrentView(TabbedWebView *view)
void addToolButton(AbstractButtonInterface *button)
NavigationBar(BrowserWindow *window)
void beginGroup(const QString &prefix)
QVariant value(const QString &key, const QVariant &defaultValue=QVariant())
void pageChanged(WebPage *page)