1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 10:46:35 +01:00

NavigationBar: Add support for adding additional tool buttons

This commit is contained in:
David Rosca 2018-01-05 13:16:06 +01:00
parent c0ac5ce0a2
commit 6824ea17f2
8 changed files with 435 additions and 28 deletions

View File

@ -121,6 +121,7 @@ set(SRCS ${SRCS}
navigation/locationbar.cpp
navigation/locationbarpopup.cpp
navigation/navigationbar.cpp
navigation/navigationbartoolbutton.cpp
navigation/navigationcontainer.cpp
navigation/reloadstopbutton.cpp
navigation/siteicon.cpp
@ -178,6 +179,7 @@ set(SRCS ${SRCS}
tabwidget/tabstackedwidget.cpp
tabwidget/tabwidget.cpp
tabwidget/tabcontextmenu.cpp
tools/abstractbuttoninterface.cpp
tools/aesinterface.cpp
tools/animatedwidget.cpp
tools/buttonbox.cpp

View File

@ -983,6 +983,7 @@ void BrowserWindow::currentTabChanged()
m_ipLabel->setText(view->getIp());
view->setFocus();
m_navigationToolbar->setCurrentView(view);
updateLoadingActions();
// Setting correct tab order (LocationBar -> WebSearchBar -> WebView)

View File

@ -28,6 +28,8 @@
#include "webpage.h"
#include "qzsettings.h"
#include "qztools.h"
#include "abstractbuttoninterface.h"
#include "navigationbartoolbutton.h"
#include <QTimer>
#include <QSplitter>
@ -153,13 +155,6 @@ NavigationBar::NavigationBar(BrowserWindow* window)
m_navigationSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
m_navigationSplitter->setCollapsible(0, false);
addWidget(backNextWidget, QSL("button-backforward"));
addWidget(m_reloadStop, QSL("button-reloadstop"));
addWidget(buttonHome, QSL("button-home"));
addWidget(buttonAddTab, QSL("button-addtab"));
addWidget(m_navigationSplitter, QSL("locationbar"));
addWidget(buttonTools, QSL("button-tools"));
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint)));
@ -177,6 +172,16 @@ NavigationBar::NavigationBar(BrowserWindow* window)
connect(buttonHome, SIGNAL(controlClicked()), m_window, SLOT(goHomeInNewTab()));
connect(buttonAddTab, SIGNAL(clicked()), m_window, SLOT(addTab()));
connect(buttonAddTab, SIGNAL(middleMouseClicked()), m_window->tabWidget(), SLOT(addTabFromClipboard()));
loadSettings();
connect(mApp, &MainApplication::settingsReloaded, this, &NavigationBar::loadSettings);
addWidget(backNextWidget, QSL("button-backforward"), tr("Back and Forward buttons"));
addWidget(m_reloadStop, QSL("button-reloadstop"), tr("Reload button"));
addWidget(buttonHome, QSL("button-home"), tr("Home button"));
addWidget(buttonAddTab, QSL("button-addtab"), tr("Add tab button"));
addWidget(m_navigationSplitter, QSL("locationbar"), tr("Address and Search Bar"));
addWidget(buttonTools, QSL("button-tools"), tr("Tools button"));
}
void NavigationBar::setSplitterSizes(int locationBar, int websearchBar)
@ -194,6 +199,15 @@ void NavigationBar::setSplitterSizes(int locationBar, int websearchBar)
m_navigationSplitter->setSizes(sizes);
}
void NavigationBar::setCurrentView(TabbedWebView *view)
{
for (const WidgetData &data : qAsConst(m_widgets)) {
if (data.button) {
data.button->setWebPage(view->page());
}
}
}
void NavigationBar::showReloadButton()
{
m_reloadStop->showReloadButton();
@ -229,18 +243,56 @@ void NavigationBar::setLayoutSpacing(int spacing)
m_layout->setSpacing(spacing);
}
void NavigationBar::addWidget(QWidget *widget, const QString &id)
void NavigationBar::addWidget(QWidget *widget, const QString &id, const QString &name)
{
m_widgets[id] = widget;
if (!widget || id.isEmpty() || name.isEmpty()) {
return;
}
WidgetData data;
data.id = id;
data.name = name;
data.widget = widget;
m_widgets[id] = data;
reloadLayout();
}
void NavigationBar::removeWidget(const QString &id)
{
if (!m_widgets.contains(id)) {
return;
}
m_widgets.remove(id);
reloadLayout();
}
void NavigationBar::addToolButton(AbstractButtonInterface *button)
{
if (!button || !button->isValid()) {
return;
}
WidgetData data;
data.id = button->id();
data.name = button->name();
data.widget = new NavigationBarToolButton(button, this);
data.button = button;
m_widgets[data.id] = data;
reloadLayout();
}
void NavigationBar::removeToolButton(AbstractButtonInterface *button)
{
if (!button || !m_widgets.contains(button->id())) {
return;
}
delete m_widgets.take(button->id()).widget;
}
void NavigationBar::aboutToShowHistoryBackMenu()
{
if (!m_menuBack || !m_window->weView()) {
@ -317,6 +369,14 @@ void NavigationBar::aboutToShowToolsMenu()
m_window->createSidebarsMenu(m_menuTools->addMenu(tr("Sidebars")));
m_menuTools->addSeparator();
for (const WidgetData &data : qAsConst(m_widgets)) {
AbstractButtonInterface *button = data.button;
if (button && !m_layoutIds.contains(data.id)) {
m_menuTools->addAction(button->icon(), button->title(), this, &NavigationBar::toolActionActivated)->setData(data.id);
}
}
m_menuTools->addSeparator();
m_menuTools->addAction(IconProvider::settingsIcon(), tr("Configure Toolbar"), this, SLOT(openConfigurationDialog()));
}
@ -338,7 +398,42 @@ void NavigationBar::openConfigurationDialog()
{
}
void NavigationBar::reloadLayout()
void NavigationBar::toolActionActivated()
{
QAction *act = qobject_cast<QAction*>(sender());
if (!act) {
return;
}
const QString id = act->data().toString();
if (!m_widgets.contains(id)) {
return;
}
WidgetData data = m_widgets.value(id);
if (!data.button) {
return;
}
ToolButton *buttonTools = qobject_cast<ToolButton*>(m_widgets.value(QSL("button-tools")).widget);
if (!buttonTools) {
return;
}
AbstractButtonInterface::ClickController c;
c.visualParent = buttonTools;
c.popupPosition = [=](const QSize &size) {
QPoint pos = buttonTools->mapToGlobal(buttonTools->rect().bottomRight());
if (QApplication::isRightToLeft()) {
pos.setX(pos.x() - buttonTools->rect().width());
} else {
pos.setX(pos.x() - size.width());
}
return pos;
};
buttonTools->setDown(true);
emit data.button->clicked(&c);
buttonTools->setDown(false);
}
void NavigationBar::loadSettings()
{
const QStringList defaultIds = {
QSL("button-backforward"),
@ -348,12 +443,20 @@ void NavigationBar::reloadLayout()
QSL("button-tools")
};
QStringList ids = Settings().value(QSL("NavigationBar/Layout"), defaultIds).toStringList();
ids.removeDuplicates();
if (!ids.contains(QSL("locationbar"))) {
ids.append(QSL("locationbar"));
}
Settings settings;
settings.beginGroup(QSL("NavigationBar"));
m_layoutIds = settings.value(QSL("Layout"), defaultIds).toStringList();
settings.endGroup();
m_layoutIds.removeDuplicates();
if (!m_layoutIds.contains(QSL("locationbar"))) {
m_layoutIds.append(QSL("locationbar"));
}
}
void NavigationBar::reloadLayout()
{
// Clear layout
while (m_layout->count() != 0) {
QLayoutItem *item = m_layout->takeAt(0);
if (!item) {
@ -366,15 +469,17 @@ void NavigationBar::reloadLayout()
widget->setParent(nullptr);
}
for (QWidget *widget : m_widgets) {
widget->hide();
// Hide all widgets
for (const WidgetData &data : m_widgets) {
data.widget->hide();
}
for (const QString &id : qAsConst(ids)) {
QWidget *widget = m_widgets.value(id);
if (widget) {
m_layout->addWidget(widget);
widget->show();
// Add widgets to layout
for (const QString &id : qAsConst(m_layoutIds)) {
const WidgetData data = m_widgets.value(id);
if (data.widget) {
m_layout->addWidget(data.widget);
data.widget->show();
}
}

View File

@ -22,6 +22,7 @@
#include "qzcommon.h"
class QUrl;
class QHBoxLayout;
class QSplitter;
class QWebEngineHistoryItem;
@ -31,19 +32,21 @@ class WebSearchBar;
class BrowserWindow;
class ReloadStopButton;
class Menu;
class QUrl;
class AbstractButtonInterface;
class TabbedWebView;
class FALKON_EXPORT NavigationBar : public QWidget
{
Q_OBJECT
public:
explicit NavigationBar(BrowserWindow* window);
Q_PROPERTY(int layoutMargin READ layoutMargin WRITE setLayoutMargin)
Q_PROPERTY(int layoutSpacing READ layoutSpacing WRITE setLayoutSpacing)
public:
explicit NavigationBar(BrowserWindow* window);
void setSplitterSizes(int locationBar, int websearchBar);
void setCurrentView(TabbedWebView *view);
void showReloadButton();
void showStopButton();
@ -58,9 +61,12 @@ public:
int layoutSpacing() const;
void setLayoutSpacing(int spacing);
void addWidget(QWidget *widget, const QString &id);
void addWidget(QWidget *widget, const QString &id, const QString &name);
void removeWidget(const QString &id);
void addToolButton(AbstractButtonInterface *button);
void removeToolButton(AbstractButtonInterface *button);
public slots:
void refreshHistory();
@ -82,8 +88,10 @@ private slots:
void clearHistory();
void contextMenuRequested(const QPoint &pos);
void openConfigurationDialog();
void toolActionActivated();
private:
void loadSettings();
void reloadLayout();
void loadHistoryItem(const QWebEngineHistoryItem &item);
void loadHistoryItemInNewTab(const QWebEngineHistoryItem &item);
@ -101,7 +109,15 @@ private:
Menu *m_menuTools;
ToolButton* m_supMenu;
QHash<QString, QWidget*> m_widgets;
struct WidgetData {
QString id;
QString name;
QWidget *widget = nullptr;
AbstractButtonInterface *button = nullptr;
};
QStringList m_layoutIds;
QHash<QString, WidgetData> m_widgets;
};
#endif // NAVIGATIONBAR_H

View File

@ -0,0 +1,55 @@
/* ============================================================
* QupZilla - Qt web browser
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "navigationbartoolbutton.h"
#include "abstractbuttoninterface.h"
#include <QApplication>
NavigationBarToolButton::NavigationBarToolButton(AbstractButtonInterface *button, QWidget *parent)
: ToolButton(parent)
, m_button(button)
{
setAutoRaise(true);
setToolbarButtonLook(true);
setFocusPolicy(Qt::NoFocus);
setToolTip(button->toolTip());
setIcon(button->icon());
connect(button, &AbstractButtonInterface::iconChanged, this, &ToolButton::setIcon);
connect(button, &AbstractButtonInterface::toolTipChanged, this, &ToolButton::setToolTip);
connect(this, &ToolButton::clicked, this, &NavigationBarToolButton::clicked);
}
void NavigationBarToolButton::clicked()
{
AbstractButtonInterface::ClickController c;
c.visualParent = this;
c.popupPosition = [this](const QSize &size) {
QPoint pos = mapToGlobal(rect().bottomRight());
if (QApplication::isRightToLeft()) {
pos.setX(pos.x() - rect().width());
} else {
pos.setX(pos.x() - size.width());
}
return pos;
};
setDown(true);
emit m_button->clicked(&c);
setDown(false);
}

View File

@ -0,0 +1,34 @@
/* ============================================================
* QupZilla - Qt web browser
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#pragma once
#include "qzcommon.h"
#include "toolbutton.h"
class AbstractButtonInterface;
class QUPZILLA_EXPORT NavigationBarToolButton : public ToolButton
{
public:
explicit NavigationBarToolButton(AbstractButtonInterface *button, QWidget *parent = nullptr);
private:
void clicked();
AbstractButtonInterface *m_button;
};

View File

@ -0,0 +1,114 @@
/* ============================================================
* QupZilla - Qt web browser
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#include "abstractbuttoninterface.h"
AbstractButtonInterface::AbstractButtonInterface(QObject *parent)
: QObject(parent)
{
}
bool AbstractButtonInterface::isValid() const
{
return !id().isEmpty() && !name().isEmpty();
}
bool AbstractButtonInterface::isActive() const
{
return m_active;
}
void AbstractButtonInterface::setActive(bool active)
{
if (m_active == active) {
return;
}
m_active = active;
emit activeChanged(m_active);
}
QString AbstractButtonInterface::title() const
{
return m_title;
}
void AbstractButtonInterface::setTitle(const QString &title)
{
if (m_title == title) {
return;
}
m_title = title;
emit titleChanged(m_title);
}
QString AbstractButtonInterface::toolTip() const
{
return m_toolTip;
}
void AbstractButtonInterface::setToolTip(const QString &toolTip)
{
if (m_toolTip == toolTip) {
return;
}
m_toolTip = toolTip;
emit toolTipChanged(m_toolTip);
}
QIcon AbstractButtonInterface::icon() const
{
return m_icon;
}
void AbstractButtonInterface::setIcon(const QIcon &icon)
{
m_icon = icon;
emit iconChanged(icon);
}
QString AbstractButtonInterface::badgeLabelText() const
{
return m_badgeLabelText;
}
void AbstractButtonInterface::setBadgeLabelText(const QString &badgeLabelText)
{
if (m_badgeLabelText == badgeLabelText) {
return;
}
m_badgeLabelText = badgeLabelText;
emit badgeLabelTextChanged(m_badgeLabelText);
}
WebPage *AbstractButtonInterface::webPage() const
{
return m_page;
}
void AbstractButtonInterface::setWebPage(WebPage *page)
{
if (m_page == page) {
return;
}
m_page = page;
emit webPageChanged(m_page);
}

View File

@ -0,0 +1,80 @@
/* ============================================================
* QupZilla - Qt web browser
* Copyright (C) 2018 David Rosca <nowrep@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ============================================================ */
#pragma once
#include <QIcon>
#include <QObject>
#include <functional>
#include "qzcommon.h"
class WebPage;
class QUPZILLA_EXPORT AbstractButtonInterface : public QObject
{
Q_OBJECT
public:
struct ClickController {
QWidget *visualParent;
std::function<QPoint(QSize)> popupPosition;
};
explicit AbstractButtonInterface(QObject *parent = nullptr);
virtual QString id() const = 0;
virtual QString name() const = 0;
bool isValid() const;
bool isActive() const;
void setActive(bool active);
QString title() const;
void setTitle(const QString &text);
QString toolTip() const;
void setToolTip(const QString &toolTip);
QIcon icon() const;
void setIcon(const QIcon &icon);
QString badgeLabelText() const;
void setBadgeLabelText(const QString &badgeLabelText);
WebPage *webPage() const;
void setWebPage(WebPage *page);
signals:
void activeChanged(bool active);
void titleChanged(const QString &title);
void toolTipChanged(const QString &toolTip);
void iconChanged(const QIcon &icon);
void badgeLabelTextChanged(const QString &badgeLabelText);
void webPageChanged(WebPage *page);
void clicked(ClickController *controller);
private:
bool m_active = true;
QString m_title;
QString m_toolTip;
QIcon m_icon;
QString m_badgeLabelText;
WebPage *m_page = nullptr;
};