aboutsummaryrefslogtreecommitdiff
path: root/src/mainwindow
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainwindow')
-rw-r--r--src/mainwindow/addressbar.cpp63
-rw-r--r--src/mainwindow/addressbar.h42
-rw-r--r--src/mainwindow/addressbar.ui59
-rw-r--r--src/mainwindow/mainwindow.cpp29
-rw-r--r--src/mainwindow/mainwindow.h3
-rw-r--r--src/mainwindow/menubar.cpp42
-rw-r--r--src/mainwindow/menubar.h3
-rw-r--r--src/mainwindow/widgets/completer.cpp81
-rw-r--r--src/mainwindow/widgets/completer.h35
-rw-r--r--src/mainwindow/widgets/navigationbar.cpp18
-rw-r--r--src/mainwindow/widgets/navigationbar.h2
-rw-r--r--src/mainwindow/widgets/urllineedit.cpp157
-rw-r--r--src/mainwindow/widgets/urllineedit.h51
13 files changed, 535 insertions, 50 deletions
diff --git a/src/mainwindow/addressbar.cpp b/src/mainwindow/addressbar.cpp
new file mode 100644
index 0000000..42fa890
--- /dev/null
+++ b/src/mainwindow/addressbar.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 "addressbar.h"
+#include "ui_addressbar.h"
+#include <QShortcut>
+#include "configuration.h"
+
+AddressBar::AddressBar(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::AddressBar)
+{
+ ui->setupUi(this);
+
+ Configuration conf;
+ ui->urlBar->menuAction->setShortcut(QKeySequence(conf.value<QString>("shortcuts.address.menu").value()));
+
+ auto *focusShortcut = new QShortcut(QKeySequence(conf.value<QString>("shortcuts.address.focus").value()), parent);
+ connect(focusShortcut, &QShortcut::activated, ui->urlBar, [=]() {
+ ui->urlBar->setFocus();
+ ui->urlBar->selectAll();
+ });
+
+ connect(ui->urlBar, &UrlLineEdit::textEdited, [=](const QString &text) {
+ std::function<void(QStringList &)> callback = std::bind(&UrlLineEdit::updateCompleter, ui->urlBar, std::placeholders::_1);
+ emit complete(text, callback);
+ });
+
+ connect(ui->urlBar, &UrlLineEdit::returnPressed, [=]() {
+ const QUrl url = QUrl::fromUserInput(ui->urlBar->text());
+
+ // check if url contains \w+:// (matches protocol://) or contains a '.' (matches site.domain)
+ // this is because single words are valid URLs for QUrl (searchterm becomes http://searchterm)
+ // check for protocol://site because \. wouldn't match it (localhost is a search term; http://localhost is an address)
+ if(ui->urlBar->text().contains(QRegularExpression("\\w+://|\\.")) && url.isValid()) {
+ emit load(url);
+ } else {
+ emit search(ui->urlBar->text());
+ }
+ });
+}
+
+AddressBar::~AddressBar()
+{
+ disconnect(this);
+}
+
+void AddressBar::setUrl(const QUrl &url)
+{
+ if(url.isEmpty())
+ ui->urlBar->clear();
+ else
+ ui->urlBar->setUrl(url);
+}
+
+void AddressBar::setProgress(int value) {
+ ui->loadingBar->setValue(std::min(value, 100));
+}
diff --git a/src/mainwindow/addressbar.h b/src/mainwindow/addressbar.h
new file mode 100644
index 0000000..61d00e9
--- /dev/null
+++ b/src/mainwindow/addressbar.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/gitea/aqua/smolbote
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#ifndef SMOLBOTE_ADDRESSBAR_H
+#define SMOLBOTE_ADDRESSBAR_H
+
+#include <QWidget>
+#include <functional>
+
+namespace Ui {
+class AddressBar;
+}
+
+class AddressBar : public QWidget
+{
+ Q_OBJECT
+
+public:
+ AddressBar(QWidget *parent = nullptr);
+ ~AddressBar() override;
+
+signals:
+ void complete(const QString &term, std::function<void(QStringList &)> callback);
+
+ void search(const QString &term);
+ void load(const QUrl &url);
+ void giveFocus();
+
+public slots:
+ void setUrl(const QUrl &url);
+ void setProgress(int value);
+
+private:
+ Ui::AddressBar *ui;
+};
+
+#endif // SMOLBOTE_ADDRESSBAR_H
diff --git a/src/mainwindow/addressbar.ui b/src/mainwindow/addressbar.ui
new file mode 100644
index 0000000..1af1689
--- /dev/null
+++ b/src/mainwindow/addressbar.ui
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddressBar</class>
+ <widget class="QWidget" name="AddressBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>31</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="UrlLineEdit" name="urlBar"/>
+ </item>
+ <item>
+ <widget class="QProgressBar" name="loadingBar">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>5</height>
+ </size>
+ </property>
+ <property name="textVisible">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>UrlLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>mainwindow/widgets/urllineedit.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp
index 7fb7d9e..fa8b23a 100644
--- a/src/mainwindow/mainwindow.cpp
+++ b/src/mainwindow/mainwindow.cpp
@@ -9,7 +9,7 @@
#include "mainwindow.h"
#include "addressbar.h"
#include "browser.h"
-#include "config.h"
+#include "conf.hpp"
#include "configuration.h"
#include "menubar.h"
#include "webprofilemanager.h"
@@ -39,14 +39,11 @@
#include <KWindowEffects>
#endif
-MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *parent)
+MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
- , configuration(config.get())
, mdiArea(new QMdiArea(this))
{
- Q_ASSERT(config);
-
- m_menuBar = new MenuBar(config.get(), this);
+ m_menuBar = new MenuBar(this);
this->setMenuBar(m_menuBar);
#ifdef CONFIG_PLASMA_BLUR
@@ -54,10 +51,12 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
KWindowEffects::enableBlurBehind(this->winId(), true);
#endif
+ Configuration config;
+
// create UI
- setWindowTitle(config->value<QString>("mainwindow.title").value());
- resize(config->value<int>("mainwindow.width").value(), config->value<int>("mainwindow.height").value());
- if(config->value<bool>("mainwindow.maximized").value()) {
+ setWindowTitle(config.value<QString>("mainwindow.title").value());
+ resize(config.value<int>("mainwindow.width").value(), config.value<int>("mainwindow.height").value());
+ if(config.value<bool>("mainwindow.maximized").value_or(false)) {
setWindowState(Qt::WindowMaximized);
}
show();
@@ -66,7 +65,7 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
{
QAction *subwindowMenuAction = new QAction(this);
QMainWindow::addAction(subwindowMenuAction);
- config->setShortcut(subwindowMenuAction, "subwindow.shortcuts.menu");
+ setShortcut(subwindowMenuAction, "shortcuts.subwindow.menu");
connect(subwindowMenuAction, &QAction::triggered, this, [this]() {
QMdiSubWindow *window = mdiArea->currentSubWindow();
if(window != nullptr) {
@@ -78,12 +77,12 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
});
}
- navigationToolBar = new NavigationBar(config.get(), this);
- navigationToolBar->setMovable(config->value<bool>("navigation.movable").value());
+ navigationToolBar = new NavigationBar(this);
+ navigationToolBar->setMovable(config.value<bool>("navigation.movable").value_or(false));
addToolBar(Qt::TopToolBarArea, navigationToolBar);
navigationToolBar->connectWebView(nullptr);
- addressBar = new AddressBar(config->section("addressbar"), this);
+ addressBar = new AddressBar(this);
navigationToolBar->addWidget(addressBar);
mdiArea->setBackground(Qt::NoBrush);
@@ -134,7 +133,7 @@ MainWindow::MainWindow(const std::unique_ptr<Configuration> &config, QWidget *pa
// search box
auto *searchAction = new QAction(this);
- config->setShortcut(searchAction, "mainwindow.shortcuts.search");
+ setShortcut(searchAction, "shortcuts.window.search");
connect(searchAction, &QAction::triggered, this, [=]() {
/* QTBUG-18665
* When focusing out of the search box and hiding it, the first
@@ -224,7 +223,7 @@ SubWindow *MainWindow::createSubWindow(WebProfile *profile, bool openProfileNewt
shouldMaximize = currentWindow->isMaximized();
}
- auto *w = new SubWindow(configuration, this);
+ auto *w = new SubWindow(this);
m_menuBar->insertSubWindow(w);
w->setProfile(profile);
diff --git a/src/mainwindow/mainwindow.h b/src/mainwindow/mainwindow.h
index 44ee633..dc185da 100644
--- a/src/mainwindow/mainwindow.h
+++ b/src/mainwindow/mainwindow.h
@@ -35,7 +35,7 @@ public:
ToolsMenu
};
- explicit MainWindow(const std::unique_ptr<Configuration> &config, QWidget *parent = nullptr);
+ explicit MainWindow(QWidget *parent = nullptr);
Q_DISABLE_COPY(MainWindow)
~MainWindow() override;
@@ -56,7 +56,6 @@ protected:
void closeEvent(QCloseEvent *event) override;
private:
- const Configuration *configuration = nullptr;
MenuBar *m_menuBar = nullptr;
QMenu *toolsMenu = nullptr;
QMenu *pageLoadProfileMenu = nullptr;
diff --git a/src/mainwindow/menubar.cpp b/src/mainwindow/menubar.cpp
index 7b7d912..2ce87f7 100644
--- a/src/mainwindow/menubar.cpp
+++ b/src/mainwindow/menubar.cpp
@@ -67,7 +67,7 @@ inline QDialog *createDevToolsDialog(QWebEnginePage *page)
return popup;
}
-MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
+MenuBar::MenuBar(MainWindow *parent)
: QMenuBar(parent)
{
auto *browser = qobject_cast<Browser *>(qApp);
@@ -108,30 +108,31 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
smolbote->addSeparator();
- const QString sessionPath = config->value<QString>("browser.session.path").value();
+ Configuration conf;
+ const QString sessionPath = conf.value<QString>("session.path").value();
auto *actionSaveSession = smolbote->addAction(tr("Save Session"), parent, [sessionPath]() {
auto *sessionDialog = new SaveSessionDialog(nullptr);
if(sessionDialog->exec() == QDialog::Accepted)
sessionDialog->save(sessionPath);
});
- config->setShortcut(actionSaveSession, "mainwindow.shortcuts.saveSession");
+ setShortcut(actionSaveSession, "shortcuts.session.save");
auto *actionOpenSession = smolbote->addAction(tr("Open Session"), parent, [parent]() {
auto *sessionDialog = new SessionDialog(parent);
sessionDialog->exec();
});
- config->setShortcut(actionOpenSession, "mainwindow.shortcuts.openSession");
+ setShortcut(actionOpenSession, "shortcuts.session.open");
smolbote->addSeparator();
auto *actionBookmarks = smolbote->addAction(tr("Bookmarks"), browser, [browser, parent]() {
browser->showWidget(browser->bookmarks(), parent);
});
- config->setShortcut(actionBookmarks, "bookmarks.shortcut");
+ setShortcut(actionBookmarks, "shortcuts.window.bookmarks.show");
auto *actionDownloads = smolbote->addAction(tr("Downloads"), browser, [browser, parent]() {
browser->showWidget(browser->downloads(), parent);
});
- config->setShortcut(actionDownloads, "downloads.shortcut");
+ setShortcut(actionDownloads, "shortcuts.window.downloads.show");
smolbote->addSeparator();
smolbote->addAction(tr("Load Plugin"), browser, [browser]() {
@@ -142,34 +143,31 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
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"));
+ setShortcut(actionAbout, "shortcuts.window.about");
smolbote->addSeparator();
auto *actionQuit = smolbote->addAction(tr("Quit"), qApp, &QApplication::quit);
- config->setShortcut(actionQuit, "mainwindow.shortcuts.quit");
+ setShortcut(actionQuit, "shortcuts.window.quit");
}
window = this->addMenu(tr("&Window"));
{
auto *actionNewWindow = window->addAction(tr("New Window"), browser, &Browser::createWindow);
- config->setShortcut(actionNewWindow, "mainwindow.shortcuts.newWindow");
+ setShortcut(actionNewWindow, "shortcuts.window.newwindow");
auto *actionNewSubwindow = window->addAction(tr("New Subwindow"), parent, [parent]() {
parent->createSubWindow(nullptr, true);
});
- config->setShortcut(actionNewSubwindow, "mainwindow.shortcuts.newGroup");
+ setShortcut(actionNewSubwindow, "shortcuts.window.newgroup");
window->addSeparator();
auto *actionTileSubwindows = window->addAction(tr("Tile Subwindows"), parent->mdiArea, &QMdiArea::tileSubWindows);
- config->setShortcut(actionTileSubwindows, "mainwindow.shortcuts.tileWindows");
+ setShortcut(actionTileSubwindows, "shortcuts.subwindow.tile");
auto *actionCascadeSubwindows = window->addAction(tr("Cascade Subwindows"), parent->mdiArea, &QMdiArea::cascadeSubWindows);
- config->setShortcut(actionCascadeSubwindows, "mainwindow.shortcuts.cascadeWindows");
+ setShortcut(actionCascadeSubwindows, "shortcuts.subwindow.cascade");
window->addSeparator()->setText(tr("Subwindows"));
}
@@ -182,7 +180,7 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
_subwindow->setCurrentTab(index);
});
});
- config->setShortcut(actionNewTab, "subwindow.shortcuts.new");
+ setShortcut(actionNewTab, "shortcuts.subwindow.newtab");
subwindow->addSeparator();
@@ -192,7 +190,7 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
_subwindow->setCurrentTab(index);
});
});
- config->setShortcut(actionRestoreTab, "subwindow.shortcuts.restoreTab");
+ setShortcut(actionRestoreTab, "shortcuts.subwindow.restoretab");
auto *restoreTabsMenu = subwindow->addMenu(tr("Restore previous tab"));
connect(restoreTabsMenu, &QMenu::aboutToShow, parent, [parent, restoreTabsMenu]() {
@@ -242,28 +240,28 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
_subwindow->setCurrentTab(qMax(0, currentIdx - 1));
});
});
- config->setShortcut(leftTab, "subwindow.shortcuts.left");
+ setShortcut(leftTab, "shortcuts.subwindow.tableft");
auto *moveTabLeft = subwindow->addAction(tr("Move tab left"), parent, [parent]() {
run_if(parent->currentSubWindow(), [](SubWindow *_subwindow, int currentIdx) {
_subwindow->moveTab(currentIdx, currentIdx - 1);
});
});
- config->setShortcut(moveTabLeft, "subwindow.shortcuts.moveLeft");
+ setShortcut(moveTabLeft, "shortcuts.subwindow.movetableft");
auto *rightTab = subwindow->addAction(tr("Switch to tab on the right"), parent, [parent]() {
run_if(parent->currentSubWindow(), [](SubWindow *_subwindow, int currentIdx) {
_subwindow->setCurrentTab(qMin(currentIdx + 1, _subwindow->tabCount() - 1));
});
});
- config->setShortcut(rightTab, "subwindow.shortcuts.right");
+ setShortcut(rightTab, "shortcuts.subwindow.tabright");
auto *moveTabRight = subwindow->addAction(tr("Move tab right"), parent, [parent]() {
run_if(parent->currentSubWindow(), [](SubWindow *_subwindow, int currentIdx) {
_subwindow->moveTab(currentIdx, currentIdx + 1);
});
});
- config->setShortcut(moveTabRight, "subwindow.shortcuts.moveRight");
+ setShortcut(moveTabRight, "shortcuts.subwindow.movetabright");
subwindow->addSeparator();
@@ -272,7 +270,7 @@ MenuBar::MenuBar(const Configuration *config, MainWindow *parent)
_subwindow->closeTab(currentIdx);
});
});
- config->setShortcut(closeTab, "subwindow.shortcuts.close");
+ setShortcut(closeTab, "shortcuts.subwindow.closetab");
subwindow->addAction(tr("Close tabs to the left"), parent, [parent]() {
run_if(parent->currentSubWindow(), [](SubWindow *_subwindow, int currentIdx) {
diff --git a/src/mainwindow/menubar.h b/src/mainwindow/menubar.h
index 0d94f30..f4d39c5 100644
--- a/src/mainwindow/menubar.h
+++ b/src/mainwindow/menubar.h
@@ -11,7 +11,6 @@
#include <QMenuBar>
-class Configuration;
class MainWindow;
class SubWindow;
class MenuBar : public QMenuBar
@@ -19,7 +18,7 @@ class MenuBar : public QMenuBar
Q_OBJECT
public:
- MenuBar(const Configuration *config, MainWindow *parent = nullptr);
+ MenuBar(MainWindow *parent = nullptr);
QAction *insertPlugin(QMenu *menu);
void insertSubWindow(SubWindow *subwindow);
diff --git a/src/mainwindow/widgets/completer.cpp b/src/mainwindow/widgets/completer.cpp
new file mode 100644
index 0000000..578f745
--- /dev/null
+++ b/src/mainwindow/widgets/completer.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "completer.h"
+#include <QKeyEvent>
+
+Completer::Completer(QWidget *parent)
+ : QListView(parent)
+{
+ setObjectName("Completer");
+ setWindowFlags(Qt::ToolTip);
+ setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+ connect(this, &Completer::activated, [=](const QModelIndex &index) {
+ hide();
+ emit completionActivated(index.data().toString());
+ });
+}
+
+bool Completer::updateItems(const QStringList &list)
+{
+ if(list.isEmpty())
+ return false;
+
+ auto *model = new QStringListModel(list, this);
+ setModel(model);
+
+ delete completionModel;
+ completionModel = model;
+
+ return true;
+}
+
+bool Completer::keyPressed(QKeyEvent *event)
+{
+ if(isHidden())
+ return false;
+
+ Q_CHECK_PTR(completionModel);
+
+ int count = completionModel->rowCount();
+ const QModelIndex currentIndex = this->currentIndex();
+
+ switch(event->key()) {
+ case Qt::Key_Down:
+ if(currentIndex.row() + 1 >= count) {
+ setCurrentIndex(completionModel->index(0, 0));
+ } else {
+ setCurrentIndex(completionModel->index(currentIndex.row() + 1, 0));
+ }
+ break;
+
+ case Qt::Key_Up:
+ if(currentIndex.row() == 0) {
+ setCurrentIndex(completionModel->index(count - 1, 0));
+ } else {
+ setCurrentIndex(completionModel->index(currentIndex.row() - 1, 0));
+ }
+ break;
+
+ case Qt::Key_Escape:
+ hide();
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ hide();
+ emit completionActivated(currentIndex.data().toString());
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/mainwindow/widgets/completer.h b/src/mainwindow/widgets/completer.h
new file mode 100644
index 0000000..656a80f
--- /dev/null
+++ b/src/mainwindow/widgets/completer.h
@@ -0,0 +1,35 @@
+/*
+ * 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_COMPLETER_H
+#define SMOLBOTE_COMPLETER_H
+
+#include <QListView>
+#include <QStringListModel>
+#include <QTreeWidgetItem>
+
+class Completer : public QListView
+{
+
+ Q_OBJECT
+
+public:
+ explicit Completer(QWidget *parent = nullptr);
+
+ bool updateItems(const QStringList &list);
+
+ bool keyPressed(QKeyEvent *event);
+
+signals:
+ void completionActivated(const QString &url);
+
+private:
+ QStringListModel *completionModel = nullptr;
+};
+
+#endif //SMOLBOTE_COMPLETER_H
diff --git a/src/mainwindow/widgets/navigationbar.cpp b/src/mainwindow/widgets/navigationbar.cpp
index e77ce6d..f57d678 100644
--- a/src/mainwindow/widgets/navigationbar.cpp
+++ b/src/mainwindow/widgets/navigationbar.cpp
@@ -20,12 +20,14 @@
#include <QWebEngineHistory>
#include "webprofile.h"
-NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
+NavigationBar::NavigationBar(QWidget *parent)
: QToolBar(parent)
{
+ Configuration config;
+
// Back button
backAction = addAction(Util::icon(QStyle::SP_ArrowBack), tr("Back"));
- config->setShortcut(backAction, "navigation.shortcuts.back");
+ setShortcut(backAction, "shortcuts.navigation.back");
connect(backAction, &QAction::triggered, this, [this]() {
m_view->history()->back();
});
@@ -43,7 +45,7 @@ NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
});
backAction->setMenu(backMenu);
- auto *backMenuShortcut = new QShortcut(QKeySequence(config->value<QString>("navigation.shortcuts.backMenu").value()), this);
+ auto *backMenuShortcut = new QShortcut(QKeySequence(config.value<QString>("shortcuts.navigation.backmenu").value()), this);
connect(backMenuShortcut, &QShortcut::activated, backMenu, [this, backMenu]() {
if(backAction->isEnabled()) {
auto *widget = this->widgetForAction(backAction);
@@ -53,7 +55,7 @@ NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
// Forward button
forwardAction = addAction(Util::icon(QStyle::SP_ArrowForward), tr("Forward"));
- config->setShortcut(forwardAction, "navigation.shortcuts.forward");
+ setShortcut(forwardAction, "shortcuts.navigation.forward");
connect(forwardAction, &QAction::triggered, this, [this]() {
m_view->history()->forward();
});
@@ -71,7 +73,7 @@ NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
});
forwardAction->setMenu(forwardMenu);
- auto *forwardMenuShortcut = new QShortcut(QKeySequence(config->value<QString>("navigation.shortcuts.forwardMenu").value()), this);
+ auto *forwardMenuShortcut = new QShortcut(QKeySequence(config.value<QString>("shortcuts.navigation.forwardmenu").value()), this);
connect(forwardMenuShortcut, &QShortcut::activated, forwardMenu, [this, forwardMenu]() {
if(forwardAction->isEnabled()) {
auto *widget = this->widgetForAction(forwardAction);
@@ -81,7 +83,7 @@ NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
// Stop/Refresh button
stopReloadAction = addAction(Util::icon(QStyle::SP_BrowserReload), tr("Refresh"));
- config->setShortcut(stopReloadAction, "navigation.shortcuts.refresh");
+ setShortcut(stopReloadAction, "shortcuts.navigation.refresh");
connect(stopReloadAction, &QAction::triggered, this, [this]() {
if(m_view->isLoaded())
m_view->reload();
@@ -89,14 +91,14 @@ NavigationBar::NavigationBar(const Configuration *config, QWidget *parent)
m_view->stop();
});
- auto *reloadShortcut = new QShortcut(QKeySequence(config->value<QString>("navigation.shortcuts.reload").value()), this);
+ auto *reloadShortcut = new QShortcut(QKeySequence(config.value<QString>("shortcuts.navigation.reload").value()), this);
connect(reloadShortcut, &QShortcut::activated, this, [this]() {
m_view->triggerPageAction(QWebEnginePage::ReloadAndBypassCache);
});
// Home button
homeAction = addAction(Util::icon(QStyle::SP_DirHomeIcon), tr("Home"));
- config->setShortcut(homeAction, "navigation.shortcuts.home");
+ setShortcut(homeAction, "shortcuts.navigation.home");
connect(homeAction, &QAction::triggered, this, [this]() {
m_view->load(m_view->profile()->homepage());
});
diff --git a/src/mainwindow/widgets/navigationbar.h b/src/mainwindow/widgets/navigationbar.h
index 0b5a319..b8c73e1 100644
--- a/src/mainwindow/widgets/navigationbar.h
+++ b/src/mainwindow/widgets/navigationbar.h
@@ -18,7 +18,7 @@ class NavigationBar : public QToolBar
Q_OBJECT
public:
- explicit NavigationBar(const Configuration *config, QWidget *parent = nullptr);
+ explicit NavigationBar(QWidget *parent = nullptr);
public slots:
void connectWebView(WebView *view);
diff --git a/src/mainwindow/widgets/urllineedit.cpp b/src/mainwindow/widgets/urllineedit.cpp
new file mode 100644
index 0000000..378945f
--- /dev/null
+++ b/src/mainwindow/widgets/urllineedit.cpp
@@ -0,0 +1,157 @@
+/*
+ * 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 "urllineedit.h"
+#include <QMenu>
+#include <QShortcut>
+#include <QApplication>
+#include <QClipboard>
+#include "../addressbar.h"
+
+UrlLineEdit::UrlLineEdit(QWidget *parent)
+ : QLineEdit(parent)
+ , m_listView(new Completer(this))
+{
+ setObjectName("UrlBar");
+ setPlaceholderText(tr("Enter address"));
+
+ m_listView->setVisible(false);
+ connect(m_listView, &Completer::completionActivated, this, &UrlLineEdit::setText);
+
+ addressbar = qobject_cast<AddressBar *>(parent);
+ Q_CHECK_PTR(addressbar);
+
+ auto *copyAction = new QAction(tr("Copy URL"), this);
+ connect(copyAction, &QAction::triggered, this, [this]() {
+ qApp->clipboard()->setText(this->text());
+ });
+ actions.append(copyAction);
+
+ auto *pasteAction = new QAction(tr("Paste URL"), this);
+ connect(pasteAction, &QAction::triggered, this, [this]() {
+ this->setText(qApp->clipboard()->text());
+ this->setFocus();
+ });
+ actions.append(pasteAction);
+
+ auto *loadAction = new QAction(tr("Paste and load"), this);
+ connect(loadAction, &QAction::triggered, this, [=]() {
+ emit addressbar->load(QUrl::fromUserInput(qApp->clipboard()->text()));
+ });
+ actions.append(loadAction);
+
+ auto *searchAction = new QAction(tr("Paste and search"), this);
+ connect(searchAction, &QAction::triggered, this, [=]() {
+ emit addressbar->search(qApp->clipboard()->text());
+ });
+ actions.append(searchAction);
+
+ menuAction = addAction(style()->standardIcon(QStyle::SP_DriveNetIcon), QLineEdit::LeadingPosition);
+ connect(menuAction, &QAction::triggered, this, [this]() {
+ auto *menu = new QMenu();
+ menu->setAttribute(Qt::WA_DeleteOnClose, true);
+ menu->setMinimumWidth(240);
+ menu->addActions(actions);
+
+ menu->exec(this->mapToGlobal(QPoint(0, height())));
+ });
+
+ auto *goAction = addAction(style()->standardIcon(QStyle::SP_DialogOkButton), QLineEdit::TrailingPosition);
+ connect(goAction, &QAction::triggered, this, [this]() {
+ emit returnPressed();
+ });
+
+ QTextCharFormat hostnameFormat;
+ hostnameFormat.setFontWeight(QFont::Bold);
+ m_hostFormat.format = hostnameFormat;
+}
+
+void UrlLineEdit::setUrl(const QUrl &url)
+{
+ QString urlText = url.toString();
+ QString domain = url.host();
+
+ m_hostFormat.start = urlText.indexOf(domain);
+ m_hostFormat.length = domain.length();
+
+ clear();
+ clearTextFormat();
+ setTextFormat(m_hostFormat);
+ setText(urlText);
+}
+
+void UrlLineEdit::updateCompleter(const QStringList &l)
+{
+ if(!m_listView->updateItems(l)) {
+ m_listView->hide();
+ return;
+ }
+
+ // positioning
+ m_listView->setFixedWidth(width());
+ m_listView->move(mapToGlobal(QPoint(0, height())));
+ m_listView->show();
+}
+
+void UrlLineEdit::focusInEvent(QFocusEvent *event)
+{
+ // a context menu event also causes a focusInEvent, so if text is selected
+ // skip the formatting step
+ if(event->reason() == Qt::PopupFocusReason) {
+ QLineEdit::focusInEvent(event);
+ return;
+ }
+
+ clearTextFormat();
+ QLineEdit::focusInEvent(event);
+}
+
+void UrlLineEdit::focusOutEvent(QFocusEvent *event)
+{
+ // a context menu event causes a focusOutEvent, and setUrl will clear the
+ // selection, and this would prevent the menu from working properly
+ if(event->reason() == Qt::PopupFocusReason) {
+ QLineEdit::focusOutEvent(event);
+ return;
+ }
+
+ const QUrl url = QUrl::fromUserInput(text());
+ if(url.isValid())
+ setUrl(url);
+
+ emit addressbar->giveFocus();
+ QLineEdit::focusOutEvent(event);
+}
+
+void UrlLineEdit::keyPressEvent(QKeyEvent *event)
+{
+ if(m_listView->keyPressed(event)) {
+ event->accept();
+ return;
+ } else if(event->key() == Qt::Key::Key_Escape) {
+ clearFocus();
+ event->accept();
+ return;
+ }
+
+ QLineEdit::keyPressEvent(event);
+}
+
+// formatting taken from: https://forum.qt.io/topic/60962/setting-qlineedit-text-bold
+void UrlLineEdit::setTextFormat(const QTextLayout::FormatRange &format)
+{
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, format.start, format.length, format.format));
+ QInputMethodEvent ev(QString(), attributes);
+ event(&ev);
+}
+
+void UrlLineEdit::clearTextFormat()
+{
+ setTextFormat(QTextLayout::FormatRange());
+}
diff --git a/src/mainwindow/widgets/urllineedit.h b/src/mainwindow/widgets/urllineedit.h
new file mode 100644
index 0000000..88780a1
--- /dev/null
+++ b/src/mainwindow/widgets/urllineedit.h
@@ -0,0 +1,51 @@
+/*
+ * 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_URLLINEEDIT_H
+#define SMOLBOTE_URLLINEEDIT_H
+
+#include "completer.h"
+#include <QAction>
+#include <QLineEdit>
+#include <QTextLayout>
+
+class AddressBar;
+class WebView;
+class UrlLineEdit : public QLineEdit
+{
+ Q_OBJECT
+public:
+ explicit UrlLineEdit(QWidget *parent = nullptr);
+
+public slots:
+ void setUrl(const QUrl &url);
+
+ void updateCompleter(const QStringList &l);
+
+public:
+ QAction *menuAction = nullptr;
+
+protected:
+ void focusInEvent(QFocusEvent *event) override;
+ void focusOutEvent(QFocusEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+
+private:
+ void setTextFormat(const QTextLayout::FormatRange &format);
+ void clearTextFormat();
+
+ QList<QAction *> actions;
+
+ QTextLayout::FormatRange m_hostFormat;
+
+ // completer
+ Completer *m_listView;
+ AddressBar *addressbar;
+};
+
+#endif // SMOLBOTE_URLLINEEDIT_H