aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/web/profilemanager.cpp20
-rw-r--r--lib/web/profilemanager.h1
-rw-r--r--linux/makepkg/PKGBUILD2
-rw-r--r--src/browser.cpp42
-rw-r--r--src/browser.h8
-rw-r--r--src/mainwindow/mainwindow.cpp130
-rw-r--r--src/mainwindow/mainwindow.h17
-rw-r--r--src/mainwindow/mainwindow.ui202
-rw-r--r--src/mainwindow/menubar.cpp239
-rw-r--r--src/mainwindow/menubar.h28
-rw-r--r--src/mainwindow/widgets/menusearch.cpp17
-rw-r--r--src/mainwindow/widgets/menusearch.h20
-rw-r--r--src/mainwindow/widgets/navigationbar.cpp4
-rw-r--r--src/meson.build6
-rw-r--r--src/session/session.cpp4
-rw-r--r--src/subwindow/subwindow.cpp38
-rw-r--r--src/subwindow/subwindow.h3
-rw-r--r--src/subwindow/tabwidget.cpp78
-rw-r--r--src/subwindow/tabwidget.h5
19 files changed, 431 insertions, 433 deletions
diff --git a/lib/web/profilemanager.cpp b/lib/web/profilemanager.cpp
index 14795cd..6e6281b 100644
--- a/lib/web/profilemanager.cpp
+++ b/lib/web/profilemanager.cpp
@@ -10,6 +10,8 @@
#include "webprofile.h"
#include <QFileInfo>
#include <QWebEngineSettings>
+#include <QWidgetAction>
+#include <QRadioButton>
ProfileManager::ProfileManager(const QHash<QString, QString> &profileSection, QObject *parent)
: QObject(parent)
@@ -111,6 +113,24 @@ void ProfileManager::deleteProfile(const QString &id)
}
}
+void ProfileManager::profilePickerMenu(QMenu *menu, WebProfile *current, std::function<void(WebProfile *)> callback) const
+{
+ for(const auto &profileData : m_profiles) {
+ WebProfile *profile = profileData.second->profile;
+
+ auto *profileButton = new QRadioButton(profile->name(), menu);
+ profileButton->setChecked(profile == current);
+
+ auto *action = new QWidgetAction(menu);
+ action->setDefaultWidget(profileButton);
+ connect(profileButton, &QRadioButton::clicked, profile, [profile, callback]() {
+ callback(profile);
+ });
+
+ menu->addAction(action);
+ }
+}
+
QMenu *ProfileManager::createProfileMenu(std::function<void(WebProfile *)> callback, QWidget *parent) const
{
auto *menu = new QMenu(parent);
diff --git a/lib/web/profilemanager.h b/lib/web/profilemanager.h
index f5e33b9..e0040a3 100644
--- a/lib/web/profilemanager.h
+++ b/lib/web/profilemanager.h
@@ -31,6 +31,7 @@ public:
WebProfile *loadProfile(const QString &path);
void deleteProfile(const QString &id);
+ void profilePickerMenu(QMenu *menu, WebProfile *current, std::function<void(WebProfile *)> callback) const;
QMenu *createProfileMenu(std::function<void(WebProfile *)> callback, QWidget *parent = nullptr) const;
const QStringList idList() const;
diff --git a/linux/makepkg/PKGBUILD b/linux/makepkg/PKGBUILD
index cd5e8db..52537d1 100644
--- a/linux/makepkg/PKGBUILD
+++ b/linux/makepkg/PKGBUILD
@@ -57,7 +57,7 @@ build() {
# b_pie: Build executables as position independent
# b_lto: Use link time optimization
meson --buildtype=plain --prefix=/usr/local --auto-features=disabled \
- -Db_pie=enabled -Db_lto=enabled -Dcpp_link_args="-fuse-ld=gold" \
+ -Db_pie=true -Db_lto=true -Dcpp_link_args="-fuse-ld=gold" \
-DPlasma=enabled -Dmanpage=enabled \
$srcdir/build
diff --git a/src/browser.cpp b/src/browser.cpp
index 18ccc92..0422a4e 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -17,7 +17,6 @@
#include "mainwindow/mainwindow.h"
#include "profilemanager.h"
#include "subwindow/subwindow.h"
-#include "ui_mainwindow.h"
#include "util.h"
#include "webengine/filter.h"
#include "webengine/urlinterceptor.h"
@@ -34,6 +33,7 @@
#include <QVersionNumber>
#include <plugininterface.h>
#include <version.h>
+#include "mainwindow/menubar.h"
Browser::Browser(int &argc, char *argv[], bool allowSecondary)
: SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion)
@@ -195,38 +195,21 @@ void Browser::setup(QVector<QPluginLoader *> plugins)
timer->start(5 * 60 * 1000);
}
+void Browser::showWidget(QWidget *widget, MainWindow *where) const
+{
+ bool wasVisible = widget->isVisible();
+ for(MainWindow *w : qAsConst(m_windows))
+ w->removeDockWidget(widget);
+
+ if(!wasVisible)
+ where->addDockWidget(Qt::RightDockWidgetArea, widget);
+}
+
MainWindow *Browser::createWindow()
{
// the window will delete itself when it closes, so we don't need to delete it
auto *window = new MainWindow(m_config);
connect(window->addressBar, &AddressBar::complete, m_bookmarks.get(), &BookmarksWidget::search);
- connect(window, &MainWindow::createBookmark, m_bookmarks.get(), &BookmarksWidget::addBookmark);
-
- m_config->setShortcut(window->ui->actionBookmarks, "bookmarks.shortcut");
- connect(window->ui->actionBookmarks, &QAction::triggered, window, [this, window]() {
- bool wasVisible = m_bookmarks->isVisible();
- for(MainWindow *w : qAsConst(m_windows)) {
- w->removeDockWidget(m_bookmarks.get());
- }
- if(!wasVisible) {
- window->addDockWidget(Qt::RightDockWidgetArea, m_bookmarks.get());
- }
- });
-
- m_config->setShortcut(window->ui->actionDownloads, "downloads.shortcut");
- connect(window->ui->actionDownloads, &QAction::triggered, window, [this, window]() {
- bool wasVisible = m_downloads->isVisible();
- for(MainWindow *w : qAsConst(m_windows)) {
- w->removeDockWidget(m_downloads.get());
- }
- if(!wasVisible) {
- window->addDockWidget(Qt::RightDockWidgetArea, m_downloads.get());
- }
- });
-
- connect(window->ui->actionAddPlugin, &QAction::triggered, this, [this]() {
- this->addPlugin(QFileDialog::getOpenFileName(nullptr, tr("Add Plugin"), QDir::homePath(), tr("Plugins (*.so)")));
- });
for(auto *info : m_plugins) {
addPluginTo(info, window);
@@ -243,7 +226,8 @@ MainWindow *Browser::createWindow()
void Browser::addPluginTo(PluginInfo *info, MainWindow *window)
{
QPluginLoader *loader = info->loader;
- auto *pluginMenu = window->ui->menuTools->addMenu(loader->metaData().value("MetaData").toObject().value("name").toString());
+ auto *pluginMenu = new QMenu(loader->metaData().value("MetaData").toObject().value("name").toString());
+ window->m_menuBar->insertPlugin(pluginMenu);
info->menus.append(pluginMenu);
auto *aboutAction = pluginMenu->addAction(tr("About"));
diff --git a/src/browser.h b/src/browser.h
index f5c63f8..53ee521 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -58,7 +58,15 @@ public:
return qAsConst(m_windows);
}
+ BookmarksWidget *bookmarks() const {
+ return m_bookmarks.get();
+ }
+ DownloadsWidget *downloads() const {
+ return m_downloads.get();
+ }
+
public slots:
+ void showWidget(QWidget *widget, MainWindow *where) const;
MainWindow *createWindow();
private:
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp
index 1544e79..ea024c5 100644
--- a/src/mainwindow/mainwindow.cpp
+++ b/src/mainwindow/mainwindow.cpp
@@ -11,11 +11,11 @@
#include "browser.h"
#include "config.h"
#include "configuration.h"
+#include "menubar.h"
#include "profilemanager.h"
#include "session/session.h"
#include "session/sessiondialog.h"
#include "subwindow/subwindow.h"
-#include "ui_mainwindow.h"
#include "webengine/webview.h"
#include "webprofile.h"
#include "widgets/dockwidget.h"
@@ -31,9 +31,6 @@
#include <QMdiSubWindow>
#include <QMenuBar>
#include <QMessageBox>
-#include <QPrintDialog>
-#include <QPrinter>
-#include <QPrinterInfo>
#include <QShortcut>
#include <QStatusBar>
#include <QToolBar>
@@ -71,12 +68,13 @@ inline QDialog *createDevToolsDialog(QWebEnginePage *page)
MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *parent)
: QMainWindow(parent)
- , ui(new Ui::MainWindow)
+ , configuration(config.get())
, mdiArea(new QMdiArea(this))
{
Q_ASSERT(config);
- ui->setupUi(this);
+ m_menuBar = new MenuBar(config.get(), this);
+ this->setMenuBar(m_menuBar);
#ifdef CONFIG_PLASMA_BLUR
setAttribute(Qt::WA_TranslucentBackground, true);
@@ -91,98 +89,6 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
}
show();
- // connect smolbote menu
- {
- connect(ui->actionNewSubwindow, &QAction::triggered, this, [this, &config]() {
- auto *profile = WebProfile::defaultProfile();
- auto *window = createSubWindow(config.get(), profile);
- window->addTab(profile->newtab(), profile);
- });
- config->setShortcut(ui->actionNewSubwindow, "mainwindow.shortcuts.newGroup");
-
- connect(ui->actionNewWindow, &QAction::triggered, this, []() {
- auto *browser = qobject_cast<Browser *>(qApp);
- if(browser)
- browser->createWindow();
- });
- config->setShortcut(ui->actionNewWindow, "mainwindow.shortcuts.newWindow");
-
- connect(ui->actionAbout, &QAction::triggered, qobject_cast<Browser *>(qApp), &Browser::about);
- config->setShortcut(ui->actionAbout, "mainwindow.shortcuts.about");
-
- connect(ui->actionAboutQt, &QAction::triggered, qApp, &QApplication::aboutQt);
-
- connect(ui->actionQuit, &QAction::triggered, qApp, &QApplication::quit);
- config->setShortcut(ui->actionQuit, "mainwindow.shortcuts.quit");
- }
-
- // connect session menu
- {
- const QString sessionPath = config->value<QString>("browser.session.path").value();
- connect(ui->actionSaveSession, &QAction::triggered, this, [this, sessionPath]() {
- const QString filename = QFileDialog::getSaveFileName(this, tr("Save Session"), sessionPath, tr("JSON (*.json)"));
- QFile output(filename);
- if(output.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
- auto *browser = qobject_cast<Browser *>(qApp);
- auto data = Session::_session(browser->windows());
- output.write(QJsonDocument(data).toJson());
- output.close();
- }
- });
-
- connect(ui->actionLoadSession, &QAction::triggered, this, [this]() {
- auto *sessionDialog = new SessionDialog(this);
- sessionDialog->exec();
- });
- }
-
- // connect window menu
- {
- connect(ui->actionTileSubwindows, &QAction::triggered, mdiArea, &QMdiArea::tileSubWindows);
- config->setShortcut(ui->actionTileSubwindows, "mainwindow.shortcuts.tileWindows");
-
- connect(ui->actionCascadeSubwindows, &QAction::triggered, mdiArea, &QMdiArea::cascadeSubWindows);
- config->setShortcut(ui->actionCascadeSubwindows, "mainwindow.shortcuts.cascadeWindows");
- }
-
- // connect page menu
- {
- connect(ui->actionBookmarkPage, &QAction::triggered, this, [this]() {
- if(currentView != nullptr)
- emit createBookmark(currentView->title(), currentView->url().toString());
- });
- connect(ui->actionSavePage, &QAction::triggered, this, [this]() {
- if(currentView != nullptr)
- currentView->triggerPageAction(QWebEnginePage::SavePage);
- });
- connect(ui->actionPrintPage, &QAction::triggered, this, [this]() {
- if(currentView != nullptr) {
- auto *printer = new QPrinter(QPrinterInfo::defaultPrinter());
- QPrintDialog dlg(printer, this);
- if(dlg.exec() == QDialog::Accepted) {
- currentView->page()->print(printer, [printer](bool success) {
- Q_UNUSED(success);
- delete printer;
- });
- }
- }
- });
- connect(ui->actionPrintPageToPdf, &QAction::triggered, this, [this]() {
- if(currentView != nullptr) {
- const QString path = QFileDialog::getSaveFileName(this, tr("Print to PDF"), QDir::homePath(), tr("PDF files (*.pdf)"));
- currentView->page()->printToPdf(path);
- }
- });
-
- connect(ui->actionDeveloperTools, &QAction::triggered, this, [this]() {
- if(currentView != nullptr)
- createDevToolsDialog(currentView->page())->show();
- });
-
- pageLoadProfileMenu = ui->menuPage->addMenu(tr("Load Profile"));
- connect(pageLoadProfileMenu, &QMenu::aboutToShow, this, &MainWindow::updatePageLoadProfileMenu);
- }
-
// current subwindow shortcut
{
QAction *subwindowMenuAction = new QAction(this);
@@ -221,16 +127,13 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
disconnect(viewChangedConnection);
disconnect(searchBoxConnection);
disconnect(statusBarConnection);
- ui->actionCurrentSubwindow->setMenu(nullptr);
auto *w = qobject_cast<SubWindow *>(window);
if(w == nullptr) {
// no current subwindow, clear everything
setView(nullptr);
- ui->actionCurrentSubwindow->setMenu(nullptr);
} else {
setView(w->currentView());
- ui->actionCurrentSubwindow->setMenu(w->systemMenu());
viewChangedConnection = connect(w, &SubWindow::currentViewChanged, this, &MainWindow::setView);
statusBarConnection = connect(w, &SubWindow::showStatusMessage, statusBar(), &QStatusBar::showMessage);
}
@@ -340,7 +243,7 @@ SubWindow *MainWindow::currentSubWindow() const
return qobject_cast<SubWindow *>(mdiArea->currentSubWindow());
}
-SubWindow *MainWindow::createSubWindow(const Configuration *config, WebProfile *profile)
+SubWindow *MainWindow::createSubWindow(WebProfile *profile, bool openProfileNewtab)
{
bool shouldMaximize = true;
// if there is a current window, use its maximize state
@@ -348,7 +251,8 @@ SubWindow *MainWindow::createSubWindow(const Configuration *config, WebProfile *
shouldMaximize = currentWindow->isMaximized();
}
- auto *w = new SubWindow(config, this);
+ auto *w = new SubWindow(configuration, this);
+
w->setProfile(profile);
mdiArea->addSubWindow(w);
if(shouldMaximize)
@@ -357,6 +261,10 @@ SubWindow *MainWindow::createSubWindow(const Configuration *config, WebProfile *
w->show();
w->setFocus();
+
+ if(openProfileNewtab)
+ w->addTab(w->profile()->newtab());
+
return w;
}
@@ -384,22 +292,6 @@ void MainWindow::setView(WebView *view)
searchBox->setView(view);
}
-void MainWindow::updatePageLoadProfileMenu()
-{
- Q_CHECK_PTR(pageLoadProfileMenu);
- pageLoadProfileMenu->clear();
-
- if(currentView == nullptr)
- return;
-
- auto *profileManager = dynamic_cast<Browser *>(qApp)->getProfileManager();
- pageLoadProfileMenu->addActions(profileManager->createProfileMenu([this](WebProfile *profile) {
- this->currentView->setProfile(profile);
- },
- this)
- ->actions());
-}
-
void MainWindow::closeEvent(QCloseEvent *event)
{
if(mdiArea->subWindowList().count() > 1) {
diff --git a/src/mainwindow/mainwindow.h b/src/mainwindow/mainwindow.h
index de77540..44ee633 100644
--- a/src/mainwindow/mainwindow.h
+++ b/src/mainwindow/mainwindow.h
@@ -22,15 +22,11 @@ class SearchForm;
class WebView;
class NavigationBar;
class WebProfile;
-
-namespace Ui
-{
-class MainWindow;
-}
-
+class MenuBar;
class MainWindow : public QMainWindow
{
friend class Browser;
+ friend class MenuBar;
Q_OBJECT
@@ -49,22 +45,19 @@ public:
const QVector<SubWindow *> subWindows() const;
SubWindow *currentSubWindow() const;
-signals:
- void createBookmark(const QString &title, const QString &url);
-
public slots:
void createTab(const QUrl &url);
- SubWindow *createSubWindow(const Configuration *config, WebProfile *profile);
+ SubWindow *createSubWindow(WebProfile *profile = nullptr, bool openProfileNewtab = false);
private slots:
void setView(WebView *view);
- void updatePageLoadProfileMenu();
protected:
void closeEvent(QCloseEvent *event) override;
private:
- Ui::MainWindow *ui;
+ const Configuration *configuration = nullptr;
+ MenuBar *m_menuBar = nullptr;
QMenu *toolsMenu = nullptr;
QMenu *pageLoadProfileMenu = nullptr;
diff --git a/src/mainwindow/mainwindow.ui b/src/mainwindow/mainwindow.ui
deleted file mode 100644
index 19cecbb..0000000
--- a/src/mainwindow/mainwindow.ui
+++ /dev/null
@@ -1,202 +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>800</width>
- <height>600</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>MainWindow</string>
- </property>
- <widget class="QWidget" name="centralwidget"/>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>800</width>
- <height>30</height>
- </rect>
- </property>
- <widget class="QMenu" name="menusmolbote">
- <property name="title">
- <string>s&amp;molbote</string>
- </property>
- <addaction name="actionNewSubwindow"/>
- <addaction name="actionNewWindow"/>
- <addaction name="separator"/>
- <addaction name="actionAbout"/>
- <addaction name="actionAboutQt"/>
- <addaction name="separator"/>
- <addaction name="actionQuit"/>
- </widget>
- <widget class="QMenu" name="menuSession">
- <property name="title">
- <string>Sessio&amp;n</string>
- </property>
- <addaction name="actionSaveSession"/>
- <addaction name="actionLoadSession"/>
- </widget>
- <widget class="QMenu" name="menuSubWindow">
- <property name="title">
- <string>S&amp;ubwindow</string>
- </property>
- <addaction name="actionTileSubwindows"/>
- <addaction name="actionCascadeSubwindows"/>
- <addaction name="separator"/>
- <addaction name="actionCurrentSubwindow"/>
- </widget>
- <widget class="QMenu" name="menuTools">
- <property name="title">
- <string>Too&amp;ls</string>
- </property>
- <addaction name="actionBookmarks"/>
- <addaction name="actionDownloads"/>
- <addaction name="separator"/>
- <addaction name="actionAddPlugin"/>
- <addaction name="separator"/>
- </widget>
- <widget class="QMenu" name="menuPage">
- <property name="title">
- <string>Pa&amp;ge</string>
- </property>
- <addaction name="actionBookmarkPage"/>
- <addaction name="actionSavePage"/>
- <addaction name="actionPrintPage"/>
- <addaction name="actionPrintPageToPdf"/>
- <addaction name="separator"/>
- <addaction name="actionDeveloperTools"/>
- </widget>
- <addaction name="menusmolbote"/>
- <addaction name="menuSession"/>
- <addaction name="menuSubWindow"/>
- <addaction name="menuPage"/>
- <addaction name="menuTools"/>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- <action name="actionNewSubwindow">
- <property name="text">
- <string>&amp;New Subwindow</string>
- </property>
- </action>
- <action name="actionNewWindow">
- <property name="icon">
- <iconset theme="window-new"/>
- </property>
- <property name="text">
- <string>New &amp;Window</string>
- </property>
- </action>
- <action name="actionAbout">
- <property name="icon">
- <iconset theme="help-about"/>
- </property>
- <property name="text">
- <string>&amp;About</string>
- </property>
- </action>
- <action name="actionAboutQt">
- <property name="text">
- <string>A&amp;bout Qt</string>
- </property>
- </action>
- <action name="actionQuit">
- <property name="icon">
- <iconset theme="application-exit"/>
- </property>
- <property name="text">
- <string>&amp;Quit</string>
- </property>
- </action>
- <action name="actionSaveSession">
- <property name="text">
- <string>&amp;Save Session</string>
- </property>
- </action>
- <action name="actionLoadSession">
- <property name="text">
- <string>&amp;Load Session</string>
- </property>
- </action>
- <action name="actionTileSubwindows">
- <property name="text">
- <string>&amp;Tile Subwindows</string>
- </property>
- </action>
- <action name="actionCascadeSubwindows">
- <property name="text">
- <string>&amp;Cascade Subwindows</string>
- </property>
- </action>
- <action name="actionCurrentSubwindow">
- <property name="text">
- <string>Current &amp;Subwindow</string>
- </property>
- </action>
- <action name="actionBookmarkPage">
- <property name="text">
- <string>&amp;Create Bookmark</string>
- </property>
- </action>
- <action name="actionSavePage">
- <property name="icon">
- <iconset theme="document-save"/>
- </property>
- <property name="text">
- <string>&amp;Save Page</string>
- </property>
- </action>
- <action name="actionPrintPage">
- <property name="icon">
- <iconset theme="document-print"/>
- </property>
- <property name="text">
- <string>&amp;Print Page</string>
- </property>
- </action>
- <action name="actionPrintPageToPdf">
- <property name="icon">
- <iconset theme="document-print"/>
- </property>
- <property name="text">
- <string>P&amp;rint to PDF</string>
- </property>
- </action>
- <action name="actionDeveloperTools">
- <property name="text">
- <string>&amp;Developer Tools</string>
- </property>
- </action>
- <action name="actionBookmarks">
- <property name="icon">
- <iconset theme="bookmarks"/>
- </property>
- <property name="text">
- <string>&amp;Bookmarks</string>
- </property>
- </action>
- <action name="actionDownloads">
- <property name="icon">
- <iconset theme="download"/>
- </property>
- <property name="text">
- <string>&amp;Downloads</string>
- </property>
- </action>
- <action name="actionAddPlugin">
- <property name="icon">
- <iconset theme="plugins"/>
- </property>
- <property name="text">
- <string>&amp;Add Plugin</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/mainwindow/menubar.cpp b/src/mainwindow/menubar.cpp
new file mode 100644
index 0000000..0429ffd
--- /dev/null
+++ b/src/mainwindow/menubar.cpp
@@ -0,0 +1,239 @@
+/*
+ * 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/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "menubar.h"
+#include "bookmarkswidget.h"
+#include "browser.h"
+#include "configuration.h"
+#include "downloadswidget.h"
+#include "mainwindow.h"
+#include "profilemanager.h"
+#include "session/sessiondialog.h"
+#include "subwindow/subwindow.h"
+#include "webengine/webview.h"
+#include "widgets/menusearch.h"
+#include <QApplication>
+#include <QDir>
+#include <QFileDialog>
+#include <QLineEdit>
+#include <QMdiArea>
+#include <QPrintDialog>
+#include <QPrinter>
+#include <QPrinterInfo>
+#include <QWidgetAction>
+
+MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
+ : QMenuBar(parent)
+{
+ auto *browser = qobject_cast<Browser *>(qApp);
+ Q_CHECK_PTR(browser);
+
+ smolbote = this->addMenu(qApp->applicationName());
+ {
+ auto *findMenu = smolbote->addMenu(tr("Find in menus"));
+
+ auto *findWidget = new QWidgetAction(this);
+ auto *find_lineEdit = new MenuSearch(this);
+ findWidget->setDefaultWidget(find_lineEdit);
+ findMenu->addAction(findWidget);
+
+ connect(findMenu, &QMenu::aboutToShow, [findMenu, find_lineEdit]() {
+ find_lineEdit->clear();
+ const auto actions = findMenu->actions();
+ for(int i = 1; i < actions.length(); i++)
+ findMenu->removeAction(actions.at(i));
+ find_lineEdit->setFocus();
+ });
+
+ connect(find_lineEdit, &QLineEdit::textEdited, [this, findMenu](const QString &text) {
+ // clear menu
+ const auto actions = findMenu->actions();
+ for(int i = 1; i < actions.length(); i++)
+ findMenu->removeAction(actions.at(i));
+
+ if(text.isEmpty())
+ return;
+
+ // findChildren
+ for(QAction *a : this->findChildren<QAction *>()) {
+ if(a->text().contains(text))
+ findMenu->addAction(a);
+ }
+ });
+
+ smolbote->addSeparator();
+
+ const QString sessionPath = config->value<QString>("browser.session.path").value();
+ smolbote->addAction(tr("Save Session"), parent, [parent, sessionPath]() {
+ const QString filename = QFileDialog::getSaveFileName(parent, tr("Save Session"), sessionPath, tr("JSON (*.json)"));
+ QFile output(filename);
+ if(output.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ auto *browser = qobject_cast<Browser *>(qApp);
+ auto data = Session::_session(browser->windows());
+ output.write(QJsonDocument(data).toJson());
+ output.close();
+ }
+ });
+
+ smolbote->addAction(tr("Open Session"), parent, [parent]() {
+ auto *sessionDialog = new SessionDialog(parent);
+ sessionDialog->exec();
+ });
+
+ smolbote->addSeparator();
+ auto *actionBookmarks = smolbote->addAction(tr("Bookmarks"), browser, [browser, parent]() {
+ browser->showWidget(browser->bookmarks(), parent);
+ });
+ config->setShortcut(actionBookmarks, "bookmarks.shortcut");
+
+ auto *actionDownloads = smolbote->addAction(tr("Downloads"), browser, [browser, parent]() {
+ browser->showWidget(browser->downloads(), parent);
+ });
+ config->setShortcut(actionDownloads, "downloads.shortcut");
+
+ smolbote->addSeparator();
+ smolbote->addAction(tr("Load Plugin"), browser, [browser]() {
+ const QString path = QFileDialog::getOpenFileName(nullptr, tr("Select Plugin"), QDir::homePath(), tr("Plugins (*.so)"));
+ browser->addPlugin(path);
+ });
+
+ pluginInsertLocation = smolbote->addSeparator();
+
+ auto *actionAbout = smolbote->addAction(tr("About"), browser, &Browser::about);
+ config->setShortcut(actionAbout, "mainwindow.shortcuts.about");
+
+ smolbote->addAction(tr("Help"));
+
+ //smolbote->addAction(tr("Check for updates"));
+
+ smolbote->addSeparator();
+
+ auto *actionQuit = smolbote->addAction(tr("Quit"), qApp, &QApplication::quit);
+ config->setShortcut(actionQuit, "mainwindow.shortcuts.quit");
+ }
+
+ auto *window = this->addMenu(tr("Window"));
+ {
+ auto *actionNewWindow = window->addAction(tr("New Window"), browser, &Browser::createWindow);
+ config->setShortcut(actionNewWindow, "mainwindow.shortcuts.newWindow");
+
+ auto *actionNewSubwindow = window->addAction(tr("New Subwindow"), parent, [parent]() {
+ parent->createSubWindow(nullptr, true);
+ });
+ config->setShortcut(actionNewSubwindow, "mainwindow.shortcuts.newGroup");
+
+ window->addSeparator();
+
+ auto *actionTileSubwindows = window->addAction(tr("Tile Subwindows"), parent->mdiArea, &QMdiArea::tileSubWindows);
+ config->setShortcut(actionTileSubwindows, "mainwindow.shortcuts.tileWindows");
+
+ auto *actionCascadeSubwindows = window->addAction(tr("Cascade Subwindows"), parent->mdiArea, &QMdiArea::cascadeSubWindows);
+ config->setShortcut(actionCascadeSubwindows, "mainwindow.shortcuts.cascadeWindows");
+ }
+
+ auto *subwindow = this->addMenu(tr("Subwindow"));
+ {
+ auto *actionNewTab = subwindow->addAction(tr("New Tab"), parent, [parent]() {
+ auto *_subwindow = parent->currentSubWindow();
+ if(_subwindow != nullptr) {
+ const int index = _subwindow->addTab();
+ _subwindow->setCurrentTab(index);
+ }
+ });
+ config->setShortcut(actionNewTab, "subwindow.shortcuts.new");
+
+ subwindow->addSeparator();
+
+ subwindow->addAction(tr("Restore last tab"), parent, [parent]() {
+ auto *_subwindow = parent->currentSubWindow();
+ if(_subwindow != nullptr) {
+ const int index = _subwindow->restoreLastTab();
+ _subwindow->setCurrentTab(index);
+ }
+ });
+
+ auto *restoreTabsMenu = subwindow->addMenu(tr("Restore previous tab"));
+ connect(restoreTabsMenu, &QMenu::aboutToShow, parent, [parent, restoreTabsMenu]() {
+ restoreTabsMenu->clear();
+ auto *_subwindow = parent->currentSubWindow();
+ if(_subwindow != nullptr) {
+ _subwindow->restoreTabMenu(restoreTabsMenu);
+ }
+ });
+
+ subwindow->addSeparator();
+
+ auto *subwindowProfile = subwindow->addMenu(tr("Subwindow Profile"));
+ connect(subwindowProfile, &QMenu::aboutToShow, subwindowProfile, [=]() {
+ subwindowProfile->clear();
+
+ auto *_subwindow = parent->currentSubWindow();
+ if(_subwindow != nullptr) {
+ browser->getProfileManager()->profilePickerMenu(subwindowProfile, _subwindow->profile(), [_subwindow](WebProfile *profile) {
+ _subwindow->setProfile(profile);
+ });
+ }
+ });
+ }
+
+ auto *page = this->addMenu(tr("Page"));
+ {
+ page->addAction(tr("Create Bookmark"), parent, [browser, parent]() {
+ if(parent->currentView != nullptr)
+ browser->bookmarks()->addBookmark(parent->currentView->title(), parent->currentView->url().toString());
+ });
+
+ page->addSeparator();
+
+ page->addAction(tr("Save"), parent, [parent]() {
+ if(parent->currentView != nullptr)
+ parent->currentView->triggerPageAction(QWebEnginePage::SavePage);
+ });
+ page->addAction(tr("Print"), parent, [parent]() {
+ if(parent->currentView != nullptr) {
+ auto *printer = new QPrinter(QPrinterInfo::defaultPrinter());
+ QPrintDialog dlg(printer, parent);
+ if(dlg.exec() == QDialog::Accepted) {
+ parent->currentView->page()->print(printer, [printer](bool success) {
+ Q_UNUSED(success);
+ delete printer;
+ });
+ }
+ }
+ });
+
+ page->addAction(tr("Print to PDF"), parent, [parent]() {
+ if(parent->currentView != nullptr) {
+ const QString path = QFileDialog::getSaveFileName(parent, tr("Print to PDF"), QDir::homePath(), tr("PDF files (*.pdf)"));
+ parent->currentView->page()->printToPdf(path);
+ }
+ });
+
+ page->addSeparator();
+
+ auto pageProfile = page->addMenu(tr("Page Profile"));
+ connect(pageProfile, &QMenu::aboutToShow, pageProfile, [=]() {
+ pageProfile->clear();
+
+ if(parent->currentView != nullptr) {
+ browser->getProfileManager()->profilePickerMenu(pageProfile, parent->currentView->profile(), [parent](WebProfile *profile) {
+ parent->currentView->setProfile(profile);
+ });
+ }
+ });
+
+ page->addSeparator();
+ page->addAction(tr("Developer Tools"));
+ page->addAction(tr("View Source"));
+ }
+}
+
+QAction *MenuBar::insertPlugin(QMenu *menu)
+{
+ return smolbote->insertMenu(pluginInsertLocation, menu);
+}
diff --git a/src/mainwindow/menubar.h b/src/mainwindow/menubar.h
new file mode 100644
index 0000000..38b1286
--- /dev/null
+++ b/src/mainwindow/menubar.h
@@ -0,0 +1,28 @@
+/*
+ * 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/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_MENUBAR_H
+#define SMOLBOTE_MENUBAR_H
+
+#include <QMenuBar>
+
+class Configuration;
+class MainWindow;
+class MenuBar : public QMenuBar
+{
+public:
+ MenuBar(const Configuration *config, MainWindow *parent = nullptr);
+
+ QAction *insertPlugin(QMenu *menu);
+
+private:
+ QMenu *smolbote = nullptr;
+ QAction *pluginInsertLocation = nullptr;
+};
+
+#endif // SMOLBOTE_MENUBAR_H
diff --git a/src/mainwindow/widgets/menusearch.cpp b/src/mainwindow/widgets/menusearch.cpp
new file mode 100644
index 0000000..2905d6d
--- /dev/null
+++ b/src/mainwindow/widgets/menusearch.cpp
@@ -0,0 +1,17 @@
+/*
+ * 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/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "menusearch.h"
+
+MenuSearch::MenuSearch(QWidget *parent)
+ : QLineEdit(parent)
+{
+ setMinimumWidth(300);
+ setPlaceholderText(tr("Find..."));
+ setClearButtonEnabled(true);
+}
diff --git a/src/mainwindow/widgets/menusearch.h b/src/mainwindow/widgets/menusearch.h
new file mode 100644
index 0000000..e20604c
--- /dev/null
+++ b/src/mainwindow/widgets/menusearch.h
@@ -0,0 +1,20 @@
+/*
+ * 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/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_MENUSEARCH_H
+#define SMOLBOTE_MENUSEARCH_H
+
+#include <QLineEdit>
+
+class MenuSearch : public QLineEdit
+{
+public:
+ MenuSearch(QWidget *parent = nullptr);
+};
+
+#endif // SMOLBOTE_MENUSEARCH_H
diff --git a/src/mainwindow/widgets/navigationbar.cpp b/src/mainwindow/widgets/navigationbar.cpp
index 61d17fa..c56d342 100644
--- a/src/mainwindow/widgets/navigationbar.cpp
+++ b/src/mainwindow/widgets/navigationbar.cpp
@@ -7,8 +7,9 @@
*/
#include "navigationbar.h"
-#include "urllineedit.h"
#include "configuration.h"
+#include "urllineedit.h"
+#include "util.h"
#include "webengine/webview.h"
#include <QHBoxLayout>
#include <QMenu>
@@ -17,7 +18,6 @@
#include <QToolBar>
#include <QToolButton>
#include <QWebEngineHistory>
-#include "util.h"
NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
: QToolBar(parent)
diff --git a/src/meson.build b/src/meson.build
index 0ad0166..7dfba88 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,11 +1,11 @@
# poi
poi_moc = qt5.preprocess(
moc_headers: ['browser.h',
- 'mainwindow/mainwindow.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h',
+ 'mainwindow/mainwindow.h', 'mainwindow/menubar.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h',
'session/sessiondialog.h', 'session/sessionform.h',
'subwindow/subwindow.h', 'subwindow/tabwidget.h',
'webengine/filter.h', 'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h'],
- ui_files: ['mainwindow/mainwindow.ui', 'mainwindow/widgets/searchform.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
+ ui_files: ['mainwindow/widgets/searchform.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
qresources: '../data/resources.qrc',
rcc_extra_arguments: ['--format-version=1'],
dependencies: dep_qt5
@@ -30,7 +30,9 @@ poi = executable(get_option('poiName'), install: true,
'util.cpp', 'util.h',
'mainwindow/mainwindow.cpp',
+ 'mainwindow/menubar.cpp',
'mainwindow/widgets/dockwidget.cpp',
+ 'mainwindow/widgets/menusearch.cpp',
'mainwindow/widgets/navigationbar.cpp',
'mainwindow/widgets/searchform.cpp',
diff --git a/src/session/session.cpp b/src/session/session.cpp
index 10aca4e..f7d372b 100644
--- a/src/session/session.cpp
+++ b/src/session/session.cpp
@@ -150,7 +150,7 @@ void Session::restoreSession(const QJsonObject &sessionData)
subwindow = window->currentSubWindow();
} else {
window = browser->createWindow();
- subwindow = window->createSubWindow(browser->getConfiguration(), profileManager->profile(subwindowData.toObject()["profile"].toString()));
+ subwindow = window->createSubWindow(profileManager->profile(subwindowData.toObject()["profile"].toString()));
}
Q_CHECK_PTR(window);
@@ -166,7 +166,7 @@ void Session::restoreSession(const QJsonObject &sessionData)
auto *window = browser->createWindow();
for(const auto subwindowData : windowData.toObject()["subwindows"].toArray()) {
- auto *subwindow = window->createSubWindow(browser->getConfiguration(), profileManager->profile(subwindowData.toObject()["profile"].toString()));
+ auto *subwindow = window->createSubWindow(profileManager->profile(subwindowData.toObject()["profile"].toString()));
for(const auto tabData : subwindowData.toObject()["tabs"].toArray()) {
auto *view = subwindow->view(subwindow->addTab());
diff --git a/src/subwindow/subwindow.cpp b/src/subwindow/subwindow.cpp
index 0844f1f..4beba49 100644
--- a/src/subwindow/subwindow.cpp
+++ b/src/subwindow/subwindow.cpp
@@ -61,18 +61,6 @@ SubWindow::SubWindow(const Configuration *config, QWidget *parent, Qt::WindowFla
menu->insertSeparator(firstAction);
}
- // new tab button
- auto *newTab_button = new QToolButton(this);
- newTab_button->setIcon(style()->standardIcon(QStyle::SP_FileIcon));
- newTab_button->setToolTip(tr("Add tab"));
- newTab_button->setShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.new").value()));
- connect(newTab_button, &QToolButton::clicked, this, [=]() {
- auto index = addTab(WebProfile::defaultProfile()->newtab());
- tabWidget->setCurrentIndex(index);
- });
- newTab_button->setMenu(tabWidget->createTabMenu(newTab_button));
- tabWidget->setCornerWidget(newTab_button, Qt::TopRightCorner);
-
// general actions
auto *closeTab_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.close").value()), this);
connect(closeTab_shortcut, &QShortcut::activated, this, [=]() {
@@ -159,8 +147,10 @@ int SubWindow::tabCount() const
void SubWindow::setProfile(WebProfile *profile)
{
- if(profile == nullptr)
+ if(profile == nullptr) {
+ setProfile(WebProfile::defaultProfile());
return;
+ }
this->m_profile = profile;
for(int i = 0; i < tabWidget->count(); ++i) {
@@ -178,13 +168,29 @@ int SubWindow::addTab(const QUrl &url, WebProfile *profile)
{
Q_CHECK_PTR(m_profile);
- auto *view = new WebView((profile == nullptr) ? m_profile : profile, this);
- if(!url.isEmpty())
+ auto *_profile = (profile == nullptr) ? m_profile : profile;
+
+ auto *view = new WebView(_profile, this);
+ if(url.isEmpty())
+ view->load(_profile->newtab());
+ else
view->load(url);
+
return tabWidget->addTab(view);
}
void SubWindow::setCurrentTab(int index)
{
- tabWidget->setCurrentIndex(index);
+ if(index > 0)
+ tabWidget->setCurrentIndex(index);
+}
+
+int SubWindow::restoreLastTab()
+{
+ return tabWidget->restoreLastTab();
+}
+
+void SubWindow::restoreTabMenu(QMenu *menu)
+{
+ tabWidget->restoreTabMenu(menu);
}
diff --git a/src/subwindow/subwindow.h b/src/subwindow/subwindow.h
index 3d70c98..1fc0097 100644
--- a/src/subwindow/subwindow.h
+++ b/src/subwindow/subwindow.h
@@ -40,6 +40,9 @@ public slots:
int addTab(const QUrl &url = QUrl(), WebProfile *profile = nullptr);
void setCurrentTab(int index);
+ int restoreLastTab();
+ void restoreTabMenu(QMenu *menu);
+
private:
WebProfile *m_profile;
TabWidget *tabWidget;
diff --git a/src/subwindow/tabwidget.cpp b/src/subwindow/tabwidget.cpp
index 942a364..c635aee 100644
--- a/src/subwindow/tabwidget.cpp
+++ b/src/subwindow/tabwidget.cpp
@@ -31,7 +31,7 @@ TabWidget::TabWidget(QWidget *parent)
setStyleSheet("QTabBar::tab { width: 200px; }");
setTabsClosable(true);
- //setTabBarAutoHide(true);
+ setTabBarAutoHide(true);
setElideMode(Qt::ElideRight);
setMovable(true);
@@ -75,51 +75,6 @@ TabWidget::~TabWidget()
}
}
-QMenu *TabWidget::createTabMenu(QWidget *parent)
-{
- auto *menu = new QMenu(parent);
-
- auto *reopenTabAction = menu->addAction(tr("Reopen last tab"));
- connect(reopenTabAction, &QAction::triggered, this, [this]() {
- if(!m_closedTabs.isEmpty()) {
- TabInformation tab = m_closedTabs.takeLast();
- addTab(createViewFromInfo(tab, this));
- }
- });
-
- auto *tabHistoryMenu = menu->addMenu(tr("Tab History"));
- connect(tabHistoryMenu, &QMenu::aboutToShow, this, [this, tabHistoryMenu]() {
- tabHistoryMenu->clear();
- for(int i = 0; i < m_closedTabs.count(); ++i) {
- auto *openAction = tabHistoryMenu->addAction(m_closedTabs.at(i).title);
-
- connect(openAction, &QAction::triggered, this, [this, i]() {
- TabInformation tab = m_closedTabs.takeAt(i);
- addTab(createViewFromInfo(tab, this));
- });
- }
-
- tabHistoryMenu->addSeparator();
-
- auto *clearTabHistory = tabHistoryMenu->addAction(tr("Clear"));
- connect(clearTabHistory, &QAction::triggered, this, [this]() {
- m_closedTabs.clear();
- });
- });
-
- connect(menu, &QMenu::aboutToShow, this, [this, reopenTabAction, tabHistoryMenu]() {
- if(m_closedTabs.isEmpty()) {
- reopenTabAction->setEnabled(false);
- tabHistoryMenu->setEnabled(false);
- } else {
- reopenTabAction->setEnabled(true);
- tabHistoryMenu->setEnabled(true);
- }
- });
-
- return menu;
-}
-
int TabWidget::addTab(WebView *view)
{
Q_ASSERT_X(view != nullptr, "TabWidget::addTab", "Tried to add null view");
@@ -165,6 +120,37 @@ void TabWidget::deleteTab(int index)
parentWidget()->close();
}
+int TabWidget::restoreLastTab()
+{
+ if(!m_closedTabs.isEmpty()) {
+ TabInformation tab = m_closedTabs.takeLast();
+ return addTab(createViewFromInfo(tab, this));
+ }
+ return -1;
+}
+
+void TabWidget::restoreTabMenu(QMenu *menu)
+{
+ if(m_closedTabs.isEmpty())
+ return;
+
+ for(int i = 0; i < m_closedTabs.count(); ++i) {
+ auto *openAction = menu->addAction(m_closedTabs.at(i).title);
+
+ connect(openAction, &QAction::triggered, this, [this, i]() {
+ TabInformation tab = m_closedTabs.takeAt(i);
+ addTab(createViewFromInfo(tab, this));
+ });
+ }
+
+ menu->addSeparator();
+
+ auto *clearTabHistory = menu->addAction(tr("Clear"));
+ connect(clearTabHistory, &QAction::triggered, this, [this]() {
+ m_closedTabs.clear();
+ });
+}
+
void TabWidget::contextMenuEvent(QContextMenuEvent *event)
{
// check if the context menu was called on a tab
diff --git a/src/subwindow/tabwidget.h b/src/subwindow/tabwidget.h
index 48690e8..ef1930d 100644
--- a/src/subwindow/tabwidget.h
+++ b/src/subwindow/tabwidget.h
@@ -34,12 +34,13 @@ public:
explicit TabWidget(QWidget *parent = nullptr);
~TabWidget() override;
- QMenu *createTabMenu(QWidget *parent = nullptr);
-
public slots:
int addTab(WebView *view);
void deleteTab(int index);
+ int restoreLastTab();
+ void restoreTabMenu(QMenu *menu);
+
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;