aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt33
-rw-r--r--src/addressbar/completer.h4
-rw-r--r--src/addressbar/urllineedit.cpp18
-rw-r--r--src/addressbar/urllineedit.h7
-rw-r--r--src/browser.cpp180
-rw-r--r--src/browser.h41
-rw-r--r--src/commandline.h1
-rw-r--r--src/forms/aboutdialog.cpp98
-rw-r--r--src/forms/aboutdialog.h31
-rw-r--r--src/forms/aboutdialog.ui105
-rw-r--r--src/main.cpp83
-rw-r--r--src/mainwindow/mainwindow.cpp362
-rw-r--r--src/mainwindow/mainwindow.h84
-rw-r--r--src/mainwindow/mainwindow.ui63
-rw-r--r--src/mainwindow/widgets/loadingbar.cpp2
-rw-r--r--src/mainwindow/widgets/navigationbar.cpp115
-rw-r--r--src/mainwindow/widgets/navigationbar.h41
-rw-r--r--src/mainwindow/widgets/searchform.cpp4
-rw-r--r--src/mainwindow/widgets/tabbar.cpp171
-rw-r--r--src/mainwindow/widgets/tabbar.h56
-rw-r--r--src/mainwindow/widgets/tabwidget.cpp121
-rw-r--r--src/mainwindow/widgets/tabwidget.h40
-rw-r--r--src/mainwindow/window.cpp68
-rw-r--r--src/mainwindow/window.h42
-rw-r--r--src/version.h.in15
-rw-r--r--src/webengine/urlinterceptor.h2
-rw-r--r--src/webengine/webengineprofile.cpp214
-rw-r--r--src/webengine/webengineprofile.h39
-rw-r--r--src/webengine/webprofile.cpp216
-rw-r--r--src/webengine/webprofile.h53
-rw-r--r--src/webengine/webview.cpp47
-rw-r--r--src/webengine/webview.h13
-rw-r--r--src/webengine/widgets/pagetoolsmenu.cpp2
-rw-r--r--src/widgets/mainwindowmenubar.cpp91
-rw-r--r--src/widgets/mainwindowmenubar.h32
35 files changed, 932 insertions, 1562 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0f978b5..8adb1aa 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -20,16 +20,17 @@ add_executable(poi
# main window
mainwindow/mainwindow.cpp
mainwindow/mainwindow.h
- mainwindow/mainwindow.ui
- mainwindow/widgets/loadingbar.cpp
- mainwindow/widgets/loadingbar.h
+ mainwindow/window.cpp
+ mainwindow/window.h
+ #mainwindow/widgets/loadingbar.cpp
+ #mainwindow/widgets/loadingbar.h
mainwindow/widgets/navigationbar.cpp
mainwindow/widgets/navigationbar.h
- mainwindow/widgets/searchform.cpp
- mainwindow/widgets/searchform.h
- mainwindow/widgets/searchform.ui
- mainwindow/widgets/tabbar.cpp
- mainwindow/widgets/tabbar.h
+ #mainwindow/widgets/searchform.cpp
+ #mainwindow/widgets/searchform.h
+ #mainwindow/widgets/searchform.ui
+ mainwindow/widgets/tabwidget.cpp
+ mainwindow/widgets/tabwidget.h
# address bar
addressbar/completer.cpp
@@ -37,15 +38,11 @@ add_executable(poi
addressbar/urllineedit.cpp
addressbar/urllineedit.h
- # todo: move all to mainwindow
- widgets/mainwindowmenubar.cpp
- widgets/mainwindowmenubar.h
-
# webengine
webengine/urlinterceptor.cpp
webengine/urlinterceptor.h
- webengine/webengineprofile.cpp # todo: rename to profile
- webengine/webengineprofile.h
+ webengine/webprofile.cpp
+ webengine/webprofile.h
webengine/webpage.cpp
webengine/webpage.h
webengine/webview.cpp
@@ -55,13 +52,8 @@ add_executable(poi
webengine/widgets/pagemenu.cpp
webengine/widgets/pagemenu.h
- # forms
- forms/aboutdialog.cpp
- forms/aboutdialog.h
- forms/aboutdialog.ui
-
# plugin interfaces
- ../plugins/interfaces.h
+ #../plugins/interfaces.h
)
target_include_directories(poi
@@ -70,6 +62,7 @@ target_include_directories(poi
target_link_libraries(poi
Qt5::Core Qt5::Widgets Qt5::Concurrent Qt5::WebEngineWidgets
+ about
configuration
bookmarks downloads)
diff --git a/src/addressbar/completer.h b/src/addressbar/completer.h
index ce19f07..daef67c 100644
--- a/src/addressbar/completer.h
+++ b/src/addressbar/completer.h
@@ -21,14 +21,12 @@ class Completer : public QListView
public:
explicit Completer(QWidget *parent = nullptr);
- bool updateItems(const QList<QTreeWidgetItem*> &list);
+ bool updateItems(const QList<QTreeWidgetItem *> &list);
bool keyPressed(QKeyEvent *event);
private:
QStringListModel *completionModel;
-
};
-
#endif //SMOLBOTE_COMPLETER_H
diff --git a/src/addressbar/urllineedit.cpp b/src/addressbar/urllineedit.cpp
index cf2c08b..8aa03c7 100644
--- a/src/addressbar/urllineedit.cpp
+++ b/src/addressbar/urllineedit.cpp
@@ -7,6 +7,7 @@
*/
#include "urllineedit.h"
+#include "webengine/webview.h"
#include <QLabel>
#include <QMenu>
#include <QShortcut>
@@ -18,19 +19,13 @@ UrlLineEdit::UrlLineEdit(const QHash<QString, QString> &config, QWidget *parent)
: QLineEdit(parent)
, m_listView(new Completer(this))
{
- auto *focusShortcut = new QShortcut(QKeySequence(config.value("addressbar.shortcuts.focus")), parent);
- connect(focusShortcut, &QShortcut::activated, this, [this]() {
- setFocus();
- selectAll();
- });
-
setPlaceholderText(tr("Enter address"));
m_listView->setVisible(false);
connect(this, &UrlLineEdit::textEdited, this, &UrlLineEdit::updateCompleter);
m_pageMenuAction = addAction(style()->standardIcon(QStyle::SP_DriveNetIcon), QLineEdit::LeadingPosition);
- m_pageMenuAction->setShortcut(QKeySequence(config.value("addressbar.shortcuts.pageMenu")));
+ m_pageMenuAction->setShortcut(QKeySequence("F2"));
m_pageMenuAction->setToolTip(tr("Page Actions (%1)").arg(m_pageMenuAction->shortcut().toString()));
connect(m_pageMenuAction, &QAction::triggered, m_pageMenuAction, [&]() {
if(m_pageMenuAction->menu()) {
@@ -39,7 +34,7 @@ UrlLineEdit::UrlLineEdit(const QHash<QString, QString> &config, QWidget *parent)
});
m_toolsMenuAction = addAction(style()->standardIcon(QStyle::SP_FileIcon), QLineEdit::TrailingPosition);
- m_toolsMenuAction->setShortcut(QKeySequence(config.value("addressbar.shortcuts.toolsMenu")));
+ m_toolsMenuAction->setShortcut(QKeySequence("F10"));
m_toolsMenuAction->setToolTip(tr("Tools (%1)").arg(m_toolsMenuAction->shortcut().toString()));
connect(m_toolsMenuAction, &QAction::triggered, m_toolsMenuAction, [&]() {
if(m_toolsMenuAction->menu()) {
@@ -56,7 +51,11 @@ UrlLineEdit::UrlLineEdit(const QHash<QString, QString> &config, QWidget *parent)
if(this->text().startsWith('#')) {
emit searchTermEntered(this->text().mid(1));
} else {
- emit addressEntered(QUrl::fromUserInput(this->text()));
+ if(m_view) {
+ m_view->load(QUrl::fromUserInput(this->text()));
+ } else {
+ this->clear();
+ }
}
this->clearFocus();
});
@@ -71,6 +70,7 @@ void UrlLineEdit::setCompleterModel(BookmarksView *model)
void UrlLineEdit::connectWebView(WebView *view)
{
Q_CHECK_PTR(view);
+ m_view = view;
disconnect(urlChangedConnection);
diff --git a/src/addressbar/urllineedit.h b/src/addressbar/urllineedit.h
index 17465bc..24ad403 100644
--- a/src/addressbar/urllineedit.h
+++ b/src/addressbar/urllineedit.h
@@ -9,15 +9,16 @@
#ifndef SMOLBOTE_URLLINEEDIT_H
#define SMOLBOTE_URLLINEEDIT_H
+#include "completer.h"
+#include "webengine/webview.h"
#include <QAction>
#include <QLineEdit>
#include <QTextLayout>
-#include "webengine/webview.h"
-#include "completer.h"
class BookmarksView;
class QMenu;
class QLabel;
+class WebView;
class UrlLineEdit : public QLineEdit
{
Q_OBJECT
@@ -45,6 +46,8 @@ private:
void setTextFormat(const QTextLayout::FormatRange &format);
void clearTextFormat();
+ WebView *m_view = nullptr;
+
QTextLayout::FormatRange m_hostFormat;
// pageMenu action: zoom, print
diff --git a/src/browser.cpp b/src/browser.cpp
index c32aee7..ab07f2e 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -7,152 +7,114 @@
*/
#include "browser.h"
-#include "configuration/configuration.h"
#include "mainwindow/mainwindow.h"
-#include "webengine/urlinterceptor.h"
-#include "webengine/webengineprofile.h"
-#include <QWebEngineDownloadItem>
-#include <QtConcurrent>
+#include "mainwindow/window.h"
+#include "webengine/webprofile.h"
+#include <QAction>
+#include <configuration/configuration.h>
#include <bookmarks/bookmarkswidget.h>
#include <downloads/downloadswidget.h>
+#include <version.h>
+#include "webengine/urlinterceptor.h"
Browser::Browser(int &argc, char *argv[])
: SingleApplication(argc, argv)
{
- QApplication::setApplicationName("smolbote");
- QApplication::setWindowIcon(QIcon(":/icon.svg"));
-
- connect(this, &Browser::messageAvailable, this, &Browser::createSession);
+ setApplicationName("smolbote");
+ setWindowIcon(QIcon(":/icon.svg"));
+ setApplicationVersion(SMOLBOTE_VERSION);
}
Browser::~Browser()
{
- if(m_bookmarksManager) {
- QtConcurrent::run(QThreadPool::globalInstance(), m_bookmarksManager.get(), &BookmarksWidget::save);
- }
-
- qDebug("Waiting for threads to wind down...");
- qDebug("Thread pool is done: %s", QThreadPool::globalInstance()->waitForDone() ? "okay" : "failed");
-
- delete m_urlRequestInterceptor;
+ qDeleteAll(m_windows);
+ m_windows.clear();
}
void Browser::setConfiguration(std::shared_ptr<Configuration> &config)
{
+ Q_ASSERT(config);
m_config = config;
-
- QDir pluginsDir(QString::fromStdString(m_config->value<std::string>("plugins.path").value()));
- if(pluginsDir.exists()) {
- const QStringList entries = pluginsDir.entryList(QDir::Files | QDir::Readable);
- for(const QString &name : entries) {
- QPluginLoader loader(pluginsDir.absoluteFilePath(name));
- qDebug("Loading plugin %s: %s", qUtf8Printable(name), loader.load() ? "ok" : "failed");
- if(!loader.isLoaded()) {
- qDebug("Error: %s", qUtf8Printable(loader.errorString()));
- } else {
- Plugin d;
- d.meta = loader.metaData()["MetaData"].toObject();
- d.pointer = loader.instance();
- d.pointer->setParent(this);
- m_plugins.append(d);
- }
- }
- }
-
- m_bookmarksManager = std::make_shared<BookmarksWidget>(QString::fromStdString(m_config->value<std::string>("bookmarks.path").value()));
- m_downloadManager = std::make_shared<DownloadsWidget>(QString::fromStdString(m_config->value<std::string>("downloads.path").value()));
-
- m_urlRequestInterceptor = new UrlRequestInterceptor(QString::fromStdString(m_config->value<std::string>("filter.path").value()));
-
- // set default profile
- m_defaultProfile = profile(QString::fromStdString(m_config->value<std::string>("browser.profile").value()));
}
-MainWindow *Browser::createWindow()
+void Browser::setup(const QString &defaultProfile)
{
- // the window will delete itself when it closes, so we don't need to delete it
- MainWindow *window = new MainWindow(m_config);
- window->setBookmarksWidget(m_bookmarksManager);
- window->setDownloadsWidget(m_downloadManager);
- window->setProfile(m_defaultProfile);
- window->addPlugins(m_plugins);
+ Q_ASSERT_X(m_config, "Browser::setup", "Configuration not set");
- m_windows.append(window);
+ // url request filter
+ m_urlFilter = std::make_shared<UrlRequestInterceptor>(QString::fromStdString(m_config->value<std::string>("filter.path").value()));
- // has to be window.get(), but can't be *window
- connect(window, &MainWindow::destroyed, this, [this, window]() {
- m_windows.removeOne(window);
- });
- window->show();
+ // cookie request filter
- return window;
-}
+ // bookmarks
+ m_bookmarks = std::make_shared<BookmarksWidget>(QString::fromStdString(m_config->value<std::string>("bookmarks.path").value()));
+ connect(m_bookmarks.get(), &BookmarksWidget::openUrl, this, [this](const QUrl &url) {
+ m_windows.last()->createTab(url);
+ });
-MainWindow *Browser::createSession(const QString &profileName, bool newWindow, const QStringList &urls)
-{
- MainWindow *window = nullptr;
+ // downloads
+ m_downloads = std::make_shared<DownloadsWidget>(QString::fromStdString(m_config->value<std::string>("downloads.path").value()));
- // if we need to open in a new window, or there are no windows, make one
- if(newWindow || m_windows.isEmpty()) {
- window = createWindow();
- window->setProfile(profile(profileName));
+ // load profiles
+ if(defaultProfile == "") {
+ auto *p = new WebProfile(this);
+ p->setRequestInterceptor(m_urlFilter.get());
+ connect(p, &WebProfile::downloadRequested, m_downloads.get(), &DownloadsWidget::addDownload);
+ WebProfile::setDefaultProfile(p);
} else {
- // reverse-iterate through windows to check for window with the same profile
- for(auto it = m_windows.rbegin(); it != m_windows.rend(); ++it) {
- if((*it)->profile()->storageName() == profileName) {
- window = *it;
- break;
- }
- }
- // if none is found, create one
- if(window == nullptr) {
- window = createWindow();
- window->setProfile(profile(profileName));
- }
+ auto *p = new WebProfile(defaultProfile, this);
+ p->setRequestInterceptor(m_urlFilter.get());
+ connect(p, &WebProfile::downloadRequested, m_downloads.get(), &DownloadsWidget::addDownload);
+ WebProfile::setDefaultProfile(p);
}
+}
- Q_CHECK_PTR(window);
+void Browser::createSession(const QString &profileName, bool newWindow, const QStringList &urls)
+{
+ if(m_windows.isEmpty()) {
+ createWindow();
+ }
- if(urls.isEmpty()) {
- // no URLs were given
- window->newTab(QUrl::fromUserInput(m_config->value<std::string>("profile.homepage").value().c_str()));
+ auto *mainwindow = m_windows.last();
+ if(newWindow) {
+ QUrl firstUrl = WebProfile::defaultProfile()->homepage();
+ if(!urls.isEmpty())
+ firstUrl = QUrl::fromUserInput(urls.at(0));
+ auto *w = mainwindow->createSubWindow(firstUrl);
+ for(int i = 1; i < urls.count() - 1; i++) {
+ w->addTab(QUrl::fromUserInput(urls.at(i)));
+ }
} else {
for(const QString &url : urls) {
- window->newTab(QUrl::fromUserInput(url));
+ mainwindow->createTab(QUrl::fromUserInput(url));
}
}
-
- return window;
}
-std::shared_ptr<WebEngineProfile> Browser::profile(const QString &storageName)
+MainWindow *Browser::createWindow()
{
- if(m_profiles.contains(storageName)) {
- return m_profiles[storageName];
- }
-
- // profile with name storageName has not been loaded
- Q_ASSERT(m_config);
-
- const QString &path = QString::fromStdString(m_config->value<std::string>("profile.path").value());
- std::shared_ptr<WebEngineProfile> _profile;
+ // the window will delete itself when it closes, so we don't need to delete it
+ MainWindow *window = new MainWindow(m_config);
+ window->createSubWindow(WebProfile::defaultProfile()->newtab());
- if(storageName.isEmpty()) {
- // create off-the-record profile
- _profile = std::make_shared<WebEngineProfile>(nullptr);
- _profile->loadProfile(m_config->section("profile"), path + "/otr.ini");
- } else {
- // regular profile
- _profile = std::make_shared<WebEngineProfile>(storageName, nullptr);
- _profile->loadProfile(m_config->section("profile"), path + "/" + storageName + "/profile.ini");
- _profile->setPersistentStoragePath(path + "/storage");
- _profile->setCachePath(path + "/cache");
- }
+ auto *bookmarksAction = new QAction(tr("Bookmarks"), window);
+ bookmarksAction->setShortcut(QKeySequence(QString::fromStdString(m_config->value<std::string>("bookmarks.shortcut").value())));
+ connect(bookmarksAction, &QAction::triggered, window, [this, window]() {
+ window->addDockWidget(Qt::RightDockWidgetArea, m_bookmarks.get());
+ });
+ window->addAction(MainWindow::ToolsMenu, bookmarksAction);
- _profile->setRequestInterceptor(m_urlRequestInterceptor);
+ auto *downloadsAction = new QAction(tr("Downloads"), window);
+ downloadsAction->setShortcut(QKeySequence(QString::fromStdString(m_config->value<std::string>("downloads.shortcut").value())));
+ connect(downloadsAction, &QAction::triggered, window, [this, window]() {
+ window->addDockWidget(Qt::RightDockWidgetArea, m_downloads.get());
+ });
+ window->addAction(MainWindow::ToolsMenu, downloadsAction);
- connect(_profile.get(), &WebEngineProfile::downloadRequested, m_downloadManager.get(), &DownloadsWidget::addDownload);
+ m_windows.append(window);
+ connect(window, &MainWindow::destroyed, this, [this, window]() {
+ m_windows.removeOne(window);
+ });
- m_profiles.insert(storageName, _profile);
- return _profile;
+ return window;
}
diff --git a/src/browser.h b/src/browser.h
index f96d8c5..b43d45a 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -6,8 +6,8 @@
* SPDX-License-Identifier: GPL-3.0
*/
-#ifndef BROWSER_H
-#define BROWSER_H
+#ifndef SMOLBOTE_BROWSER_H
+#define SMOLBOTE_BROWSER_H
#include "singleapplication.h"
#include <QJsonObject>
@@ -15,55 +15,34 @@
#include <memory>
class Configuration;
-class MainWindow;
class BookmarksWidget;
class DownloadsWidget;
class UrlRequestInterceptor;
-class WebEngineProfile;
+class MainWindow;
class Browser : public SingleApplication
{
Q_OBJECT
public:
- struct Plugin {
- QJsonObject meta;
- QObject *pointer;
- };
-
explicit Browser(int &argc, char *argv[]);
~Browser() final;
Q_DISABLE_COPY(Browser)
void setConfiguration(std::shared_ptr<Configuration> &config);
-
- std::shared_ptr<WebEngineProfile> profile(const QString &storageName);
-
- const QList<QString> profiles() const
- {
- return m_profiles.keys();
- }
-
- const QVector<Plugin> plugins() const
- {
- return m_plugins;
- }
+ void setup(const QString &defaultProfile);
public slots:
- MainWindow *createSession(const QString &profileName, bool newWindow, const QStringList &urls);
-
-private:
+ void createSession(const QString &profileName, bool newWindow, const QStringList &urls);
MainWindow *createWindow();
+private:
std::shared_ptr<Configuration> m_config;
+ std::shared_ptr<BookmarksWidget> m_bookmarks;
+ std::shared_ptr<DownloadsWidget> m_downloads;
+ std::shared_ptr<UrlRequestInterceptor> m_urlFilter;
QVector<MainWindow *> m_windows;
- QVector<Plugin> m_plugins;
- QHash<QString, std::shared_ptr<WebEngineProfile>> m_profiles;
- std::shared_ptr<WebEngineProfile> m_defaultProfile;
- UrlRequestInterceptor *m_urlRequestInterceptor = nullptr;
- std::shared_ptr<BookmarksWidget> m_bookmarksManager;
- std::shared_ptr<DownloadsWidget> m_downloadManager;
};
-#endif // BROWSER_H
+#endif // SMOLBOTE_BROWSER_H
diff --git a/src/commandline.h b/src/commandline.h
index f27041e..4229ac4 100644
--- a/src/commandline.h
+++ b/src/commandline.h
@@ -17,6 +17,7 @@ public:
CommandLine();
void parseCommandLine(const QCoreApplication &app);
+
void printHelp(int exitCode = 0);
void printVersion(int exitCode = 0);
void printBuild(int exitCode = 0);
diff --git a/src/forms/aboutdialog.cpp b/src/forms/aboutdialog.cpp
deleted file mode 100644
index 058c57d..0000000
--- a/src/forms/aboutdialog.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#include "aboutdialog.h"
-#include "browser.h"
-#include "ui_aboutdialog.h"
-#include "version.h"
-#include <QtWebEngine/QtWebEngineVersion>
-#include <boost/version.hpp>
-
-// compiler
-// clang also defines __GNUC__, so we need to check for clang first
-#if defined(__clang__)
-#define compiler "Clang " __clang_version__
-#elif defined(__GNUC__)
-#define compiler "GCC " __VERSION__
-#else
-#define compiler "unknown compiler";
-#endif
-
-AboutDialog::AboutDialog(QWidget *parent)
- : QDialog(parent)
- , ui(new Ui::AboutDialog)
-{
- setAttribute(Qt::WA_DeleteOnClose, true);
- ui->setupUi(this);
-
- auto *browser = dynamic_cast<Browser *>(QApplication::instance());
-
- ui->icon->setPixmap(dynamic_cast<QApplication *>(browser)->windowIcon().pixmap(72, 72));
-
- auto *aboutLabel = new QLabel(this);
- aboutLabel->setWordWrap(true);
- aboutLabel->setText(tr("<h2>smolbote " SMOLBOTE_VERSION "</h2>"
- "<p><i>yet another no-frills browser</i></p>"));
- ui->toolBox->addItem(aboutLabel, tr("About"));
-
- auto *licenseLabel = new QLabel(this);
- licenseLabel->setWordWrap(true);
- licenseLabel->setText(tr("<p>Copyright (C) 2017 Xian Nox</p>"
- "<p>This program is free software, and you are welcome to use it under the conditions set by the GNU GPLv3:"
- "<ul>"
- "<li> the freedom to use the software for any purpose,</li>"
- "<li> the freedom to change the software to suit your needs,</li>"
- "<li> the freedom to share the software with anyone,</li>"
- "<li> the freedom to share the changes you make, and</li>"
- "<li> the responsibility to grant the same freedoms when sharing the software.</li>"
- "</ul>"
- "<p>You can find the full license text in LICENSE.md.</p>"));
- ui->toolBox->addItem(licenseLabel, tr("License"));
-
- auto *libsLabel = new QLabel(this);
- libsLabel->setWordWrap(true);
- libsLabel->setText(tr("<h3>Version " SMOLBOTE_DESCRIBE "</h3>"
- "<p>Branch: " SMOLBOTE_BRANCH "<br>"
- "Compiled with " compiler "</p>"
- "<p><ul>"
- "<li>Qt " QT_VERSION_STR "</li>"
- "<li>QtWebEngine " QTWEBENGINE_VERSION_STR "</li>"
- "<li>Boost " BOOST_LIB_VERSION " </li>"
- "</ul></p>"));
- ui->toolBox->addItem(libsLabel, tr("Details"));
-
- // list profiles
- if(!browser->profiles().isEmpty()) {
- QString profilesText = tr("<p>Profile list:</p>"
- "<p><ul>");
- for(const QString &name : browser->profiles()) {
- if(name.isEmpty())
- profilesText += tr("<li>Off-the-record</li>");
- else
- profilesText += tr("<li>%1</li>").arg(name);
- }
- profilesText += tr("</ul></p>");
- libsLabel->setText(libsLabel->text() + profilesText);
- }
-
- // list plugins
- if(!browser->plugins().isEmpty()) {
- QString pluginText = tr("<p>Plugin list:</p>"
- "<p><ul>");
- for(const Browser::Plugin &plugin : browser->plugins()) {
- pluginText += tr("<li>%1 (%2)</li>").arg(plugin.meta["name"].toString(), plugin.meta["author"].toString());
- }
- pluginText += tr("</ul></p>");
- libsLabel->setText(libsLabel->text() + pluginText);
- }
-}
-
-AboutDialog::~AboutDialog()
-{
- delete ui;
-}
diff --git a/src/forms/aboutdialog.h b/src/forms/aboutdialog.h
deleted file mode 100644
index 265f3c9..0000000
--- a/src/forms/aboutdialog.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#ifndef SMOLBOTE_ABOUTDIALOG_H
-#define SMOLBOTE_ABOUTDIALOG_H
-
-#include <QDialog>
-
-namespace Ui
-{
-class AboutDialog;
-}
-
-class AboutDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit AboutDialog(QWidget *parent = nullptr);
- ~AboutDialog() override;
-
-private:
- Ui::AboutDialog *ui;
-};
-
-#endif // SMOLBOTE_ABOUTDIALOG_H
diff --git a/src/forms/aboutdialog.ui b/src/forms/aboutdialog.ui
deleted file mode 100644
index f7fe21e..0000000
--- a/src/forms/aboutdialog.ui
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>AboutDialog</class>
- <widget class="QDialog" name="AboutDialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>500</width>
- <height>600</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>About</string>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QLabel" name="icon">
- <property name="minimumSize">
- <size>
- <width>72</width>
- <height>72</height>
- </size>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QToolBox" name="toolBox">
- <property name="currentIndex">
- <number>-1</number>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Close</set>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>AboutDialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>AboutDialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/main.cpp b/src/main.cpp
index 75691f9..9fd009b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,47 +6,24 @@
* SPDX-License-Identifier: GPL-3.0
*/
-#include "browser.h"
#include "commandline.h"
#include "mainwindow/mainwindow.h"
#include "version.h"
-#include <iomanip>
-#include <iostream>
-#include "configuration/configuration.h"
-// startup time measuring
-#ifdef QT_DEBUG
-#include <QElapsedTimer>
-#endif
+#include "webengine/webprofile.h"
+#include "browser.h"
+#include <configuration/configuration.h>
+#include <memory>
int main(int argc, char **argv)
{
- // Create application object
- Browser instance(argc, argv);
- instance.setApplicationVersion(SMOLBOTE_VERSION);
-
-#ifdef QT_DEBUG
- QElapsedTimer timer;
- timer.start();
-#endif
+ Browser app(argc, argv);
CommandLine parser;
- parser.parseCommandLine(instance);
-
-#ifdef QT_DEBUG
- qDebug("config=%s", qUtf8Printable(parser.value(parser.configOption)));
- qDebug("profile=%s", qUtf8Printable(parser.value(parser.profileOption)));
- qDebug("socket=%s", qUtf8Printable(parser.value(parser.socketOption)));
-
-#endif
+ parser.parseCommandLine(app);
+ // create and load configuration
std::shared_ptr<Configuration> config = std::make_shared<Configuration>();
-
- // load user configuration
- if(!parser.value(parser.configOption).isEmpty()) {
- qDebug("Reading configuration [%s]: %s",
- qUtf8Printable(parser.value(parser.configOption)),
- config->read(parser.value(parser.configOption)) ? "ok" : "failed");
- }
+ config->read(parser.value(parser.configOption));
// parse command-line overrides
// we assume the users knows what they're doing, so we only pass the unknown options to program_options
@@ -59,43 +36,37 @@ int main(int argc, char **argv)
const char *_argv[_argc];
// program_options requires 0 to be the program name, otherwise it seems to fail
- _argv[0] = qUtf8Printable(instance.arguments().at(0));
+ _argv[0] = qUtf8Printable(app.arguments().at(0));
for(int i = 1; i < _argc; ++i) {
_argv[i] = qUtf8Printable(QString("--%1=%2").arg(parser.unknownOptions[i - 1].names().at(0), parser.value(parser.unknownOptions[i - 1])));
}
- qDebug("Parsing command-line overrides: %s", config->parse(_argc, _argv) ? "ok" : "failed");
+ config->parse(_argc, _argv);
}
- // check for other instances
- bool isSingleInstance = instance.bindLocalSocket(parser.value(parser.socketOption));
- if(isSingleInstance) {
- qDebug("Bound to local socket %s", qUtf8Printable(instance.serverName()));
- instance.setConfiguration(config);
- }
+ app.setConfiguration(config);
+
+ // set up socket
+ bool isSingleInstance = app.bindLocalSocket(parser.value(parser.socketOption));
+#ifdef QT_DEBUG
+ qDebug("bindLocalSocket(%s) = %s", qUtf8Printable(parser.value(parser.socketOption)), isSingleInstance ? "true" : "false");
+#endif
- // create session
- {
- QString profile;
+ // if we are the only instance, set up the browser
+ if(isSingleInstance) {
if(parser.isSet(parser.profileOption))
- profile = parser.value(parser.profileOption);
+ app.setup(parser.value(parser.profileOption));
else
- profile = QString::fromStdString(config->value<std::string>("browser.profile").value());
+ app.setup(QString::fromStdString(config->value<std::string>("profile.default").value()));
- instance.sendMessage(profile, parser.isSet(parser.newWindowOption), parser.positionalArguments());
+ QObject::connect(&app, &Browser::messageAvailable, &app, &Browser::createSession);
}
- if(!isSingleInstance) {
- return 0;
- }
-
-#ifdef QT_DEBUG
- qDebug("Startup complete in %lldms", timer.elapsed());
-#endif
+ app.sendMessage(parser.value(parser.profileOption), parser.isSet(parser.newWindowOption), parser.positionalArguments());
- // Normally we'd use
- //return instance.exec();
- // but, Call to "exec" is ambiguous
- return static_cast<QApplication *>(&instance)->exec();
+ if(isSingleInstance)
+ return app.exec();
+ else
+ return 0;
}
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp
index 99a80b8..c039c8e 100644
--- a/src/mainwindow/mainwindow.cpp
+++ b/src/mainwindow/mainwindow.cpp
@@ -7,301 +7,169 @@
*/
#include "mainwindow.h"
-#include "addressbar/urllineedit.h"
-#include "configuration/configuration.h"
-#include "forms/aboutdialog.h"
-#include "mainwindow/widgets/searchform.h"
-#include "ui_mainwindow.h"
-#include "widgets/mainwindowmenubar.h"
-#include "mainwindow/widgets/tabbar.h"
+#include "webengine/webview.h"
+#include "widgets/navigationbar.h"
+#include "window.h"
+#include <QApplication>
+#include <QCloseEvent>
#include <QDockWidget>
+#include <QLineEdit>
+#include <QMdiArea>
+#include <QMdiSubWindow>
+#include <QMenuBar>
#include <QMessageBox>
-#include <bookmarks/bookmarksview.h>
-#include <bookmarks/bookmarkswidget.h>
-#include <downloads/downloadswidget.h>
+#include <QShortcut>
+#include <QToolBar>
+#include <QUrl>
+#include <about/aboutdialog.h>
+#include <configuration/configuration.h>
-MainWindow::MainWindow(std::shared_ptr<Configuration> config, QWidget *parent)
+MainWindow::MainWindow(std::shared_ptr<Configuration> &config, QWidget *parent)
: QMainWindow(parent)
- , ui(new Ui::MainWindow)
- , tabBar(new TabBar(config->section("tabbar"), this))
- , m_addressBar(new UrlLineEdit(config->section("addressbar"), this))
- , m_progressBar(new LoadingBar(this))
- , menuBar(new MainWindowMenuBar(config, this))
+ , mdiArea(new QMdiArea(this))
{
Q_ASSERT(config);
m_config = config;
- // delete this window when it closes
- setAttribute(Qt::WA_DeleteOnClose, true);
-
- // set up UI
- ui->setupUi(this);
-
- QAction *fullscreenAction = new QAction(this);
- fullscreenAction->setShortcut(QKeySequence(QString::fromStdString(m_config->value<std::string>("browser.shortcuts.fullscreen").value())));
- connect(fullscreenAction, &QAction::triggered, this, &MainWindow::toggleFullscreen);
- addAction(fullscreenAction);
-
- // Dockable widget styling
- setDockOptions(dockOptions() | AllowTabbedDocks | ForceTabbedDocks);
- setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North);
- setTabPosition(Qt::RightDockWidgetArea, QTabWidget::North);
-
- // Add the toolbars
- // tabToolBar: main menu and tab list
- ui->mainToolBar->setMovable(m_config->value<bool>("browser.ui.tabtoolbarMovable").value());
- ui->mainToolBar->addWidget(menuBar);
- //tabToolBar->addWidget(tabBar);
-
- // navigationToolBar: address bar
- ui->navigationToolBar->setMovable(m_config->value<bool>("browser.ui.navtoolbarMovable").value());
- insertToolBarBreak(ui->navigationToolBar);
-
- // page actions
- m_navigationBar = new NavigationBar(this);
- m_navigationBar->addWidgetsTo(ui->navigationToolBar);
-
- ui->navigationToolBar->addWidget(m_addressBar);
+ // create UI
+ resize(config->value<int>("mainwindow.width").value(), config->value<int>("mainwindow.height").value());
+ titleSuffix = QString::fromStdString(config->value<std::string>("mainwindow.title").value());
+ setWindowTitle(tr("smolbote"));
+ if(config->value<bool>("mainwindow.maximized").value())
+ showMaximized();
+ else
+ show();
+
+ createMenuBar();
+ auto *navigationToolBar = new NavigationBar(config->section("navigation"), this);
+ navigationToolBar->setMovable(config->value<bool>("navigation.movable").value());
+ addToolBar(Qt::TopToolBarArea, navigationToolBar);
+ navigationToolBar->connectWebView(nullptr);
+
+ setCentralWidget(mdiArea);
+ mdiArea->setFocus();
+
+ connect(mdiArea, &QMdiArea::subWindowActivated, this, [this, navigationToolBar](QMdiSubWindow *window) {
+ disconnect(titleChangedConnection);
+ disconnect(navigationBarConnection);
+
+ auto *w = qobject_cast<Window *>(window);
+ if(w != nullptr) {
+ setWindowTitle(w->windowTitle() + titleSuffix);
+ titleChangedConnection = connect(w, &Window::windowTitleChanged, this, [this](const QString &title) {
+ this->setWindowTitle(title + titleSuffix);
+ });
- // connect signals
- connect(m_addressBar, &UrlLineEdit::addressEntered, this, [&](const QUrl &url) {
- tabBar->currentView()->load(url);
- });
- connect(m_addressBar, &UrlLineEdit::searchTermEntered, this, [&](const QString &term) {
- QString t = term;
- t.replace(' ', '+');
- QString url = QString::fromStdString(m_config->value<std::string>("profile.search").value());
- url.replace("$term", t);
- tabBar->currentView()->load(QUrl::fromUserInput(url));
+ navigationToolBar->connectWebView(w->currentView());
+ navigationBarConnection = connect(w, &Window::currentViewChanged, navigationToolBar, &NavigationBar::connectWebView);
+ }
});
- connect(tabBar, &TabBar::currentTabChanged, this, &MainWindow::handleTabChanged);
- // loading bar
- ui->statusBar->addPermanentWidget(m_progressBar);
-
- // search box
- m_searchBox = new SearchForm(this);
- ui->statusBar->addWidget(m_searchBox);
- m_searchBox->setVisible(false);
-
- resize(m_config->value<int>("browser.window.width").value(), m_config->value<int>("browser.window.height").value());
- if(m_config->value<bool>("browser.window.maximized").value()) {
- showMaximized();
- }
+ auto *tileShortcut = new QShortcut(QKeySequence(config->value<std::string>("mainwindow.shortcuts.tileWindows").value().c_str()), this);
+ connect(tileShortcut, &QShortcut::activated, this, [this]() {
+ mdiArea->tileSubWindows();
+ });
}
MainWindow::~MainWindow()
{
- // Release all dock widgets before deleting so we don't accidentally delete them
- // Also fixes that annoying crash when closing
- QList<QDockWidget *> allDockWidgets = findChildren<QDockWidget *>();
- for(QDockWidget *w : allDockWidgets) {
- if(w->widget()) {
- w->widget()->setParent(nullptr);
- }
- }
-
- delete ui;
+ disconnect(titleChangedConnection);
+ disconnect(navigationBarConnection);
}
-void MainWindow::addTabbedDock(Qt::DockWidgetArea area, QWidget *widget)
+void MainWindow::createMenuBar()
{
- // make a list of widgets in the area we want
- // this way we can append the new dock widget to the last one
- QVector<QDockWidget *> areaDockWidgets;
- for(QDockWidget *w : findChildren<QDockWidget *>()) {
- // check if widget is already shown
- if(w->widget() == widget) {
- // in this case, close the dock and return
- w->close();
- return;
- }
+ auto *smolboteMenu = menuBar()->addMenu(qApp->applicationDisplayName());
+ smolboteMenu->addAction(tr("New tab"), this, [this]() {
+ createTab(QUrl::fromUserInput("about:blank"));
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.newTab").value().c_str()));
- if(dockWidgetArea(w) == area) {
- areaDockWidgets.append(w);
- }
- }
+ smolboteMenu->addAction(tr("New tab group"), this, [this]() {
+ createSubWindow(QUrl::fromUserInput("about:blank"));
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.newGroup").value().c_str()));
+ smolboteMenu->addAction(tr("New window"))->setEnabled(false);
- // create a dock widget
- QDockWidget *dock = new QDockWidget(widget->windowTitle(), this);
- dock->setAttribute(Qt::WA_DeleteOnClose, true);
+ smolboteMenu->addSeparator();
- // when the dock widget becomes invisble, release the docked widget
- // setting the widget makes the dock its parent; setting parent back to nullptr
- // makes the dock not show the widget any more
- connect(dock, &QDockWidget::visibilityChanged, [dock](bool visible) {
- if(!visible && dock->widget()) {
- dock->widget()->setParent(nullptr);
- }
- });
- dock->setWidget(widget);
+ smolboteMenu->addAction(tr("About"), this, [this]() {
+ auto *dlg = new AboutDialog(this);
+ dlg->exec();
+ },
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.about").value().c_str()));
+ smolboteMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt);
- // the same widget may be shown by docks in other windows
- // in that case, they grab ownership and the current dock won't be showing anything
- // so the current widget needs to be closed
- auto *w = dynamic_cast<BookmarksWidget *>(widget);
- w->closeOthers();
- if(w) {
- connect(w, &BookmarksWidget::closeOthersSignal, dock, [dock]() {
- dock->close();
- });
- }
-
- if(areaDockWidgets.empty()) {
- // no other widgets
- addDockWidget(area, dock);
- } else {
- // there are other widgets, so put it after the last one
- tabifyDockWidget(areaDockWidgets.last(), dock);
- }
-}
+ smolboteMenu->addSeparator();
-void MainWindow::newTab(const QUrl &url)
-{
- if(!m_tabBarAdded) {
- m_tabBarAdded = true;
- ui->mainToolBar->addWidget(tabBar);
- }
- tabBar->addTab(createWebView(url, m_profile.get(), this));
-}
+ smolboteMenu->addAction(tr("Quit"), qApp, &QApplication::quit,
+ QKeySequence(m_config->value<std::string>("mainwindow.shortcuts.quit").value().c_str()));
-MainWindow *MainWindow::newWindow(const QUrl &url)
-{
- auto *instance = dynamic_cast<Browser *>(QApplication::instance());
- return instance->createSession(m_profile->storageName(), true, QStringList(url.toString()));
+ toolsMenu = menuBar()->addMenu(tr("Tools"));
}
-void MainWindow::closeEvent(QCloseEvent *event)
+void MainWindow::addAction(ActionLocation where, QAction *action)
{
- if(tabBar->count() > 1) {
- int ret = QMessageBox::warning(this, tr("Close window?"), tr("Close multiple tabs?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
- if(ret == QMessageBox::No) {
- event->ignore();
- return;
- }
+ switch(where) {
+ case ToolsMenu:
+ toolsMenu->addAction(action);
+ break;
+ default:
+ QMainWindow::addAction(action);
+ break;
}
- QMainWindow::closeEvent(event);
-}
-
-void MainWindow::about()
-{
- auto *dlg = new AboutDialog(this);
- dlg->exec();
}
-void MainWindow::setProfile(std::shared_ptr<WebEngineProfile> profile)
+void MainWindow::addDockWidget(Qt::DockWidgetArea area, QWidget *widget)
{
- Q_ASSERT(profile);
- m_profile = profile;
- tabBar->setProfile(profile.get());
- menuBar->profileAction()->setText(tr("Current profile: %1").arg(profile->name()));
-}
-
-WebEngineProfile *MainWindow::profile()
-{
- Q_ASSERT(m_profile);
- return m_profile.get();
-}
+ QDockWidget *dock = new QDockWidget(widget->windowTitle(), this);
+ dock->setAttribute(Qt::WA_DeleteOnClose, true);
+ dock->setWidget(widget);
-void MainWindow::setBookmarksWidget(std::shared_ptr<BookmarksWidget> &widget)
-{
- Q_ASSERT(widget);
- m_bookmarksWidget = widget;
- m_addressBar->setCompleterModel(m_bookmarksWidget->model());
- connect(menuBar->bookmarksAction(), &QAction::triggered, this, [this]() {
- addTabbedDock(Qt::RightDockWidgetArea, m_bookmarksWidget.get());
- });
- connect(m_bookmarksWidget.get(), &BookmarksWidget::openUrl, this, [this](const QUrl &url) {
- if(isActiveWindow()) {
- newTab(url);
+ connect(dock, &QDockWidget::visibilityChanged, [dock](bool visible) {
+ if(!visible && dock->widget()) {
+ dock->widget()->setParent(nullptr);
}
});
-}
-void MainWindow::setDownloadsWidget(std::shared_ptr<DownloadsWidget> &widget)
-{
- Q_ASSERT(widget);
- m_downloadsWidget = widget;
+ QMainWindow::addDockWidget(area, dock);
}
-void MainWindow::toggleFullscreen()
+void MainWindow::createTab(const QUrl &url)
{
- if(isFullScreen()) {
- setWindowState(Qt::WindowMaximized | Qt::WindowActive);
+ auto *w = qobject_cast<Window *>(mdiArea->currentSubWindow());
+ if(w == nullptr) {
+ w = createSubWindow(url);
} else {
- setWindowState(Qt::WindowFullScreen | Qt::WindowActive);
+ w->addTab(url);
}
}
-void MainWindow::handleTabChanged(WebView *view)
+Window *MainWindow::createSubWindow(const QUrl &url)
{
- Q_CHECK_PTR(view);
+ auto *w = new Window(this);
+ mdiArea->addSubWindow(w);
+ w->showMaximized();
+ w->setFocus();
- disconnect(titleChangedConnection);
- disconnect(newBookmarkConnection);
+ w->addTab(url);
- m_currentView = view;
-
- // centralWidget can be a nullptr
- if(centralWidget()) {
- // clear the parent of the central widget so it doesn't get deleted
- centralWidget()->setParent(nullptr);
-
- // disconnect signals
- disconnect(centralWidget());
- }
-
- // set new central widget
- setCentralWidget(view);
-
- // connect signals
- m_navigationBar->connectWebView(view);
-
- m_addressBar->connectWebView(view);
-
- titleChangedConnection = connect(view, &WebView::titleChanged, this, &MainWindow::handleTitleUpdated);
- newBookmarkConnection = connect(view, &WebView::newBookmark, this, [this](const QString &title, const QUrl &url) {
- if(m_bookmarksWidget) {
- auto *bookmark = m_bookmarksWidget->model()->createBookmark(nullptr);
- bookmark->setText(0, title);
- bookmark->setText(1, url.toString());
- }
- });
-
- m_progressBar->connectWebView(view);
-
- // update UI
- this->handleTitleUpdated(view->title());
- centralWidget()->setFocus();
+ return w;
}
-void MainWindow::handleTitleUpdated(const QString &title)
-{
- QString t = QString::fromStdString(m_config->value<std::string>("browser.window.title").value());
- t.replace("title", title);
- t.replace("profile", m_profile->name());
- setWindowTitle(t);
- //setWindowTitle(browser->settings()->value("window.title").toString().replace("title", title).replace("profile", tabBar->profile()->name()));
-}
-
-void MainWindow::addPlugins(const QVector<Browser::Plugin> &plugins)
+void MainWindow::closeEvent(QCloseEvent *event)
{
- for(const Browser::Plugin &plugin : plugins) {
- ProfileInterface *iProfilePlugin = qobject_cast<ProfileInterface *>(plugin.pointer);
- if(iProfilePlugin) {
- QWidget *w = iProfilePlugin->createWidget(m_profile.get(), this);
-
- menuBar->profileAction()->setEnabled(true);
- connect(menuBar->profileAction(), &QAction::triggered, this, [this, w]() {
- w->setVisible(!w->isVisible());
- if(w->isVisible()) {
- QPoint pos = ui->navigationToolBar->pos();
- pos.setX(pos.x() + ui->navigationToolBar->width() - w->width());
- pos.setY(pos.y() + ui->navigationToolBar->height());
- w->move(mapToGlobal(pos));
- w->show();
- }
- });
+ if(mdiArea->subWindowList().count() > 1) {
+ int choice = QMessageBox::question(this, tr("Close multiple subwindows?"), tr("Do you want to close all subwindows?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ if(choice == QMessageBox::No) {
+ event->ignore();
+ return;
}
}
+
+ mdiArea->closeAllSubWindows();
+ if(mdiArea->currentSubWindow())
+ event->ignore();
+ else
+ event->accept();
}
diff --git a/src/mainwindow/mainwindow.h b/src/mainwindow/mainwindow.h
index 8b205ab..1817fdd 100644
--- a/src/mainwindow/mainwindow.h
+++ b/src/mainwindow/mainwindow.h
@@ -6,93 +6,49 @@
* SPDX-License-Identifier: GPL-3.0
*/
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
+#ifndef SMOLBOTE_MAINWINDOW_H
+#define SMOLBOTE_MAINWINDOW_H
-#include "browser.h"
-#include "webengine/webengineprofile.h"
-#include "widgets/loadingbar.h"
-#include "widgets/navigationbar.h"
#include <QMainWindow>
-#include <QUrl>
-#include <interfaces.h>
#include <memory>
-namespace Ui
-{
-class MainWindow;
-}
-
-class TabBar;
-class SearchForm;
+class QMdiArea;
class Configuration;
-class BookmarksWidget;
-class DownloadsWidget;
-class MainWindowMenuBar;
-class UrlLineEdit;
-
+class Window;
class MainWindow : public QMainWindow
{
Q_OBJECT
- friend class WebView;
- friend class SearchForm;
-
- friend class MainWindowMenuBar;
-
- friend class NavigationBar;
-
public:
- explicit MainWindow(std::shared_ptr<Configuration> config, QWidget *parent = nullptr);
+ enum ActionLocation {
+ ToolsMenu
+ };
+
+ explicit MainWindow(std::shared_ptr<Configuration> &config, QWidget *parent = nullptr);
Q_DISABLE_COPY(MainWindow)
~MainWindow() override;
- void addTabbedDock(Qt::DockWidgetArea area, QWidget *widget);
-
-public slots:
- void about();
-
- void newTab(const QUrl &url = QUrl(""));
- MainWindow *newWindow(const QUrl &url = QUrl(""));
+ void createMenuBar();
- void setProfile(std::shared_ptr<WebEngineProfile> profile);
- WebEngineProfile *profile();
+ void addAction(ActionLocation where, QAction *action);
+ void addDockWidget(Qt::DockWidgetArea area, QWidget *widget);
- void setBookmarksWidget(std::shared_ptr<BookmarksWidget> &widget);
- void setDownloadsWidget(std::shared_ptr<DownloadsWidget> &widget);
- void addPlugins(const QVector<Browser::Plugin> &plugins);
-
- void toggleFullscreen();
+public slots:
+ void createTab(const QUrl &url);
+ Window *createSubWindow(const QUrl &url);
protected:
void closeEvent(QCloseEvent *event) override;
-private slots:
- void handleTabChanged(WebView *view);
- void handleTitleUpdated(const QString &title);
-
private:
- Ui::MainWindow *ui;
- SearchForm *m_searchBox;
-
- TabBar *tabBar;
- WebView *m_currentView;
-
- MainWindowMenuBar *menuBar;
-
- // navigation
- NavigationBar *m_navigationBar;
- UrlLineEdit *m_addressBar;
- LoadingBar *m_progressBar;
+ QString titleSuffix;
+ QMenu *toolsMenu = nullptr;
+ QMdiArea *mdiArea;
- bool m_tabBarAdded = false;
- std::shared_ptr<WebEngineProfile> m_profile;
std::shared_ptr<Configuration> m_config;
- std::shared_ptr<BookmarksWidget> m_bookmarksWidget;
- std::shared_ptr<DownloadsWidget> m_downloadsWidget;
QMetaObject::Connection titleChangedConnection;
- QMetaObject::Connection newBookmarkConnection;
+ QMetaObject::Connection navigationBarConnection;
};
-#endif // MAINWINDOW_H
+#endif // SMOLBOTE_MAINWINDOW_H
diff --git a/src/mainwindow/mainwindow.ui b/src/mainwindow/mainwindow.ui
deleted file mode 100644
index 12a3a6c..0000000
--- a/src/mainwindow/mainwindow.ui
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>300</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>MainWindow</string>
- </property>
- <widget class="QWidget" name="centralWidget"/>
- <widget class="QStatusBar" name="statusBar">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>24</height>
- </size>
- </property>
- </widget>
- <widget class="QToolBar" name="mainToolBar">
- <property name="windowTitle">
- <string>Main</string>
- </property>
- <property name="allowedAreas">
- <set>Qt::TopToolBarArea</set>
- </property>
- <attribute name="toolBarArea">
- <enum>TopToolBarArea</enum>
- </attribute>
- <attribute name="toolBarBreak">
- <bool>false</bool>
- </attribute>
- </widget>
- <widget class="QToolBar" name="navigationToolBar">
- <property name="windowTitle">
- <string>Navigation</string>
- </property>
- <property name="allowedAreas">
- <set>Qt::TopToolBarArea</set>
- </property>
- <attribute name="toolBarArea">
- <enum>TopToolBarArea</enum>
- </attribute>
- <attribute name="toolBarBreak">
- <bool>false</bool>
- </attribute>
- </widget>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/mainwindow/widgets/loadingbar.cpp b/src/mainwindow/widgets/loadingbar.cpp
index 76eafc4..61e3eae 100644
--- a/src/mainwindow/widgets/loadingbar.cpp
+++ b/src/mainwindow/widgets/loadingbar.cpp
@@ -7,8 +7,8 @@
*/
#include "loadingbar.h"
-#include <QTimer>
#include "webengine/webview.h"
+#include <QTimer>
LoadingBar::LoadingBar(QWidget *parent)
: QProgressBar(parent)
diff --git a/src/mainwindow/widgets/navigationbar.cpp b/src/mainwindow/widgets/navigationbar.cpp
index 0652159..e2c714e 100644
--- a/src/mainwindow/widgets/navigationbar.cpp
+++ b/src/mainwindow/widgets/navigationbar.cpp
@@ -7,7 +7,9 @@
*/
#include "navigationbar.h"
-#include "mainwindow/mainwindow.h"
+#include "addressbar/urllineedit.h"
+#include "configuration/configuration.h"
+#include "webengine/webview.h"
#include <QHBoxLayout>
#include <QMenu>
#include <QShortcut>
@@ -15,99 +17,94 @@
#include <QToolBar>
#include <QToolButton>
#include <QWebEngineHistory>
-#include "webengine/webview.h"
-#include "configuration/configuration.h"
-NavigationBar::NavigationBar(MainWindow *parent)
- : QObject(parent)
+NavigationBar::NavigationBar(const QHash<QString, QString> &conf, QWidget *parent)
+ : QToolBar(parent)
{
qStyle = parent->style();
// Back button
- backButton = new QToolButton(parent);
- backButton->setIcon(qStyle->standardIcon(QStyle::SP_ArrowBack));
- backButton->setShortcut(QString::fromStdString(parent->m_config->value<std::string>("browser.shortcuts.back").value()));
- connect(backButton, &QToolButton::clicked, this, [this]() {
+ backAction = addAction(qStyle->standardIcon(QStyle::SP_ArrowBack), tr("Back"));
+ backAction->setShortcut(QKeySequence(conf.value("navigation.shortcuts.back")));
+ connect(backAction, &QAction::triggered, this, [this]() {
m_view->history()->back();
});
- auto *backMenu = new QMenu(backButton);
- backButton->setMenu(backMenu);
+ auto *backMenu = new QMenu(this);
connect(backMenu, &QMenu::aboutToShow, this, [this, backMenu]() {
backMenu->clear();
- const QList<QWebEngineHistoryItem> items = m_view->history()->backItems(10);
- for(const QWebEngineHistoryItem &i : items) {
- QAction *a = backMenu->addAction(i.title());
- connect(a, &QAction::triggered, this, [i, this]() {
- m_view->history()->goToItem(i);
+ for(const QWebEngineHistoryItem &item : m_view->history()->backItems(10)) {
+ auto *action = backMenu->addAction(item.title());
+ connect(action, &QAction::triggered, this, [item, this]() {
+ m_view->history()->goToItem(item);
});
}
});
+ backAction->setMenu(backMenu);
// Forward button
- forwardButton = new QToolButton(parent);
- forwardButton->setIcon(qStyle->standardIcon(QStyle::SP_ArrowForward));
- forwardButton->setShortcut(QString::fromStdString(parent->m_config->value<std::string>("browser.shortcuts.forward").value()));
- connect(forwardButton, &QToolButton::clicked, this, [this]() {
+ forwardAction = addAction(qStyle->standardIcon(QStyle::SP_ArrowForward), tr("Forward"));
+ forwardAction->setShortcut(QKeySequence(conf.value("navigation.shortcuts.forward")));
+ connect(forwardAction, &QAction::triggered, this, [this]() {
m_view->history()->forward();
});
- auto *forwardMenu = new QMenu(forwardButton);
- forwardButton->setMenu(forwardMenu);
+ auto *forwardMenu = new QMenu(this);
connect(forwardMenu, &QMenu::aboutToShow, this, [this, forwardMenu]() {
forwardMenu->clear();
- const QList<QWebEngineHistoryItem> items = m_view->history()->forwardItems(10);
- for(const QWebEngineHistoryItem &i : items) {
- QAction *a = forwardMenu->addAction(i.title());
- connect(a, &QAction::triggered, this, [i, this]() {
- m_view->history()->goToItem(i);
+ for(const QWebEngineHistoryItem &item : m_view->history()->forwardItems(10)) {
+ auto *action = forwardMenu->addAction(item.title());
+ connect(action, &QAction::triggered, this, [item, this]() {
+ m_view->history()->goToItem(item);
});
}
});
+ forwardAction->setMenu(forwardMenu);
// Stop/Refresh button
- stopReloadButton = new QToolButton(parent);
- stopReloadButton->setIcon(qStyle->standardIcon(QStyle::SP_BrowserReload));
- stopReloadButton->setShortcut(QString::fromStdString(parent->m_config->value<std::string>("browser.shortcuts.refresh").value()));
- connect(stopReloadButton, &QToolButton::clicked, this, [this]() {
+ stopReloadAction = addAction(qStyle->standardIcon(QStyle::SP_BrowserReload), tr("Reload"));
+ stopReloadAction->setShortcut(QKeySequence(conf.value("navigation.shortcuts.refresh")));
+ connect(stopReloadAction, &QAction::triggered, this, [this]() {
if(m_view->isLoaded())
m_view->reload();
else
m_view->stop();
});
- auto *reloadShortcut = new QShortcut(
- QString::fromStdString(parent->m_config->value<std::string>("browser.shortcuts.reload").value()),
- parent);
- connect(reloadShortcut, &QShortcut::activated, this, [this]() {
- m_view->reload();
- });
-
// Home button
- homeButton = new QToolButton(parent);
- homeButton->setIcon(qStyle->standardIcon(QStyle::SP_DirHomeIcon));
- homeButton->setShortcut(QString::fromStdString(parent->m_config->value<std::string>("browser.shortcuts.home").value()));
- connect(homeButton, &QToolButton::clicked, this, [this, parent]() {
- m_view->load(parent->m_profile->homepage());
+ homeAction = addAction(qStyle->standardIcon(QStyle::SP_DirHomeIcon), tr("Home"));
+ homeAction->setShortcut(QKeySequence(conf.value("navigation.shortcuts.home")));
+ connect(homeAction, &QAction::triggered, this, [this]() {
+ m_view->triggerViewAction(WebView::GoHome);
});
-}
-void NavigationBar::addWidgetsTo(QToolBar *toolBar)
-{
- toolBar->addWidget(backButton);
- toolBar->addWidget(forwardButton);
- toolBar->addWidget(stopReloadButton);
- toolBar->addWidget(homeButton);
+ QHash<QString, QString> a;
+ addressBar = new UrlLineEdit(a, this);
+ addWidget(addressBar);
+
+ auto *focusShortcut = new QShortcut(QKeySequence("F4"), this);
+ connect(focusShortcut, &QShortcut::activated, this, [this]() {
+ addressBar->setFocus();
+ addressBar->selectAll();
+ });
}
void NavigationBar::connectWebView(WebView *view)
{
- Q_CHECK_PTR(view);
m_view = view;
disconnect(loadStartedConnection);
disconnect(loadFinishedConnection);
+ if(view == nullptr) {
+ backAction->setEnabled(false);
+ forwardAction->setEnabled(false);
+ stopReloadAction->setEnabled(false);
+ homeAction->setEnabled(false);
+
+ return;
+ }
+
if(view->isLoaded()) {
update_loadFinished();
} else {
@@ -116,18 +113,22 @@ void NavigationBar::connectWebView(WebView *view)
loadStartedConnection = connect(view, &QWebEngineView::loadStarted, this, &NavigationBar::update_loadStarted);
loadFinishedConnection = connect(view, &WebView::loaded, this, &NavigationBar::update_loadFinished);
+ stopReloadAction->setEnabled(true);
+ homeAction->setEnabled(true);
+
+ addressBar->connectWebView(view);
}
void NavigationBar::update_loadStarted()
{
- backButton->setEnabled(m_view->history()->canGoForward());
- forwardButton->setEnabled(m_view->history()->canGoForward());
- stopReloadButton->setIcon(qStyle->standardIcon(QStyle::SP_BrowserStop));
+ backAction->setEnabled(m_view->history()->canGoForward());
+ forwardAction->setEnabled(m_view->history()->canGoForward());
+ stopReloadAction->setIcon(qStyle->standardIcon(QStyle::SP_BrowserStop));
}
void NavigationBar::update_loadFinished()
{
- backButton->setEnabled(m_view->history()->canGoBack());
- forwardButton->setEnabled(m_view->history()->canGoForward());
- stopReloadButton->setIcon(qStyle->standardIcon(QStyle::SP_BrowserReload));
+ backAction->setEnabled(m_view->history()->canGoBack());
+ forwardAction->setEnabled(m_view->history()->canGoForward());
+ stopReloadAction->setIcon(qStyle->standardIcon(QStyle::SP_BrowserReload));
}
diff --git a/src/mainwindow/widgets/navigationbar.h b/src/mainwindow/widgets/navigationbar.h
index fd0579d..1b4cc05 100644
--- a/src/mainwindow/widgets/navigationbar.h
+++ b/src/mainwindow/widgets/navigationbar.h
@@ -6,36 +6,21 @@
* SPDX-License-Identifier: GPL-3.0
*/
-/*
- * Why is this class a QObject and not a QWidget, and why don't we add the
- * NavigationBar itself to the toolbar?
- * That was the original idea: make a NavBar class, friend it from MainWindow
- * to gain access to the config, but there's a couple of issues:
- * - adding QToolButtons to a widget that's inside a toolbar makes the buttons
- * look absolutely hideous: they're smaller and have a border for some reason
- * - if you stylesheet the border away (which is a pain), they're still not
- * the same size
- * And so we ended up having this class only exist to contain all of the logic
- * for the nav buttons (which cuts down the code in MainWindow).
- */
-
-#ifndef NAVIGATIONBAR_H
-#define NAVIGATIONBAR_H
+#ifndef SMOLBOTE_NAVIGATIONBAR_H
+#define SMOLBOTE_NAVIGATIONBAR_H
-#include <QObject>
+#include <QToolBar>
-class QStyle;
-class QToolBar;
-class QToolButton;
-class MainWindow;
+class UrlLineEdit;
class WebView;
-class NavigationBar : public QObject
+class NavigationBar : public QToolBar
{
Q_OBJECT
+
public:
- explicit NavigationBar(MainWindow *parent = nullptr);
+ explicit NavigationBar(const QHash<QString, QString> &conf, QWidget *parent = nullptr);
- void addWidgetsTo(QToolBar *toolBar);
+public slots:
void connectWebView(WebView *view);
private slots:
@@ -45,11 +30,13 @@ private slots:
private:
QStyle *qStyle;
WebView *m_view;
- QToolButton *backButton, *forwardButton;
- QToolButton *stopReloadButton;
- QToolButton *homeButton;
+
+ QAction *backAction, *forwardAction;
+ QAction *stopReloadAction;
+ QAction *homeAction;
+ UrlLineEdit *addressBar;
QMetaObject::Connection loadStartedConnection, loadFinishedConnection;
};
-#endif //NAVIGATIONBAR_H
+#endif // SMOLBOTE_NAVIGATIONBAR_H
diff --git a/src/mainwindow/widgets/searchform.cpp b/src/mainwindow/widgets/searchform.cpp
index 8ac1bc2..07b8426 100644
--- a/src/mainwindow/widgets/searchform.cpp
+++ b/src/mainwindow/widgets/searchform.cpp
@@ -7,11 +7,11 @@
*/
#include "searchform.h"
+#include "configuration/configuration.h"
#include "mainwindow/mainwindow.h"
#include "ui_searchform.h"
-#include <QAction>
#include "webengine/webview.h"
-#include "configuration/configuration.h"
+#include <QAction>
SearchForm::SearchForm(MainWindow *parentWindow, QWidget *parent)
: QWidget(parent)
diff --git a/src/mainwindow/widgets/tabbar.cpp b/src/mainwindow/widgets/tabbar.cpp
deleted file mode 100644
index ef32ef0..0000000
--- a/src/mainwindow/widgets/tabbar.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#include "tabbar.h"
-#include "mainwindow/mainwindow.h"
-#include "webengine/webengineprofile.h"
-#include "webengine/webview.h"
-#include <QContextMenuEvent>
-#include <QMenu>
-
-TabBar::TabBar(const QHash<QString, QString> &config, MainWindow *parent)
- : QTabBar(parent)
-{
- Q_CHECK_PTR(parent);
-
- setElideMode(Qt::ElideRight);
- setTabsClosable(true);
- setMovable(true);
- setContextMenuPolicy(Qt::DefaultContextMenu);
-
- connect(this, &TabBar::tabCloseRequested, this, &TabBar::removeTab);
- connect(this, &TabBar::currentChanged, this, &TabBar::handleCurrentChanged);
- connect(this, &TabBar::tabMoved, this, &TabBar::updateVectorArrangement);
-
- newTab_action = new QAction(tr("New Tab"), parent);
- newTab_action->setObjectName("newTab_action");
- newTab_action->setShortcut(QKeySequence(config["tabbar.shortcuts.new"]));
- connect(newTab_action, &QAction::triggered, parent, [parent, this]() {
- parent->newTab(parent->profile()->newtab());
- });
- parent->addAction(newTab_action);
-
- closeTab_action = new QAction(tr("Close Tab"), parent);
- closeTab_action->setObjectName("closeTab_action");
- closeTab_action->setShortcut(QKeySequence(config["tabbar.shortcuts.close"]));
- connect(closeTab_action, &QAction::triggered, this, [this]() {
- removeTab(currentIndex());
- });
- parent->addAction(closeTab_action);
-
- leftTab_action = new QAction(tr("Left Tab"), parent);
- leftTab_action->setObjectName("leftTab_action");
- leftTab_action->setShortcut(QKeySequence(config["tabbar.shortcuts.left"]));
- connect(leftTab_action, &QAction::triggered, this, [this]() {
- setCurrentIndex(currentIndex() - 1);
- });
- parent->addAction(leftTab_action);
-
- rightTab_action = new QAction(tr("Right Tab"), parent);
- rightTab_action->setObjectName("rightTab_action");
- rightTab_action->setShortcut(QKeySequence(config["tabbar.shortcuts.right"]));
- connect(rightTab_action, &QAction::triggered, this, [this]() {
- setCurrentIndex(currentIndex() + 1);
- });
- parent->addAction(rightTab_action);
-
- // tab context menu
- {
- tabContextMenu = new QMenu(this);
-
- auto *closeTab = tabContextMenu->addAction(tr("Close Tab"));
- connect(closeTab, &QAction::triggered, this, [this]() {
- removeTab(tabAt(mapFromGlobal(tabContextMenu->pos())));
- });
-
- auto *closeTabsLeft = tabContextMenu->addAction(tr("Close Tabs left"));
- connect(closeTabsLeft, &QAction::triggered, this, [this]() {
- int idx = tabAt(mapFromGlobal(tabContextMenu->pos()));
- for(int i = idx - 1; i >= 0; --i) {
- removeTab(i);
- }
- });
-
- auto *closeTabsRight = tabContextMenu->addAction(tr("Close Tabs right"));
- connect(closeTabsRight, &QAction::triggered, this, [this]() {
- int idx = tabAt(mapFromGlobal(tabContextMenu->pos()));
- for(int i = count() - 1; i > idx; --i) {
- removeTab(i);
- }
- });
- }
-}
-
-TabBar::~TabBar()
-{
- // cleanup
- qDeleteAll(m_views);
- m_views.clear();
-}
-
-void TabBar::setProfile(WebEngineProfile *profile)
-{
- Q_CHECK_PTR(profile);
-
- for(auto view : qAsConst(m_views)) {
- auto *page = new WebPage(profile);
- page->load(view->url());
- view->page()->deleteLater();
- view->setPage(page);
- }
-}
-
-WebView *TabBar::currentView()
-{
- return m_views.at(currentIndex());
-}
-
-int TabBar::addTab(WebView *view)
-{
- m_views.append(view);
-
- connect(view, &QWebEngineView::titleChanged, [this, view](const QString &title) {
- int index = m_views.indexOf(view);
- setTabText(index, title);
- setTabToolTip(index, title);
- });
- connect(view, &QWebEngineView::iconChanged, [this, view](const QIcon &icon) {
- int index = m_views.indexOf(view);
- setTabIcon(index, icon);
- });
-
- return QTabBar::addTab("New Tab");
-}
-
-void TabBar::removeTab(int index)
-{
- // remove the tab data from the index
- m_views.at(index)->deleteLater();
- m_views.remove(index);
-
- // remove the tab from the QTabBar
- // this emits the currentTabChanged signal, so it should be done after the view is removed from the index
- QTabBar::removeTab(index);
-}
-
-void TabBar::contextMenuEvent(QContextMenuEvent *event)
-{
- // check if the context menu was called on a tab
- int tabIndex = tabAt(event->pos());
- if(tabIndex < 0) {
- return;
- }
-
- tabContextMenu->exec(event->globalPos());
-}
-
-QSize TabBar::tabSizeHint(int index) const
-{
- Q_UNUSED(index)
- return QSize(200, this->height());
-}
-
-void TabBar::handleCurrentChanged(int index)
-{
- if(index < 0) {
- newTab_action->trigger();
- return;
- }
-
- emit currentTabChanged(m_views.at(index));
-}
-
-void TabBar::updateVectorArrangement(int from, int to)
-{
- m_views.move(from, to);
-}
diff --git a/src/mainwindow/widgets/tabbar.h b/src/mainwindow/widgets/tabbar.h
deleted file mode 100644
index f4b7414..0000000
--- a/src/mainwindow/widgets/tabbar.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#ifndef SMOLBOTE_TABBAR_H
-#define SMOLBOTE_TABBAR_H
-
-#include <QTabBar>
-
-class MainWindow;
-class WebView;
-class WebEngineProfile;
-class QMenu;
-class TabBar : public QTabBar
-{
- Q_OBJECT
-
-public:
- explicit TabBar(const QHash<QString, QString> &config, MainWindow *parent = nullptr);
- ~TabBar() override;
-
- void setProfile(WebEngineProfile *profile);
- WebView *currentView();
-
-signals:
- void currentTabChanged(WebView *view);
-
-public slots:
- int addTab(WebView *view);
- void removeTab(int index);
-
-protected:
- void contextMenuEvent(QContextMenuEvent *event) override;
- QSize tabSizeHint(int index) const override;
-
-private slots:
- void handleCurrentChanged(int index);
- void updateVectorArrangement(int from, int to);
-
-private:
- // store all views in a vector since tabs can only store a QVariant, and that can't easily take a pointer
- QVector<WebView *> m_views;
-
- QMenu *tabContextMenu;
-
- QAction *newTab_action;
- QAction *closeTab_action;
- QAction *leftTab_action;
- QAction *rightTab_action;
-};
-
-#endif // SMOLBOTE_TABBAR_H
diff --git a/src/mainwindow/widgets/tabwidget.cpp b/src/mainwindow/widgets/tabwidget.cpp
new file mode 100644
index 0000000..21476cd
--- /dev/null
+++ b/src/mainwindow/widgets/tabwidget.cpp
@@ -0,0 +1,121 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "tabwidget.h"
+#include "webengine/webview.h"
+#include <QAction>
+#include <QContextMenuEvent>
+#include <QMenu>
+#include <QTabBar>
+
+TabWidget::TabWidget(QWidget *parent)
+ : QTabWidget(parent)
+{
+ setStyleSheet("QTabBar::tab { width: 200px; }");
+
+ setTabsClosable(true);
+ setTabBarAutoHide(true);
+ setElideMode(Qt::ElideRight);
+ setMovable(true);
+
+ connect(this, &TabWidget::tabCloseRequested, this, &TabWidget::deleteTab);
+
+ // general actions
+ closeTab_action = new QAction(this);
+ closeTab_action->setShortcut(QKeySequence("Ctrl+X"));
+ connect(closeTab_action, &QAction::triggered, this, [this]() {
+ this->deleteTab(this->currentIndex());
+ });
+ addAction(closeTab_action);
+
+ leftTab_action = new QAction(this);
+ leftTab_action->setShortcut(QKeySequence("Ctrl+O"));
+ connect(leftTab_action, &QAction::triggered, this, [this]() {
+ this->setCurrentIndex(qMax(0, this->currentIndex() - 1));
+ });
+ addAction(leftTab_action);
+
+ rightTab_action = new QAction(this);
+ rightTab_action->setShortcut(QKeySequence("Ctrl+P"));
+ connect(rightTab_action, &QAction::triggered, this, [this]() {
+ this->setCurrentIndex(qMin(this->currentIndex() + 1, this->count() - 1));
+ });
+ addAction(rightTab_action);
+
+ // context menu
+ tabContextMenu = new QMenu(this);
+ auto *closeTab = tabContextMenu->addAction(tr("Close Tab"));
+ connect(closeTab, &QAction::triggered, this, [this]() {
+ deleteTab(this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos())));
+ });
+
+ auto *closeTabsLeft = tabContextMenu->addAction(tr("Close Tabs left"));
+ connect(closeTabsLeft, &QAction::triggered, this, [this]() {
+ int idx = this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos()));
+ for(int i = idx - 1; i >= 0; --i) {
+ deleteTab(i);
+ }
+ });
+
+ auto *closeTabsRight = tabContextMenu->addAction(tr("Close Tabs right"));
+ connect(closeTabsRight, &QAction::triggered, this, [this]() {
+ int idx = this->tabBar()->tabAt(mapFromGlobal(tabContextMenu->pos()));
+ for(int i = count() - 1; i > idx; --i) {
+ deleteTab(i);
+ }
+ });
+}
+
+TabWidget::~TabWidget()
+{
+ for(int i = count() - 1; i >= 0; i--) {
+ delete widget(i);
+ }
+}
+
+int TabWidget::addTab(WebView *view)
+{
+ Q_CHECK_PTR(view);
+
+ int idx = QTabWidget::addTab(view, view->title());
+ connect(view, &WebView::titleChanged, [this, view](const QString &title) {
+ int idx = this->indexOf(view);
+ Q_ASSERT(idx != -1);
+
+ this->setTabText(idx, title);
+ });
+ connect(view, &WebView::iconChanged, [this, view](const QIcon &icon) {
+ int idx = this->indexOf(view);
+ Q_ASSERT(idx != -1);
+
+ this->setTabIcon(idx, icon);
+ });
+
+ return idx;
+}
+
+void TabWidget::deleteTab(int index)
+{
+ // deleting the widget automatically removes the tab?
+ if(count() > 1) {
+ widget(index)->deleteLater();
+ removeTab(index);
+ } else
+ parentWidget()->close();
+}
+
+void TabWidget::contextMenuEvent(QContextMenuEvent *event)
+{
+ // check if the context menu was called on a tab
+ int tabIndex = tabBar()->tabAt(event->pos());
+ if(tabIndex < 0) {
+ return;
+ }
+
+ tabContextMenu->exec(event->globalPos());
+}
diff --git a/src/mainwindow/widgets/tabwidget.h b/src/mainwindow/widgets/tabwidget.h
new file mode 100644
index 0000000..b7aad63
--- /dev/null
+++ b/src/mainwindow/widgets/tabwidget.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_TABWIDGET_H
+#define SMOLBOTE_TABWIDGET_H
+
+#include <QTabWidget>
+
+class QAction;
+class QMenu;
+class WebView;
+class TabWidget : public QTabWidget
+{
+ Q_OBJECT
+
+public:
+ explicit TabWidget(QWidget *parent = nullptr);
+ ~TabWidget() override;
+
+public slots:
+ int addTab(WebView *view);
+ void deleteTab(int index);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event) override;
+
+private:
+ QAction *closeTab_action;
+ QAction *leftTab_action;
+ QAction *rightTab_action;
+
+ QMenu *tabContextMenu;
+};
+
+#endif // SMOLBOTE_TABWIDGET_H
diff --git a/src/mainwindow/window.cpp b/src/mainwindow/window.cpp
new file mode 100644
index 0000000..67397fe
--- /dev/null
+++ b/src/mainwindow/window.cpp
@@ -0,0 +1,68 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "window.h"
+#include "webengine/webprofile.h"
+#include "webengine/webview.h"
+#include "widgets/tabwidget.h"
+#include <QUrl>
+
+Window::Window(QWidget *parent, Qt::WindowFlags flags)
+ : QMdiSubWindow(parent, flags)
+ , tabWidget(new TabWidget(this))
+{
+ // delete this window when it closes
+ setAttribute(Qt::WA_DeleteOnClose, true);
+
+ resize(800, 600);
+ setWidget(tabWidget);
+
+ connect(tabWidget, &TabWidget::currentChanged, [this](int index) {
+ if(index < 0) {
+ // last tab has been closed
+ close();
+ } else {
+ auto *view = dynamic_cast<WebView *>(tabWidget->widget(index));
+ Q_CHECK_PTR(view);
+
+ disconnect(titleConnection);
+ connect(view, &WebView::titleChanged, this, &Window::setWindowTitle);
+ setWindowTitle(view->title());
+
+ emit currentViewChanged(view);
+ }
+ });
+}
+
+Window::~Window()
+{
+ delete tabWidget;
+}
+
+WebView *Window::currentView()
+{
+ return qobject_cast<WebView *>(tabWidget->currentWidget());
+}
+
+int Window::addTab(WebView *view)
+{
+ Q_CHECK_PTR(view);
+ return tabWidget->addTab(view);
+}
+
+int Window::addTab(const QUrl &url)
+{
+ auto *view = new WebView(WebProfile::defaultProfile(), this);
+ view->load(url);
+ return tabWidget->addTab(view);
+}
+
+void Window::swapToTab(int index)
+{
+ tabWidget->setCurrentIndex(index);
+}
diff --git a/src/mainwindow/window.h b/src/mainwindow/window.h
new file mode 100644
index 0000000..743d75f
--- /dev/null
+++ b/src/mainwindow/window.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_WINDOW_H
+#define SMOLBOTE_WINDOW_H
+
+#include <QMdiSubWindow>
+#include <memory>
+
+class TabWidget;
+class WebView;
+class Window : public QMdiSubWindow
+{
+ Q_OBJECT
+
+public:
+ explicit Window(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
+ ~Window() override;
+
+ WebView *currentView();
+
+signals:
+ void currentViewChanged(WebView *view);
+
+public slots:
+ int addTab(WebView *view);
+ int addTab(const QUrl &url);
+
+ void swapToTab(int index);
+
+private:
+ TabWidget *tabWidget;
+
+ QMetaObject::Connection titleConnection;
+};
+
+#endif // SMOLBOTE_WINDOW_H
diff --git a/src/version.h.in b/src/version.h.in
index a5c3204..03d00d1 100644
--- a/src/version.h.in
+++ b/src/version.h.in
@@ -1,12 +1,19 @@
-#ifndef VERSION_H
-#define VERSION_H
+#ifndef SMOLBOTE_VERSION_H
+#define SMOLBOTE_VERSION_H
// VcsVersion gets defined by the CMakeLists if project-src/.hg exists
#cmakedefine VcsVersion
+#cmakedefine VcsBookmark
#ifdef VcsVersion
+
+#ifdef VcsBookmark
+// Version: 1.2.3 (stable)
+#define SMOLBOTE_VERSION "@VcsVersion@ (@VcsBookmark@)"
+#else
// Version: 1.2.3
#define SMOLBOTE_VERSION "@VcsVersion@"
+#endif
// Describe: 1.2.3-r123-0123456789ab
#define SMOLBOTE_DESCRIBE "@VcsVersion@-r@VcsRevision@-@VcsCommit@"
@@ -18,6 +25,8 @@
#define SMOLBOTE_BRANCH "@VcsBranch@"
#else
+
+// If VcsVersion has not been defined, these values will be used
// Version: 1.2.3
#define SMOLBOTE_VERSION "0.3.0"
@@ -32,4 +41,4 @@
#endif
-#endif //VERSION_H
+#endif // SMOLBOTE_VERSION_H
diff --git a/src/webengine/urlinterceptor.h b/src/webengine/urlinterceptor.h
index af15f99..951eb52 100644
--- a/src/webengine/urlinterceptor.h
+++ b/src/webengine/urlinterceptor.h
@@ -9,8 +9,8 @@
#ifndef URLREQUESTINTERCEPTOR_H
#define URLREQUESTINTERCEPTOR_H
-#include <QWebEngineUrlRequestInterceptor>
#include <QMutex>
+#include <QWebEngineUrlRequestInterceptor>
class UrlRequestInterceptor : public QWebEngineUrlRequestInterceptor
{
diff --git a/src/webengine/webengineprofile.cpp b/src/webengine/webengineprofile.cpp
index 55af9f2..e69de29 100644
--- a/src/webengine/webengineprofile.cpp
+++ b/src/webengine/webengineprofile.cpp
@@ -1,214 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#include "webengineprofile.h"
-#include <QFileInfo>
-#include <QSettings>
-#include <QWebEngineCookieStore>
-#include <QWebEngineSettings>
-
-WebEngineProfile::WebEngineProfile(QObject *parent)
- : QWebEngineProfile(parent)
-{
- m_name = tr("Off-the-record");
-
-#ifdef QT_DEBUG
- qDebug("Creating off-the-record profile");
-#endif
-
- // Off-the-record profiles have no persistent path
-}
-
-WebEngineProfile::WebEngineProfile(const QString &name, QObject *parent)
- : QWebEngineProfile(name, parent)
-{
- m_name = name;
-
-#ifdef QT_DEBUG
- qDebug("Creating profile %s", qUtf8Printable(m_name));
-#endif
-}
-
-WebEngineProfile::~WebEngineProfile() = default;
-
-QString WebEngineProfile::name() const
-{
- return m_name;
-}
-
-QUrl WebEngineProfile::homepage() const
-{
- return m_homepage;
-}
-
-QUrl WebEngineProfile::newtab() const
-{
- return m_newtab;
-}
-
-void WebEngineProfile::loadProfile(QHash<QString, QString> conf, const QString &path)
-{
- m_configPath = path;
-
-#ifdef QT_DEBUG
- qDebug("Reading config for profile '%s': %s", qUtf8Printable(m_name), qUtf8Printable(m_configPath));
-#endif
- QSettings config(m_configPath, QSettings::IniFormat);
-
- m_homepage = config.value("homepage", conf["profile.homepage"]).toUrl();
- m_newtab = config.value("newtab", conf["profile.newtab"]).toUrl();
-
- config.beginGroup("http");
- setHttpUserAgent(config.value("userAgent", httpUserAgent()).toString());
- setHttpAcceptLanguage(config.value("accept-lang", httpAcceptLanguage()).toString());
- {
- QString cacheType = config.value("cacheType").toString();
- if(cacheType == "memory") {
- setHttpCacheType(QWebEngineProfile::MemoryHttpCache);
- } else if(cacheType == "disk") {
- setHttpCacheType(QWebEngineProfile::DiskHttpCache);
- } else if(cacheType == "disabled") {
- setHttpCacheType(QWebEngineProfile::NoCache);
- }
- }
- setHttpCacheMaximumSize(config.value("cacheSize", httpCacheMaximumSize()).toInt());
- config.endGroup(); // http
-
- config.beginGroup("policy");
- {
- QString cookies = config.value("cookies").toString();
- if(cookies == "disabled") {
- setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
- } else if(cookies == "allow") {
- setPersistentCookiesPolicy(QWebEngineProfile::AllowPersistentCookies);
- } else if(cookies == "force") {
- setPersistentCookiesPolicy(QWebEngineProfile::ForcePersistentCookies);
- }
- }
- config.endGroup(); // policy
-
- config.beginGroup("attributes");
- QWebEngineSettings *s = settings();
- s->setAttribute(QWebEngineSettings::AutoLoadImages,
- config.value("autoLoadImages", s->testAttribute(QWebEngineSettings::AutoLoadImages)).toBool());
- s->setAttribute(QWebEngineSettings::JavascriptEnabled,
- config.value("javascriptEnabled", s->testAttribute(QWebEngineSettings::JavascriptEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows,
- config.value("javascriptCanOpenWindows", s->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows)).toBool());
- s->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
- config.value("javascriptCanAccessClipboard", s->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard)).toBool());
- s->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain,
- config.value("linksIncludedInFocusChain", s->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain)).toBool());
- s->setAttribute(QWebEngineSettings::LocalStorageEnabled,
- config.value("localStorageEnabled", s->testAttribute(QWebEngineSettings::LocalStorageEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls,
- config.value("localContentCanAccessRemoteUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls)).toBool());
- s->setAttribute(QWebEngineSettings::XSSAuditingEnabled,
- config.value("xssAuditingEnabled", s->testAttribute(QWebEngineSettings::XSSAuditingEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::SpatialNavigationEnabled,
- config.value("spatialNavigationEnabled", s->testAttribute(QWebEngineSettings::SpatialNavigationEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls,
- config.value("localContentCanAccessFileUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls)).toBool());
- s->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled,
- config.value("hyperlinkAuditingEnabled", s->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled,
- config.value("scrollAnimatorEnabled", s->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::ErrorPageEnabled,
- config.value("errorPageEnabled", s->testAttribute(QWebEngineSettings::ErrorPageEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::PluginsEnabled,
- config.value("pluginsEnabled", s->testAttribute(QWebEngineSettings::PluginsEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
- config.value("fullscreenSupportEnabled", s->testAttribute(QWebEngineSettings::FullScreenSupportEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::ScreenCaptureEnabled,
- config.value("screenCaptureEnabled", s->testAttribute(QWebEngineSettings::ScreenCaptureEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::WebGLEnabled,
- config.value("webglEnabled", s->testAttribute(QWebEngineSettings::WebGLEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled,
- config.value("accelerated2dCanvasEnabled", s->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::AutoLoadIconsForPage,
- config.value("autoLoadIconsForPage", s->testAttribute(QWebEngineSettings::AutoLoadIconsForPage)).toBool());
- s->setAttribute(QWebEngineSettings::TouchIconsEnabled,
- config.value("touchIconsEnabled", s->testAttribute(QWebEngineSettings::TouchIconsEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled,
- config.value("focusOnNavigationEnabled", s->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled)).toBool());
- s->setAttribute(QWebEngineSettings::PrintElementBackgrounds,
- config.value("printElementBackgrounds", s->testAttribute(QWebEngineSettings::PrintElementBackgrounds)).toBool());
- s->setAttribute(QWebEngineSettings::AllowRunningInsecureContent,
- config.value("allowRunningInsecureContent", s->testAttribute(QWebEngineSettings::AllowRunningInsecureContent)).toBool());
- config.endGroup(); // attributes
-}
-
-void WebEngineProfile::saveProfile(const QString &path)
-{
- QSettings config(persistentStoragePath() + "/profile.ini", QSettings::IniFormat);
-
- config.setValue("homepage", homepage().toString());
- config.setValue("newtab", newtab().toString());
-
- config.beginGroup("http");
- config.setValue("userAgent", httpUserAgent());
- config.setValue("accept-lang", httpAcceptLanguage());
- switch(httpCacheType()) {
- case MemoryHttpCache:
- config.setValue("cacheType", "memory");
- break;
- case DiskHttpCache:
- config.setValue("cacheType", "disk");
- break;
- case NoCache:
- config.setValue("cacheType", "disabled");
- break;
- }
- config.setValue("cacheSize", httpCacheMaximumSize());
- config.endGroup(); // http
-
- config.beginGroup("policy");
- switch(persistentCookiesPolicy()) {
- case NoPersistentCookies:
- config.setValue("cookies", "disabled");
- break;
- case AllowPersistentCookies:
- config.setValue("cookies", "allow");
- break;
- case ForcePersistentCookies:
- config.setValue("cookies", "force");
- break;
- }
- config.endGroup(); // policy
-
- QWebEngineSettings *s = settings();
- config.beginGroup("attributes");
- config.setValue("autoLoadImages", s->testAttribute(QWebEngineSettings::AutoLoadImages));
- config.setValue("javascriptEnabled", s->testAttribute(QWebEngineSettings::JavascriptEnabled));
- config.setValue("javascriptCanOpenWindows", s->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows));
- config.setValue("javascriptCanAccessClipboard", s->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard));
- config.setValue("linksIncludedInFocusChain", s->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain));
- config.setValue("localStorageEnabled", s->testAttribute(QWebEngineSettings::LocalStorageEnabled));
- config.setValue("localContentCanAccessRemoteUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls));
- config.setValue("xssAuditingEnabled", s->testAttribute(QWebEngineSettings::XSSAuditingEnabled));
- config.setValue("spatialNavigationEnabled", s->testAttribute(QWebEngineSettings::SpatialNavigationEnabled));
- config.setValue("localContentCanAccessFileUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls));
- config.setValue("hyperlinkAuditingEnabled", s->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled));
- config.setValue("scrollAnimatorEnabled", s->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled));
- config.setValue("errorPageEnabled", s->testAttribute(QWebEngineSettings::ErrorPageEnabled));
- config.setValue("pluginsEnabled", s->testAttribute(QWebEngineSettings::PluginsEnabled));
- config.setValue("fullscreenSupportEnabled", s->testAttribute(QWebEngineSettings::FullScreenSupportEnabled));
- config.setValue("screenCaptureEnabled", s->testAttribute(QWebEngineSettings::ScreenCaptureEnabled));
- config.setValue("webglEnabled", s->testAttribute(QWebEngineSettings::WebGLEnabled));
- config.setValue("accelerated2dCanvasEnabled", s->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled));
- config.setValue("autoLoadIconsForPage", s->testAttribute(QWebEngineSettings::AutoLoadIconsForPage));
- config.setValue("touchIconsEnabled", s->testAttribute(QWebEngineSettings::TouchIconsEnabled));
-#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
- config.setValue("focusOnNavigationEnabled", s->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled));
- config.setValue("printElementBackgrounds", s->testAttribute(QWebEngineSettings::PrintElementBackgrounds));
- config.setValue("allowRunningInsecureContent", s->testAttribute(QWebEngineSettings::AllowRunningInsecureContent));
-#endif
- config.endGroup(); // attributes
-
- config.sync();
-}
diff --git a/src/webengine/webengineprofile.h b/src/webengine/webengineprofile.h
index a38c977..e69de29 100644
--- a/src/webengine/webengineprofile.h
+++ b/src/webengine/webengineprofile.h
@@ -1,39 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#ifndef SMOLBOTE_WEBENGINEPROFILE_H
-#define SMOLBOTE_WEBENGINEPROFILE_H
-
-#include <QUrl>
-#include <QWebEngineProfile>
-
-class WebEngineProfile : public QWebEngineProfile
-{
- Q_OBJECT
-public:
- explicit WebEngineProfile(QObject *parent = nullptr);
- explicit WebEngineProfile(const QString &name, QObject *parent = nullptr);
-
- ~WebEngineProfile() override;
-
- QString name() const;
- QUrl homepage() const;
- QUrl newtab() const;
-
-public slots:
- void loadProfile(QHash<QString, QString> conf, const QString &path);
- void saveProfile(const QString &path = QString());
-
-private:
- QString m_configPath;
- QString m_name;
- QUrl m_homepage = QUrl("about:blank");
- QUrl m_newtab = QUrl("about:blank");
-};
-
-#endif // SMOLBOTE_WEBENGINEPROFILE_H
diff --git a/src/webengine/webprofile.cpp b/src/webengine/webprofile.cpp
new file mode 100644
index 0000000..24b23a0
--- /dev/null
+++ b/src/webengine/webprofile.cpp
@@ -0,0 +1,216 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "webprofile.h"
+#include <QFileInfo>
+#include <QSettings>
+#include <QWebEngineCookieStore>
+#include <QWebEngineSettings>
+
+WebProfile *WebProfile::profile = nullptr;
+
+WebProfile::WebProfile(QObject *parent)
+ : QWebEngineProfile(parent)
+{
+ m_name = tr("Off-the-record");
+
+#ifdef QT_DEBUG
+ qDebug("Creating off-the-record profile");
+#endif
+
+ // Off-the-record profiles have no persistent path
+}
+
+WebProfile::WebProfile(const QString &name, QObject *parent)
+ : QWebEngineProfile(name, parent)
+{
+ m_name = name;
+
+#ifdef QT_DEBUG
+ qDebug("Creating profile %s", qUtf8Printable(m_name));
+#endif
+}
+
+WebProfile::~WebProfile() = default;
+
+QString WebProfile::name() const
+{
+ return m_name;
+}
+
+QUrl WebProfile::homepage() const
+{
+ return m_homepage;
+}
+
+QUrl WebProfile::newtab() const
+{
+ return m_newtab;
+}
+
+void WebProfile::loadProfile(QHash<QString, QString> conf, const QString &path)
+{
+ m_configPath = path;
+
+#ifdef QT_DEBUG
+ qDebug("Reading config for profile '%s': %s", qUtf8Printable(m_name), qUtf8Printable(m_configPath));
+#endif
+ QSettings config(m_configPath, QSettings::IniFormat);
+
+ m_homepage = config.value("homepage", conf["profile.homepage"]).toUrl();
+ m_newtab = config.value("newtab", conf["profile.newtab"]).toUrl();
+
+ config.beginGroup("http");
+ setHttpUserAgent(config.value("userAgent", httpUserAgent()).toString());
+ setHttpAcceptLanguage(config.value("accept-lang", httpAcceptLanguage()).toString());
+ {
+ QString cacheType = config.value("cacheType").toString();
+ if(cacheType == "memory") {
+ setHttpCacheType(QWebEngineProfile::MemoryHttpCache);
+ } else if(cacheType == "disk") {
+ setHttpCacheType(QWebEngineProfile::DiskHttpCache);
+ } else if(cacheType == "disabled") {
+ setHttpCacheType(QWebEngineProfile::NoCache);
+ }
+ }
+ setHttpCacheMaximumSize(config.value("cacheSize", httpCacheMaximumSize()).toInt());
+ config.endGroup(); // http
+
+ config.beginGroup("policy");
+ {
+ QString cookies = config.value("cookies").toString();
+ if(cookies == "disabled") {
+ setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
+ } else if(cookies == "allow") {
+ setPersistentCookiesPolicy(QWebEngineProfile::AllowPersistentCookies);
+ } else if(cookies == "force") {
+ setPersistentCookiesPolicy(QWebEngineProfile::ForcePersistentCookies);
+ }
+ }
+ config.endGroup(); // policy
+
+ config.beginGroup("attributes");
+ QWebEngineSettings *s = settings();
+ s->setAttribute(QWebEngineSettings::AutoLoadImages,
+ config.value("autoLoadImages", s->testAttribute(QWebEngineSettings::AutoLoadImages)).toBool());
+ s->setAttribute(QWebEngineSettings::JavascriptEnabled,
+ config.value("javascriptEnabled", s->testAttribute(QWebEngineSettings::JavascriptEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows,
+ config.value("javascriptCanOpenWindows", s->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows)).toBool());
+ s->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
+ config.value("javascriptCanAccessClipboard", s->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard)).toBool());
+ s->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain,
+ config.value("linksIncludedInFocusChain", s->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain)).toBool());
+ s->setAttribute(QWebEngineSettings::LocalStorageEnabled,
+ config.value("localStorageEnabled", s->testAttribute(QWebEngineSettings::LocalStorageEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls,
+ config.value("localContentCanAccessRemoteUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls)).toBool());
+ s->setAttribute(QWebEngineSettings::XSSAuditingEnabled,
+ config.value("xssAuditingEnabled", s->testAttribute(QWebEngineSettings::XSSAuditingEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::SpatialNavigationEnabled,
+ config.value("spatialNavigationEnabled", s->testAttribute(QWebEngineSettings::SpatialNavigationEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls,
+ config.value("localContentCanAccessFileUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls)).toBool());
+ s->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled,
+ config.value("hyperlinkAuditingEnabled", s->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled,
+ config.value("scrollAnimatorEnabled", s->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::ErrorPageEnabled,
+ config.value("errorPageEnabled", s->testAttribute(QWebEngineSettings::ErrorPageEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::PluginsEnabled,
+ config.value("pluginsEnabled", s->testAttribute(QWebEngineSettings::PluginsEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
+ config.value("fullscreenSupportEnabled", s->testAttribute(QWebEngineSettings::FullScreenSupportEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::ScreenCaptureEnabled,
+ config.value("screenCaptureEnabled", s->testAttribute(QWebEngineSettings::ScreenCaptureEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::WebGLEnabled,
+ config.value("webglEnabled", s->testAttribute(QWebEngineSettings::WebGLEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled,
+ config.value("accelerated2dCanvasEnabled", s->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::AutoLoadIconsForPage,
+ config.value("autoLoadIconsForPage", s->testAttribute(QWebEngineSettings::AutoLoadIconsForPage)).toBool());
+ s->setAttribute(QWebEngineSettings::TouchIconsEnabled,
+ config.value("touchIconsEnabled", s->testAttribute(QWebEngineSettings::TouchIconsEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled,
+ config.value("focusOnNavigationEnabled", s->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled)).toBool());
+ s->setAttribute(QWebEngineSettings::PrintElementBackgrounds,
+ config.value("printElementBackgrounds", s->testAttribute(QWebEngineSettings::PrintElementBackgrounds)).toBool());
+ s->setAttribute(QWebEngineSettings::AllowRunningInsecureContent,
+ config.value("allowRunningInsecureContent", s->testAttribute(QWebEngineSettings::AllowRunningInsecureContent)).toBool());
+ config.endGroup(); // attributes
+}
+
+void WebProfile::saveProfile(const QString &path)
+{
+ QSettings config(persistentStoragePath() + "/profile.ini", QSettings::IniFormat);
+
+ config.setValue("homepage", homepage().toString());
+ config.setValue("newtab", newtab().toString());
+
+ config.beginGroup("http");
+ config.setValue("userAgent", httpUserAgent());
+ config.setValue("accept-lang", httpAcceptLanguage());
+ switch(httpCacheType()) {
+ case MemoryHttpCache:
+ config.setValue("cacheType", "memory");
+ break;
+ case DiskHttpCache:
+ config.setValue("cacheType", "disk");
+ break;
+ case NoCache:
+ config.setValue("cacheType", "disabled");
+ break;
+ }
+ config.setValue("cacheSize", httpCacheMaximumSize());
+ config.endGroup(); // http
+
+ config.beginGroup("policy");
+ switch(persistentCookiesPolicy()) {
+ case NoPersistentCookies:
+ config.setValue("cookies", "disabled");
+ break;
+ case AllowPersistentCookies:
+ config.setValue("cookies", "allow");
+ break;
+ case ForcePersistentCookies:
+ config.setValue("cookies", "force");
+ break;
+ }
+ config.endGroup(); // policy
+
+ QWebEngineSettings *s = settings();
+ config.beginGroup("attributes");
+ config.setValue("autoLoadImages", s->testAttribute(QWebEngineSettings::AutoLoadImages));
+ config.setValue("javascriptEnabled", s->testAttribute(QWebEngineSettings::JavascriptEnabled));
+ config.setValue("javascriptCanOpenWindows", s->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows));
+ config.setValue("javascriptCanAccessClipboard", s->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard));
+ config.setValue("linksIncludedInFocusChain", s->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain));
+ config.setValue("localStorageEnabled", s->testAttribute(QWebEngineSettings::LocalStorageEnabled));
+ config.setValue("localContentCanAccessRemoteUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls));
+ config.setValue("xssAuditingEnabled", s->testAttribute(QWebEngineSettings::XSSAuditingEnabled));
+ config.setValue("spatialNavigationEnabled", s->testAttribute(QWebEngineSettings::SpatialNavigationEnabled));
+ config.setValue("localContentCanAccessFileUrls", s->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls));
+ config.setValue("hyperlinkAuditingEnabled", s->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled));
+ config.setValue("scrollAnimatorEnabled", s->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled));
+ config.setValue("errorPageEnabled", s->testAttribute(QWebEngineSettings::ErrorPageEnabled));
+ config.setValue("pluginsEnabled", s->testAttribute(QWebEngineSettings::PluginsEnabled));
+ config.setValue("fullscreenSupportEnabled", s->testAttribute(QWebEngineSettings::FullScreenSupportEnabled));
+ config.setValue("screenCaptureEnabled", s->testAttribute(QWebEngineSettings::ScreenCaptureEnabled));
+ config.setValue("webglEnabled", s->testAttribute(QWebEngineSettings::WebGLEnabled));
+ config.setValue("accelerated2dCanvasEnabled", s->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled));
+ config.setValue("autoLoadIconsForPage", s->testAttribute(QWebEngineSettings::AutoLoadIconsForPage));
+ config.setValue("touchIconsEnabled", s->testAttribute(QWebEngineSettings::TouchIconsEnabled));
+#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
+ config.setValue("focusOnNavigationEnabled", s->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled));
+ config.setValue("printElementBackgrounds", s->testAttribute(QWebEngineSettings::PrintElementBackgrounds));
+ config.setValue("allowRunningInsecureContent", s->testAttribute(QWebEngineSettings::AllowRunningInsecureContent));
+#endif
+ config.endGroup(); // attributes
+
+ config.sync();
+}
diff --git a/src/webengine/webprofile.h b/src/webengine/webprofile.h
new file mode 100644
index 0000000..41d1aec
--- /dev/null
+++ b/src/webengine/webprofile.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of smolbote. It's copyrighted by the contributors recorded
+ * in the version control history of the file, available from its original
+ * location: https://neueland.iserlohn-fortress.net/smolbote.hg
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_WEBENGINEPROFILE_H
+#define SMOLBOTE_WEBENGINEPROFILE_H
+
+#include <QHash>
+#include <QUrl>
+#include <QWebEngineProfile>
+
+class WebProfile : public QWebEngineProfile
+{
+ Q_OBJECT
+public:
+ explicit WebProfile(QObject *parent = nullptr);
+ explicit WebProfile(const QString &name, QObject *parent = nullptr);
+
+ ~WebProfile() override;
+
+ static void setDefaultProfile(WebProfile *profile)
+ {
+ Q_CHECK_PTR(profile);
+ WebProfile::profile = profile;
+ }
+ static WebProfile *defaultProfile()
+ {
+ Q_CHECK_PTR(WebProfile::profile);
+ return WebProfile::profile;
+ }
+
+ QString name() const;
+ QUrl homepage() const;
+ QUrl newtab() const;
+
+public slots:
+ void loadProfile(QHash<QString, QString> conf, const QString &path);
+ void saveProfile(const QString &path = QString());
+
+private:
+ static WebProfile *profile;
+
+ QString m_configPath;
+ QString m_name;
+ QUrl m_homepage = QUrl("about:blank");
+ QUrl m_newtab = QUrl("about:blank");
+};
+
+#endif // SMOLBOTE_WEBENGINEPROFILE_H
diff --git a/src/webengine/webview.cpp b/src/webengine/webview.cpp
index 7734aa0..d145d2b 100644
--- a/src/webengine/webview.cpp
+++ b/src/webengine/webview.cpp
@@ -7,19 +7,23 @@
*/
#include "webview.h"
-#include "mainwindow/mainwindow.h"
-#include "mainwindow/widgets/tabbar.h"
+#include "webpage.h"
+#include "webprofile.h"
#include "widgets/pagemenu.h"
#include "widgets/pagetoolsmenu.h"
#include <QDialog>
#include <QStatusBar>
#include <QVBoxLayout>
+#include "mainwindow/window.h"
-WebView::WebView(MainWindow *parentMainWindow, QWidget *parent)
+WebView::WebView(WebProfile *profile, QWidget *parent)
: QWebEngineView(parent)
{
- Q_CHECK_PTR(parentMainWindow);
- m_parent = parentMainWindow;
+ Q_CHECK_PTR(profile);
+ m_profile = profile;
+ setPage(new WebPage(profile, this));
+
+ m_parentWindow = qobject_cast<Window *>(parent);
// load status and progress
connect(this, &QWebEngineView::loadStarted, this, [this]() {
@@ -72,26 +76,32 @@ int WebView::loadProgress() const
WebView *WebView::createWindow(QWebEnginePage::WebWindowType type)
{
- WebView *view = new WebView(m_parent);
+ if(m_parentWindow == nullptr) {
+ qDebug("parent window not found!");
+ return nullptr;
+ }
+
+ // parent Window has been found
+ WebView *view = new WebView(m_profile, m_parentWindow);
switch(type) {
case QWebEnginePage::WebBrowserWindow:
// a complete web browser window
- m_parent->newWindow()->tabBar->addTab(view);
+ m_parentWindow->addTab(view);
break;
case QWebEnginePage::WebBrowserTab:
// a web browser tab
- m_parent->tabBar->setCurrentIndex(m_parent->tabBar->addTab(view));
+ m_parentWindow->swapToTab(m_parentWindow->addTab(view));
break;
case QWebEnginePage::WebDialog:
// a window without decorations
- m_parent->newWindow()->tabBar->addTab(view);
+ m_parentWindow->addTab(view);
break;
case QWebEnginePage::WebBrowserBackgroundTab:
// a web browser tab, but don't swap to it
- m_parent->tabBar->addTab(view);
+ m_parentWindow->addTab(view);
break;
}
@@ -100,26 +110,17 @@ WebView *WebView::createWindow(QWebEnginePage::WebWindowType type)
void WebView::handleLinkHovered(const QString &url)
{
- if(isVisible()) {
- m_parent->statusBar()->showMessage(url, 3000);
- }
+ // TODO: tooltip
+ qDebug("%s", qUtf8Printable(url));
}
void WebView::triggerViewAction(WebView::ViewAction action)
{
switch(action) {
+ case GoHome:
+ load(m_profile->homepage());
case BookmarkPage:
emit newBookmark(this->title(), this->url());
break;
}
}
-
-WebView *createWebView(const QUrl &url, WebEngineProfile *profile, MainWindow *parent)
-{
- auto *view = new WebView(parent);
- auto *page = new WebPage(profile);
- view->setPage(page);
- page->load(url);
-
- return view;
-}
diff --git a/src/webengine/webview.h b/src/webengine/webview.h
index 233565e..a27a61f 100644
--- a/src/webengine/webview.h
+++ b/src/webengine/webview.h
@@ -13,17 +13,18 @@
#include <QWebEngineView>
class QMenu;
-class MainWindow;
-class WebEngineProfile;
+class WebProfile;
+class Window;
class WebView : public QWebEngineView
{
Q_OBJECT
public:
enum ViewAction {
+ GoHome,
BookmarkPage
};
- explicit WebView(MainWindow *parentMainWindow, QWidget *parent = nullptr);
+ explicit WebView(WebProfile *profile = nullptr, QWidget *parent = nullptr);
~WebView() override;
QMenu *pageMenu();
@@ -53,7 +54,9 @@ private slots:
void handleLinkHovered(const QString &url);
private:
- MainWindow *m_parent = nullptr;
+ Window *m_parentWindow = nullptr;
+ WebProfile *m_profile = nullptr;
+
QMenu *m_pageMenu = nullptr;
QMenu *m_toolsMenu = nullptr;
@@ -61,6 +64,4 @@ private:
int m_loadProgress;
};
-WebView *createWebView(const QUrl &url, WebEngineProfile *profile, MainWindow *parent);
-
#endif // SMOLBOTE_WEBVIEW_H
diff --git a/src/webengine/widgets/pagetoolsmenu.cpp b/src/webengine/widgets/pagetoolsmenu.cpp
index 381c6f4..2a227ea 100644
--- a/src/webengine/widgets/pagetoolsmenu.cpp
+++ b/src/webengine/widgets/pagetoolsmenu.cpp
@@ -52,7 +52,7 @@ QDialog *PageToolsMenu::createDevToolsDialog(QWebEnginePage *page)
auto *devPage = new QWebEnginePage(view);
view->setPage(devPage);
-// page->setDevToolsPage(devPage);
+ // page->setDevToolsPage(devPage);
auto *l = new QVBoxLayout(popup);
l->setContentsMargins(0, 0, 0, 0);
diff --git a/src/widgets/mainwindowmenubar.cpp b/src/widgets/mainwindowmenubar.cpp
deleted file mode 100644
index 44a6eba..0000000
--- a/src/widgets/mainwindowmenubar.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#include "mainwindowmenubar.h"
-#include "browser.h"
-#include "downloads/downloadswidget.h"
-#include "mainwindow/mainwindow.h"
-#include <QInputDialog>
-#include <QShortcut>
-#include "configuration/configuration.h"
-
-MainWindowMenuBar::MainWindowMenuBar(std::shared_ptr<Configuration> config, MainWindow *parent)
- : QMenuBar(parent)
-{
- Q_ASSERT(config);
- Q_CHECK_PTR(parent);
-
- setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
-
- auto *browser = dynamic_cast<Browser *>(QApplication::instance());
-
- // Browser menu
- QMenu *browserMenu = new QMenu(qApp->applicationName(), this);
- addMenu(browserMenu);
-
- QAction *newWindowAction = browserMenu->addAction(tr("New Window"));
- connect(newWindowAction, &QAction::triggered, parent, [parent]() {
- parent->newWindow();
- });
- newWindowAction->setShortcut(QKeySequence(config->value<std::string>("browser.shortcuts.newWindow").value().c_str()));
-
- browserMenu->addAction(parent->findChild<QAction*>("newTab_action"));
-
- browserMenu->addSeparator();
- //browserMenu->addAction(tr("Settings"), parent, &MainWindow::showSettingsDialog);
- browserMenu->addAction(tr("About"), parent, &MainWindow::about, QKeySequence(config->value<std::string>("browser.shortcuts.about").value().c_str()));
- browserMenu->addAction(tr("About Qt"), qApp, &QApplication::aboutQt);
- browserMenu->addSeparator();
-
- QAction *quitAction = browserMenu->addAction(tr("Quit"), qApp, &QApplication::quit);
- quitAction->setShortcut(QKeySequence(config->value<std::string>("browser.shortcuts.quit").value().c_str()));
-
- // Tools menu
- QMenu *toolsMenu = new QMenu(tr("Tools"), this);
- addMenu(toolsMenu);
-
- m_downloadsAction = toolsMenu->addAction(tr("Downloads"));
- m_downloadsAction->setParent(parent);
- m_downloadsAction->setShortcut(QKeySequence(config->value<std::string>("downloads.shortcut").value().c_str()));
- connect(m_downloadsAction, &QAction::triggered, [parent]() {
- parent->m_downloadsWidget->show();
- });
-
- m_bookmarksAction = toolsMenu->addAction(tr("Bookmarks"));
- m_bookmarksAction->setParent(parent);
- m_bookmarksAction->setShortcut(QKeySequence(config->value<std::string>("bookmarks.shortcut").value().c_str()));
-
- //toolsMenu->addAction(tr("Filter"), browser->blocklists(), SLOT(show()), QKeySequence::fromString(browser->settings()->value("blocker.shortcut").toString()));
-
- // Profile menu
- QMenu *profileMenu = addMenu(tr("Profile"));
- m_profileAction = profileMenu->addAction(tr("Current profile"));
- m_profileAction->setEnabled(false);
-
- QMenu *loadMenu = profileMenu->addMenu(tr("Load"));
-
- for(const QString &name : browser->profiles()) {
- QAction *profileAction = loadMenu->addAction(browser->profile(name)->name());
- connect(profileAction, &QAction::triggered, this, [browser, parent, name] {
- parent->setProfile(browser->profile(name));
- });
- }
-}
-
-QAction *MainWindowMenuBar::bookmarksAction()
-{
- Q_CHECK_PTR(m_bookmarksAction);
- return m_bookmarksAction;
-}
-
-QAction *MainWindowMenuBar::profileAction() const
-{
- Q_CHECK_PTR(m_profileAction);
- return m_profileAction;
-}
-
diff --git a/src/widgets/mainwindowmenubar.h b/src/widgets/mainwindowmenubar.h
deleted file mode 100644
index 11c8beb..0000000
--- a/src/widgets/mainwindowmenubar.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This file is part of smolbote. It's copyrighted by the contributors recorded
- * in the version control history of the file, available from its original
- * location: https://neueland.iserlohn-fortress.net/smolbote.hg
- *
- * SPDX-License-Identifier: GPL-3.0
- */
-
-#ifndef MAINWINDOWMENUBAR_H
-#define MAINWINDOWMENUBAR_H
-
-#include <QMenuBar>
-#include <memory>
-
-class MainWindow;
-class Configuration;
-class MainWindowMenuBar : public QMenuBar
-{
- Q_OBJECT
-public:
- explicit MainWindowMenuBar(std::shared_ptr<Configuration> config, MainWindow *parent = nullptr);
-
- QAction *bookmarksAction();
- QAction *profileAction() const;
-
-private:
- QAction *m_bookmarksAction;
- QAction *m_downloadsAction;
- QAction *m_profileAction;
-};
-
-#endif // MAINWINDOWMENUBAR_H