aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2019-11-03 00:18:10 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2019-11-03 00:20:41 +0200
commitf3a4607d6a722a862af0eb9747a15dcdf624b6fb (patch)
tree9885709cdff55a865be6c03c591a9757680b0396 /src
parentChange spdlog from makedepends to depends (diff)
downloadsmolbote-f3a4607d6a722a862af0eb9747a15dcdf624b6fb.tar.xz
Drop boost dependency
- wrote not-invented-here config file parser and conf class - spent obscene amount of time plugging in said conf class
Diffstat (limited to 'src')
-rw-r--r--src/browser.cpp91
-rw-r--r--src/browser.h7
-rw-r--r--src/conf.hpp.in32
-rw-r--r--src/main.cpp98
-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
-rw-r--r--src/meson.build11
-rw-r--r--src/session/sessiondialog.cpp4
-rw-r--r--src/subwindow/subwindow.cpp5
-rw-r--r--src/subwindow/subwindow.h3
-rw-r--r--src/webengine/webview.cpp2
22 files changed, 666 insertions, 172 deletions
diff --git a/src/browser.cpp b/src/browser.cpp
index 0b076ca..d677997 100644
--- a/src/browser.cpp
+++ b/src/browser.cpp
@@ -9,9 +9,9 @@
#include "browser.h"
#include "aboutdialog.h"
#include "aboutplugin.h"
-#include "addressbar.h"
+#include "mainwindow/addressbar.h"
#include "bookmarkswidget.h"
-#include "config.h"
+#include "conf.hpp"
#include "configuration.h"
#include "downloadswidget.h"
#include "mainwindow/mainwindow.h"
@@ -39,6 +39,8 @@
#include "hostlist/hostlist.h"
#include <spdlog/spdlog.h>
#include <pluginloader.h>
+#include <QLibraryInfo>
+#include <QTranslator>
Browser::Browser(int &argc, char *argv[], bool allowSecondary)
: SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion)
@@ -46,6 +48,29 @@ Browser::Browser(int &argc, char *argv[], bool allowSecondary)
setApplicationName(CONFIG_POI_NAME);
setWindowIcon(QIcon(CONFIG_POI_ICON));
setApplicationVersion(QVersionNumber::fromString(QLatin1String(poi_Version)).toString());
+
+ Configuration conf;
+
+ if(const auto _translation = conf.value<QString>("browser.translation")) {
+ auto *translator = new QTranslator(this);
+ if(translator->load(_translation.value()))
+ installTranslator(translator);
+ else
+ delete translator;
+ }
+
+ if(const auto _locale = conf.value<QString>("browser.locale")) {
+ auto *locale = new QTranslator(this);
+ if(locale->load("qt_" + _locale.value(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+ installTranslator(locale);
+ else
+ delete locale;
+ }
+
+ if(auto iconTheme = conf.value<QString>("browser.iconTheme")) {
+ QIcon::setThemeName(iconTheme.value());
+ }
+
}
Browser::~Browser()
@@ -66,25 +91,6 @@ void Browser::about()
dlg->exec();
}
-const QStringList Browser::configurationOptions() const
-{
- QStringList options;
- for(const auto &option : m_config->description().options()) {
- options.append(QString::fromStdString(option->long_name()));
- }
- return options;
-}
-
-const QString Browser::configuration(const QString &key) const
-{
- return m_config->value<QString>(qUtf8Printable(key)).value_or(QString());
-}
-
-void Browser::setConfiguration(const QString &key, const QString &value)
-{
- m_config->setValue(qUtf8Printable(key), value);
-}
-
const QList<QPair<QString, Profile *>> Browser::profileList() const
{
QList<QPair<QString, Profile *>> profiles;
@@ -96,6 +102,8 @@ const QList<QPair<QString, Profile *>> Browser::profileList() const
QPair<QString, Profile *> Browser::loadProfile(const QString &id, bool isOffTheRecord)
{
+ Configuration conf;
+
const QString _id = [id](){
// if id contains a separator, it should be a path
if(id.contains(QDir::separator())) {
@@ -112,7 +120,7 @@ QPair<QString, Profile *> Browser::loadProfile(const QString &id, bool isOffTheR
for(UrlFilter *filter : m_filters) {
interceptor->addFilter(filter);
}
- const auto headers = m_config->value<QStringList>("filter.header").value_or(QStringList());
+ const auto headers = conf.value<QStringList>("filter.header").value_or(QStringList());
for(const QString &header : headers) {
const auto h = header.split(QLatin1Literal(":"));
if(h.length() == 2)
@@ -129,18 +137,6 @@ void Browser::removeProfile(const QString &id)
m_profileManager->deleteProfile(id);
}
-void Browser::setConfiguration(std::unique_ptr<Configuration> &config)
-{
- Q_ASSERT(config);
- m_config = std::move(config);
-}
-
-Configuration *Browser::getConfiguration() const
-{
- Q_ASSERT(m_config);
- return m_config.get();
-}
-
WebProfileManager *Browser::getProfileManager()
{
return m_profileManager;
@@ -172,13 +168,13 @@ QPluginLoader *Browser::addPlugin(const QString &path)
void Browser::setup(QVector<QPluginLoader *> plugins)
{
- Q_ASSERT(m_config);
+ Configuration conf;
+
for(QPluginLoader *loader : plugins) {
m_plugins.append(new PluginInfo(loader));
}
- auto stylesheet = m_config->value<QString>("browser.stylesheet");
- if(stylesheet) {
+ if(auto stylesheet = conf.value<QString>("browser.stylesheet")) {
QFile f(stylesheet.value());
if(f.open(QIODevice::ReadOnly)) {
setStyleSheet(f.readAll());
@@ -187,16 +183,17 @@ void Browser::setup(QVector<QPluginLoader *> plugins)
}
// downloads
- m_downloads = std::make_unique<DownloadsWidget>(m_config->value<QString>("downloads.path").value());
+ m_downloads = std::make_unique<DownloadsWidget>(conf.value<QString>("downloads.path").value());
+
// url request filter
- for(const QString &hostlist : Util::files(m_config->value<QString>("filter.hosts").value_or(QString()))) {
+ for(const QString &hostlist : Util::files(conf.value<QString>("filter.hosts").value_or(QString()))) {
QFile f(hostlist);
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_filters.append(new HostList(&f));
f.close();
}
}
- for(const QString &adblock : Util::files(m_config->value<QString>("filter.adblock").value_or(QString()))) {
+ for(const QString &adblock : Util::files(conf.value<QString>("filter.adblock").value_or(QString()))) {
QFile f(adblock);
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_filters.append(new AdBlockList(&f));
@@ -206,14 +203,18 @@ void Browser::setup(QVector<QPluginLoader *> plugins)
// cookie request filter
// load profiles
- m_profileManager = new WebProfileManager(m_config->section("profile"), this);
- for(const QString &profilePath : Util::files(m_config->value<QString>("profile.path").value(), { "*.profile" })) {
+ ProfileDefault_t p;
+ p.search = conf.value<QString>("profile.search").value();
+ p.homepage = conf.value<QString>("profile.homepage").value();
+ p.newtab = conf.value<QString>("profile.newtab").value();
+ m_profileManager = new WebProfileManager(p, this);
+ for(const QString &profilePath : Util::files(conf.value<QString>("profile.path").value(), { "*.profile" })) {
this->loadProfile(profilePath);
}
// set default profile
{
- const QString id = m_config->value<QString>("profile.default").value();
+ const QString id = conf.value<QString>("profile.default").value();
auto *profile = m_profileManager->profile(id);
if(profile == nullptr) {
profile = qobject_cast<WebProfile *>(loadProfile(id).second);
@@ -223,7 +224,7 @@ void Browser::setup(QVector<QPluginLoader *> plugins)
}
// bookmarks
- m_bookmarks = std::make_shared<BookmarksWidget>(QString::fromStdString(m_config->value<std::string>("bookmarks.path").value()));
+ m_bookmarks = std::make_shared<BookmarksWidget>(QString::fromStdString(conf.value<std::string>("bookmarks.path").value()));
connect(m_bookmarks.get(), &BookmarksWidget::showContextMenu, this, [this](const QUrl &url, const QPoint &pos) {
auto *subwindow = m_windows.last()->currentSubWindow();
if(subwindow == nullptr)
@@ -276,7 +277,7 @@ void Browser::showWidget(QWidget *widget, MainWindow *where) const
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);
+ auto *window = new MainWindow();
connect(window->addressBar, &AddressBar::complete, m_bookmarks.get(), &BookmarksWidget::search);
for(auto *info : m_plugins) {
diff --git a/src/browser.h b/src/browser.h
index a005513..1faf210 100644
--- a/src/browser.h
+++ b/src/browser.h
@@ -38,18 +38,12 @@ public slots:
public:
// interface
- Configuration *getConfiguration() const;
- const QStringList configurationOptions() const override;
- const QString configuration(const QString &key) const override;
- void setConfiguration(const QString &key, const QString &value) override;
-
WebProfileManager *getProfileManager();
const QList<QPair<QString, Profile *>> profileList() const override;
QPair<QString, Profile *> loadProfile(const QString &id, bool isOffTheRecord = true) override;
void removeProfile(const QString &id) override;
QPluginLoader *addPlugin(const QString &path = QString());
- void setConfiguration(std::unique_ptr<Configuration> &config);
void setup(QVector<QPluginLoader *> plugins);
@@ -87,7 +81,6 @@ private:
Q_DISABLE_COPY(Browser)
- std::unique_ptr<Configuration> m_config;
std::shared_ptr<BookmarksWidget> m_bookmarks;
std::unique_ptr<DownloadsWidget> m_downloads;
WebProfileManager *m_profileManager = nullptr;
diff --git a/src/conf.hpp.in b/src/conf.hpp.in
new file mode 100644
index 0000000..f509eb2
--- /dev/null
+++ b/src/conf.hpp.in
@@ -0,0 +1,32 @@
+/*
+ * 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 "configuration.h"
+#include <fstream>
+
+#mesondefine CONFIG_POI_NAME
+#mesondefine CONFIG_POI_ICON
+#mesondefine CONFIG_POI_CFG_PATH
+
+#mesondefine CONFIG_QTBUG_65223
+
+inline void init_conf(const std::string &path)
+{
+ std::fstream fs;
+ fs.open(path, std::fstream::in);
+ assert(fs.is_open());
+
+ auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({
+ @conf_init_list@
+ });
+ value_map->read(fs);
+
+ Configuration::move_global(std::move(value_map));
+ fs.close();
+}
+
diff --git a/src/main.cpp b/src/main.cpp
index 02a1168..c6f4120 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,15 +15,15 @@
#include "util.h"
#include "version.h"
#include <QFile>
-#include <QLibraryInfo>
#include <QPluginLoader>
-#include <QTranslator>
#include <args.hxx>
#include <iostream>
#include <memory>
#include <plugininterface.h>
#include <pluginloader.h>
#include <spdlog/spdlog.h>
+#include "conf.hpp"
+#include <QStandardPaths>
typedef std::function<void(const std::string &, std::vector<std::string>::const_iterator, std::vector<std::string>::const_iterator)> subcommand_func;
typedef std::unordered_map<std::string, subcommand_func> command_map;
@@ -42,24 +42,6 @@ inline std::string join_keys(const command_map &map, const std::string sep = ",
return k;
}
-#include <QStandardPaths>
-inline std::string defaultUserConfigLocation()
-{
-#ifdef CONFIG_PATH_CONFIG
- return CONFIG_PATH_CONFIG;
-#else
- // try to locate an existing config
- QString path = QStandardPaths::locate(QStandardPaths::ConfigLocation, "smolbote/smolbote.cfg");
-
- // it's possible there is no config, so set the path properly
- if(path.isEmpty())
- path = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/smolbote/smolbote.cfg";
-
- return path.toStdString();
-#endif
-}
-
-#include "config.h"
#if defined(CONFIG_USEPLASMA) && !defined(PLASMA)
#error "You have enabled Plasma integration, but Frameworks was not found."
#endif
@@ -94,7 +76,7 @@ int main(int argc, char **argv)
args::PositionalList<std::string> cmd_args(parser, "URL(s)", "List of URLs to open");
try {
- auto next = parser.ParseArgs(args);
+ /*auto next = */parser.ParseArgs(args);
if(cmd_version)
return builtins::version();
@@ -121,52 +103,48 @@ int main(int argc, char **argv)
// create and load configuration
const std::string config_path = [&]() {
+ std::string path;
if(cmd_config)
- return args::get(cmd_config);
+ path = args::get(cmd_config);
else
- return defaultUserConfigLocation();
+ path = std::string(CONFIG_POI_CFG_PATH);
+
+ if(path.front() == '~')
+ path.replace(0, 1, QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString());
+
+ return path;
}();
- std::unique_ptr<Configuration> config = std::make_unique<Configuration>(argc, argv, config_path);
- QTranslator translator;
- if(config->exists("browser.translation")) {
- translator.load(config->value<QString>("browser.translation").value());
- }
+ spdlog::debug("Opening config file {}", config_path);
+ init_conf(config_path);
+
QVector<QPluginLoader *> plugins;
CommandHash_t pluginCommands;
// Load plugins
- for(const QString &path : Util::files(config->value<QString>("plugins.path").value(), { "*.so", "*.dll" })) {
- auto *loader = new PluginLoader(path);
- const bool loaded = loader->load();
- spdlog::info("{} plugin {}", loaded ? "Loaded" : "Failed to load", qUtf8Printable(path));
-
- if(loaded) {
- plugins.append(loader);
- auto *plugin = qobject_cast<PluginInterface *>(loader->instance());
- pluginCommands.unite(plugin->commands());
- } else {
- spdlog::warn("{}", qUtf8Printable(loader->errorString()));
- delete loader;
- }
+ [&]() {
+ Configuration conf;
+ spdlog::debug("plugins.path={}", conf.value<std::string>("plugins.path").value());
+ for(const QString &path : Util::files(conf.value<QString>("plugins.path").value(), { "*.so", "*.dll" })) {
+ auto *loader = new PluginLoader(path);
+ const bool loaded = loader->load();
+ spdlog::info("{} plugin {}", loaded ? "Loaded" : "Failed to load", qUtf8Printable(path));
+
+ if(loaded) {
+ plugins.append(loader);
+ auto *plugin = qobject_cast<PluginInterface *>(loader->instance());
+ pluginCommands.unite(plugin->commands());
+ } else {
+ spdlog::warn("{}", qUtf8Printable(loader->errorString()));
+ delete loader;
+ }
}
+ }();
// argc, argv, allowSecondary
Browser app(argc, argv);
// set this, otherwise the webview becomes black when using a stylesheet
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
- app.installTranslator(&translator);
- if(config->exists("browser.locale")) {
- auto *locale = new QTranslator(&app);
- if(locale->load("qt_" + config->value<QString>("browser.locale").value(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
- app.installTranslator(locale);
- else
- delete locale;
- }
-
- if(auto iconTheme = config->value<QString>("browser.iconTheme")) {
- QIcon::setThemeName(iconTheme.value());
- }
#ifdef CONFIG_USEBREAKPAD
const std::string crashpath = config->value<std::string>("browser.crash.path").value_or("/tmp");
@@ -186,14 +164,14 @@ int main(int argc, char **argv)
// minidump descriptor, filter callback, minidump callback, callback_context, install handler, server_fd
google_breakpad::ExceptionHandler eh(descriptor, nullptr, CrashHandler::dumpCallback, &ctx, true, -1);
-#ifdef QT_DEBUG
- spdlog::info("Installed breakpad exception handler (path {})", crashpath);
-#endif
+ spdlog::debug("Installed breakpad exception handler (path {})", crashpath);
#endif // CONFIG_USEBREAKPAD
- const auto profile = config->value<QString>("profile.default");
+ const auto profile = [](){
+ Configuration c;
+ return c.value<QString>("profile.default").value();
+ }();
- app.setConfiguration(config); // app takes ownership of config
app.setup(plugins);
QStringList urls;
@@ -225,7 +203,7 @@ int main(int argc, char **argv)
if(const auto pick = dlg->pickSession())
sessionData = pick.value();
else
- sessionData = Session::fromCommandLine(profile.value(), urls);
+ sessionData = Session::fromCommandLine(profile, urls);
} else if(cmd_session) {
QFile sessionJson(QString::fromStdString(args::get(cmd_session)));
if(sessionJson.open(QIODevice::ReadOnly | QIODevice::Text)) {
@@ -233,7 +211,7 @@ int main(int argc, char **argv)
sessionJson.close();
}
} else {
- sessionData = Session::fromCommandLine(profile.value(), urls);
+ sessionData = Session::fromCommandLine(profile, urls);
}
if(app.isPrimary() || cmd_noRemote) {
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
diff --git a/src/meson.build b/src/meson.build
index d2ff9ad..b263b5f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,11 +1,11 @@
# poi
poi_moc = mod_qt5.preprocess(
moc_headers: ['browser.h',
- 'mainwindow/mainwindow.h', 'mainwindow/menubar.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h',
+ 'mainwindow/mainwindow.h', 'mainwindow/addressbar.h', 'mainwindow/menubar.h', 'mainwindow/widgets/completer.h', 'mainwindow/widgets/urllineedit.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h',
'session/savesessiondialog.h', 'session/sessiondialog.h', 'session/sessionform.h',
'subwindow/subwindow.h', 'subwindow/tabwidget.h',
'webengine/urlinterceptor.h', 'webengine/webpage.h', 'webengine/webview.h'],
- ui_files: ['mainwindow/widgets/searchform.ui', 'session/savesessiondialog.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
+ ui_files: ['mainwindow/addressbar.ui', 'mainwindow/widgets/searchform.ui', 'session/savesessiondialog.ui', 'session/sessiondialog.ui', 'session/sessionform.ui'],
qresources: '../data/resources.qrc',
rcc_extra_arguments: ['--format-version=1'],
dependencies: dep_qt5
@@ -13,15 +13,18 @@ poi_moc = mod_qt5.preprocess(
poi = executable(get_option('poiName'), install: true,
cpp_args: ['-DQAPPLICATION_CLASS=QApplication'],
- dependencies: [dep_qt5, dep_boost, dep_spdlog, dep_SingleApplication, dep_args, optional_deps,
- dep_about, dep_addressbar, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter, dep_webprofile],
+ dependencies: [dep_qt5, dep_spdlog, dep_SingleApplication, dep_args, optional_deps,
+ dep_about, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter, dep_webprofile],
include_directories: [include],
sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, version_h,
'browser.cpp',
'util.cpp', 'util.h',
'mainwindow/mainwindow.cpp',
+ 'mainwindow/addressbar.cpp',
'mainwindow/menubar.cpp',
+ 'mainwindow/widgets/completer.cpp',
+ 'mainwindow/widgets/urllineedit.cpp',
'mainwindow/widgets/dockwidget.cpp',
'mainwindow/widgets/menusearch.cpp',
'mainwindow/widgets/navigationbar.cpp',
diff --git a/src/session/sessiondialog.cpp b/src/session/sessiondialog.cpp
index b734088..301b4b6 100644
--- a/src/session/sessiondialog.cpp
+++ b/src/session/sessiondialog.cpp
@@ -16,6 +16,7 @@
#include <QFileDialog>
#include <QToolButton>
#include <QStyle>
+#include "configuration.h"
SessionDialog::SessionDialog(QWidget *parent)
: QDialog(parent)
@@ -27,7 +28,8 @@ SessionDialog::SessionDialog(QWidget *parent)
auto *browser = qobject_cast<Browser *>(qApp);
Q_CHECK_PTR(browser);
- for(const QString &path : Util::files(browser->configuration("browser.session.path"), { "*.json" })) {
+ Configuration conf;
+ for(const QString &path : Util::files(conf.value<QString>("session.path").value(), { "*.json" })) {
addItem(path);
}
diff --git a/src/subwindow/subwindow.cpp b/src/subwindow/subwindow.cpp
index 31b49b9..869a453 100644
--- a/src/subwindow/subwindow.cpp
+++ b/src/subwindow/subwindow.cpp
@@ -22,7 +22,7 @@
#include "configuration.h"
#include "webprofile.h"
-SubWindow::SubWindow(const Configuration *config, QWidget *parent, Qt::WindowFlags flags)
+SubWindow::SubWindow(QWidget *parent, Qt::WindowFlags flags)
: QMdiSubWindow(parent, flags)
, tabWidget(new TabWidget(this))
{
@@ -34,7 +34,8 @@ SubWindow::SubWindow(const Configuration *config, QWidget *parent, Qt::WindowFla
m_profile = WebProfile::defaultProfile();
- auto *fullScreen_shortcut = new QShortcut(QKeySequence(config->value<QString>("subwindow.shortcuts.fullscreen").value()), this);
+ Configuration config;
+ auto *fullScreen_shortcut = new QShortcut(QKeySequence(config.value<QString>("shortcuts.subwindow.fullscreen").value()), this);
connect(fullScreen_shortcut, &QShortcut::activated, this, [=]() {
auto *w = this->window();
if(w->isFullScreen())
diff --git a/src/subwindow/subwindow.h b/src/subwindow/subwindow.h
index eb7973f..c4f96c0 100644
--- a/src/subwindow/subwindow.h
+++ b/src/subwindow/subwindow.h
@@ -16,7 +16,6 @@
class TabWidget;
class WebView;
class WebProfile;
-class Configuration;
class SubWindow : public QMdiSubWindow
{
Q_OBJECT
@@ -28,7 +27,7 @@ public:
bool refreshLocked = false;
};
- explicit SubWindow(const Configuration *config, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
+ explicit SubWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
~SubWindow() override;
int currentTabIndex() const;
diff --git a/src/webengine/webview.cpp b/src/webengine/webview.cpp
index 5c9ab26..5307291 100644
--- a/src/webengine/webview.cpp
+++ b/src/webengine/webview.cpp
@@ -24,7 +24,7 @@
#include "webprofile.h"
#include "browser.h"
#include "wallet/wallet.h"
-#include "config.h"
+#include "conf.hpp"
inline QAction *historyAction(QWebEngineView *view, const QWebEngineHistoryItem &item)
{