Browse Source

Drop boost dependency

- wrote not-invented-here config file parser and conf class
- spent obscene amount of time plugging in said conf class
master
Aqua-sama 1 month ago
parent
commit
f3a4607d6a
Signed by: Aqua-sama <aqua@iserlohn-fortress.net> GPG Key ID: 81A99984EABC02D1
41 changed files with 645 additions and 655 deletions
  1. +167
    -6
      Kconfig
  2. +0
    -5
      include/browserinterface.h
  3. +2
    -1
      lib/about/aboutdialog.cpp
  4. +0
    -15
      lib/addressbar/meson.build
  5. +0
    -131
      lib/configuration/Kconfig
  6. +78
    -127
      lib/configuration/configuration.cpp
  7. +46
    -90
      lib/configuration/configuration.h
  8. +3
    -11
      lib/configuration/meson.build
  9. +0
    -26
      lib/pluginloader/Kconfig
  10. +1
    -1
      lib/pluginloader/pluginloader.cpp
  11. +4
    -4
      lib/webprofile/webprofilemanager.cpp
  12. +9
    -2
      lib/webprofile/webprofilemanager.h
  13. +59
    -42
      linux/.config
  14. +2
    -2
      linux/makepkg/PKGBUILD
  15. +22
    -11
      meson.build
  16. +0
    -1
      meson_options.txt
  17. +46
    -45
      src/browser.cpp
  18. +0
    -7
      src/browser.h
  19. +32
    -0
      src/conf.hpp.in
  20. +38
    -60
      src/main.cpp
  21. +5
    -3
      src/mainwindow/addressbar.cpp
  22. +1
    -1
      src/mainwindow/addressbar.h
  23. +1
    -1
      src/mainwindow/addressbar.ui
  24. +14
    -15
      src/mainwindow/mainwindow.cpp
  25. +1
    -2
      src/mainwindow/mainwindow.h
  26. +20
    -22
      src/mainwindow/menubar.cpp
  27. +1
    -2
      src/mainwindow/menubar.h
  28. +0
    -0
      src/mainwindow/widgets/completer.cpp
  29. +0
    -0
      src/mainwindow/widgets/completer.h
  30. +10
    -8
      src/mainwindow/widgets/navigationbar.cpp
  31. +1
    -1
      src/mainwindow/widgets/navigationbar.h
  32. +1
    -2
      src/mainwindow/widgets/urllineedit.cpp
  33. +1
    -1
      src/mainwindow/widgets/urllineedit.h
  34. +7
    -4
      src/meson.build
  35. +3
    -1
      src/session/sessiondialog.cpp
  36. +3
    -2
      src/subwindow/subwindow.cpp
  37. +1
    -2
      src/subwindow/subwindow.h
  38. +1
    -1
      src/webengine/webview.cpp
  39. +54
    -0
      test/conf/main.cpp
  40. +6
    -0
      test/conf/meson.build
  41. +5
    -0
      test/conf/smolbote.cfg

+ 167
- 6
Kconfig View File

@@ -5,19 +5,180 @@ menu "Application"
config POI_ICON
string "Path to icon"
default ":/icons/poi.svg"
config POI_CFG_PATH
string "Configuration location"
default "~/.config/smolbote/smolbote.cfg"
endmenu

source 'lib/configuration/Kconfig'
menu "Keyboard shortcuts"
comment "Main Window shortcuts"
config shortcuts.session.save
string "Save Session shortcut"
default "Ctrl+S,S"
config shortcuts.session.open
string "Load Session shortcut"
default "Ctrl+S,O"
config shortcuts.window.newgroup
string "New Group shortcut"
default "Ctrl+G"
config shortcuts.window.newwindow
string "New Window shortcut"
default "Ctrl+N"
config shortcuts.window.about
string "Show About Dialog"
default "Ctrl+H"
config shortcuts.window.quit
string "Quit shortcut"
default "Ctrl+Q"
config shortcuts.window.search
string "Show or hide search box"
default "F3"
config shortcuts.window.bookmarks.show
string "Show bookmarks dialog in this window"
default "Ctrl+B"
config shortcuts.window.downloads.show
string "Show downloads dialog in this window"
default "Ctrl+D"

# Plugin loading
source 'lib/pluginloader/Kconfig'
comment "Navigation Bar shortcuts"
config shortcuts.navigation.back
string "Go back in history"
default "Ctrl+Left"
config shortcuts.navigation.backmenu
string "Show Back history menu"
default "Ctrl+Down"
config shortcuts.navigation.forward
string "Go forward in history"
default "Ctrl+Right"
config shortcuts.navigation.forwardmenu
string "Show Forward history menu"
default "Ctrl+Up"
config shortcuts.navigation.refresh
string "Refresh the page"
default "F5"
config shortcuts.navigation.reload
string "Reload the page"
default "Ctrl+F5"
config shortcuts.navigation.home
string "Load homepage"
default "Ctrl+Home"

comment "Address Bar shortcuts"
config shortcuts.address.focus
string "Focus the Address Bar"
default "F4"
config shortcuts.address.menu
string "Show Address Bar menu"
default "F2"

comment "Subwindow shortcuts"
config shortcuts.subwindow.menu
string "Subwindow context menu"
default "F1"
config shortcuts.subwindow.tile
string "Tile subwindows"
default "F9"
config shortcuts.subwindow.cascade
string "Cascade subwindow"
default "F10"
config shortcuts.subwindow.fullscreen
string "Make current subwindow fullscreen"
default "F11"
config shortcuts.subwindow.newtab
string "Create new tab"
default "Ctrl+T"
config shortcuts.subwindow.closetab
string "Close current tab"
default "Ctrl+X"
config shortcuts.subwindow.restoretab
string "Restore last closed tab"
default "Ctrl+Shift+T"
config shortcuts.subwindow.tableft
string "Switch to the tab on the left"
default "Ctrl+O"
config shortcuts.subwindow.movetableft
string "Move tab to the left"
default "Ctrl+Shift+O"
config shortcuts.subwindow.tabright
string "Switch to the tab on the right"
default "Ctrl+P"
config shortcuts.subwindow.movetabright
string "Move tab to the right"
default "Ctrl+Shift+P"

endmenu

menu "Main Window"
config mainwindow.title
string "Main window title"
default "smolbote"
config mainwindow.width
int "Main window width"
default 1280
config mainwindow.height
int "Main window height"
default 720
endmenu

menu "Profile Settings"
config profile.path
string "Profile load location"
default "~/.config/smolbote/profiles.d"
config profile.default
string "Default profile"
default ""
config profile.search
string "Search engine"
default "https://duckduckgo.com/?q=%1&ia=web"
config profile.homepage
string "Homepage"
default "about:blank"
config profile.newtab
string "New tab page"
default "about:blank"
endmenu

config USEPLUGINS
bool "Enable plugins"
default y

menu "Plugin Settings"
depends on USEPLUGINS
config plugins.path
string "Plugin load location"
default "~/.config/smolbote/plugins.d"
choice PLUGIN_SIGNATURE_CHECK
bool "Plugin Signature enforcement"
default PLUGIN_SIGNATURE_CHECKED
config PLUGIN_SIGNATURE_IGNORED
bool "Don't check plugin signatures"
config PLUGIN_SIGNATURE_CHECKED
bool "Don't load plugins with invalid signatures"
config PLUGIN_SIGNATURE_ENFORCED
bool "Only load plugins with valid signatures"
endchoice
config PLUGIN_SIGNATURE_HASH
string "Hashing algorithm used by the signature"
default "SHA256"
endmenu

comment "Default paths"
config filter.path
string "Host filter path"
default "~/.config/smolbote/hosts.d"
config bookmarks.path
string "Bookmarks location"
default "~/.config/smolbote/bookmarks.xbel"
config downloads.path
string "Downloads location"
default "~/Downloads"
config session.path
string "Session location"
default "~/.config/smolbote/session.d"

config USEPLASMA
bool "Enable KDE Frameworks integration"
default n
select SHOW_KDE_INTEGRATION
help
This is a help message

menu "KDE Integration"
depends on USEPLASMA

+ 0
- 5
include/browserinterface.h View File

@@ -14,11 +14,6 @@ class BrowserInterface
public:
virtual ~BrowserInterface() = default;

// configuration access
virtual const QStringList configurationOptions() const = 0;
virtual const QString configuration(const QString &key) const = 0;
virtual void setConfiguration(const QString &key, const QString &value) = 0;

// profile access
virtual const QList<QPair<QString, Profile *>> profileList() const = 0;
virtual QPair<QString, Profile *> loadProfile(const QString &id, bool isOffTheRecord = true) = 0;

+ 2
- 1
lib/about/aboutdialog.cpp View File

@@ -52,7 +52,8 @@ AboutDialog::AboutDialog(QWidget *parent)
"<p>Compiled with " compiler "</p>"
"<p>Libraries: <ul>"
"<li><a href='https://www.qt.io/'>Qt5</a> " QT_VERSION_STR "</li>"
"<li><a href='https://www.boost.org/'>Boost</a></li>"
"<li>spdlog</li>"
"<li><a href='https://github.com/Taywee/args'>args.hxx</a></li>"
"<li><a href='https://github.com/itay-grudev/SingleApplication'>SingleApplication</a></li>"
#ifdef CONFIG_USEPLASMA
"<li><a href='https://community.kde.org/Frameworks'>KDE Frameworks</a></li>"

+ 0
- 15
lib/addressbar/meson.build View File

@@ -1,15 +0,0 @@
addressbar_inc = include_directories('.')
addressbar_moc = mod_qt5.preprocess(
moc_headers: ['addressbar.h', 'completer.h', 'urllineedit.h'],
ui_files: ['addressbar.ui'],
dependencies: dep_qt5
)

addressbar_lib = static_library('addressbar', ['addressbar.cpp', 'completer.cpp', 'urllineedit.cpp', addressbar_moc],
dependencies: dep_qt5,
)

dep_addressbar = declare_dependency(
include_directories: addressbar_inc,
link_with: addressbar_lib
)

+ 0
- 131
lib/configuration/Kconfig View File

@@ -1,131 +0,0 @@
menu "Configuration defaults"
config PATH_CONFIG
string "Configuration location"
default "~/.config/smolbote/smolbote.cfg"
config PATH_FILTER
string "Host filter path"
default "~/.config/smolbote/hosts.d"
config PATH_PLUGINS
string "Plugin load location"
default "~/.config/smolbote/plugins.d"
config PATH_PROFILES
string "Profile load location"
default "~/.config/smolbote/profiles.d"
config PATH_BOOKMARKS
string "Bookmarks location"
default "~/.config/smolbote/bookmarks.xbel"
config PATH_DOWNLOADS
string "Downloads location"
default "~/Downloads"
config PATH_SESSION
string "Session location"
default "~/.config/smolbote/session.d"
endmenu

menu "Keyboard shortcuts"
comment "Main Window shortcuts"
config SHORTCUT_WINDOW_NEWGROUP
string "New Group shortcut"
default "Ctrl+G"
config SHORTCUT_WINDOW_NEWWINDOW
string "New Window shortcut"
default "Ctrl+N"
config SHORTCUT_WINDOW_ABOUT
string "Show About Dialog"
default "Ctrl+H"
config SHORTCUT_WINDOW_QUIT
string "Quit shortcut"
default "Ctrl+Q"

config SHORTCUT_WINDOW_SEARCH
string "Show or hide search box"
default "F3"

config SHORTCUT_WINDOW_BOOKMARKS
string "Show bookmarks dialog in this window"
default "Ctrl+B"
config SHORTCUT_WINDOW_DOWNLOADS
string "Show downloads dialog in this window"
default "Ctrl+D"

comment "Navigation Bar shortcuts"
config SHORTCUT_NAVIGATION_BACK
string "Go back in history"
default "Ctrl+Left"
config SHORTCUT_NAVIGATION_BACKMENU
string "Show Back history menu"
default "Ctrl+Down"
config SHORTCUT_NAVIGATION_FORWARD
string "Go forward in history"
default "Ctrl+Right"
config SHORTCUT_NAVIGATION_FORWARDMENU
string "Show Forward history menu"
default "Ctrl+Up"
config SHORTCUT_NAVIGATION_REFRESH
string "Refresh the page"
default "F5"
config SHORTCUT_NAVIGATION_RELOAD
string "Reload the page"
default "Ctrl+F5"
config SHORTCUT_NAVIGATION_HOME
string "Load homepage"
default "Ctrl+Home"

comment "Address Bar shortcuts"
config SHORTCUT_ADDRESS_FOCUS
string "Focus the Address Bar"
default "F4"
config SHORTCUT_ADDRESS_MENU
string "Show Address Bar menu"
default "F2"

comment "Subwindow shortcuts"
config SHORTCUT_SUBWINDOW_MENU
string "Subwindow context menu"
default "F1"
config SHORTCUT_SUBWINDOW_TILE
string "Tile subwindows"
default "F9"
config SHORTCUT_SUBWINDOW_CASCADE
string "Cascade subwindow"
default "F10"
config SHORTCUT_SUBWINDOW_FULLSCREEN
string "Make current subwindow fullscreen"
default "F11"

config SHORTCUT_SUBWINDOW_NEWTAB
string "Create new tab"
default "Ctrl+T"
config SHORTCUT_SUBWINDOW_CLOSETAB
string "Close current tab"
default "Ctrl+X"
config SHORTCUT_SUBWINDOW_TABLEFT
string "Switch to the tab on the left"
default "Ctrl+O"
config SHORTCUT_SUBWINDOW_MOVETABLEFT
string "Move tab to the left"
default "Ctrl+Shift+O"
config SHORTCUT_SUBWINDOW_TABRIGHT
string "Switch to the tab on the right"
default "Ctrl+P"
config SHORTCUT_SUBWINDOW_MOVETABRIGHT
string "Move tab to the right"
default "Ctrl+Shift+P"

endmenu

menu "Profile defaults"
config PROFILE_DEFAULT
string "Default profile"
default ""
config PROFILE_DEFAULT_SEARCH
string "Search engine"
default "https://duckduckgo.com/?q=%1&ia=web"
config PROFILE_DEFAULT_HOMEPAGE
string "Homepage"
default "about:blank"
config PROFILE_DEFAULT_NEWTAB
string "New tab page"
default "about:blank"
endmenu


+ 78
- 127
lib/configuration/configuration.cpp View File

@@ -7,146 +7,97 @@
*/

#include "configuration.h"
#include <QStandardPaths>
#include <fstream>
#include <boost/algorithm/string/predicate.hpp>
#include <sstream>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <QCoreApplication>
#include "config.h"
#include <QStandardPaths>

namespace po = boost::program_options;
static std::unique_ptr<Configuration> s_conf;

inline std::string defaultUserConfigLocation()
inline void strip(std::string &value)
{
#ifdef CONFIG_PATH_CONFIG
return CONFIG_PATH_CONFIG;
#else
// try to locate an existing config
QString path = QStandardPaths::locate(QStandardPaths::ConfigLocation, "smolbote/smolbote.cfg");
value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
}

// 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
Configuration::Configuration()
: use_global(true)
{
if(!s_conf)
throw new std::runtime_error("Trying to use default Configuration, but none has been set!");
}

Configuration::Configuration(int argc, char **argv, const std::string &path, QObject *parent)
: QObject(parent)
, m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString())
Configuration::Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept
: m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString())
{
configuration_desc.add_options()
("browser.stylesheet", po::value<std::string>())
("browser.iconTheme", po::value<std::string>(), "Icon theme")
("browser.locale", po::value<std::string>(), "Set Qt localization.")
("browser.translation", po::value<std::string>(), "Set application localization.")

// sessions
("browser.session.path", po::value<std::string>()->default_value(CONFIG_PATH_SESSION))

#ifdef CONFIG_USEBREAKPAD
("browser.crash.path", po::value<std::string>()->default_value(CONFIG_PATH_CRASHDUMP))
("browser.crash.handler", po::value<std::string>()->default_value(CONFIG_PATH_CRASHHANDLER))
#endif

// main window ui
("mainwindow.height", po::value<int>()->default_value(720))
("mainwindow.width", po::value<int>()->default_value(1280))
("mainwindow.maximized", po::value<bool>()->default_value(true))
("mainwindow.title", po::value<std::string>()->default_value(CONFIG_POI_NAME))

// main window shortcuts
("mainwindow.shortcuts.saveSession", po::value<std::string>()->default_value("Ctrl+S,S"))
("mainwindow.shortcuts.openSession", po::value<std::string>()->default_value("Ctrl+S,O"))

("mainwindow.shortcuts.newGroup", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_NEWGROUP))
("mainwindow.shortcuts.newWindow", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_NEWWINDOW))

("mainwindow.shortcuts.about", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_ABOUT))
("mainwindow.shortcuts.quit", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_QUIT))

("mainwindow.shortcuts.search", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_SEARCH))
("mainwindow.shortcuts.tileWindows", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TILE))
("mainwindow.shortcuts.cascadeWindows", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_CASCADE))

// navigation
("navigation.movable", po::value<bool>()->default_value(false))
("navigation.shortcuts.back", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_BACK))
("navigation.shortcuts.backMenu", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_BACKMENU))
("navigation.shortcuts.forward", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_FORWARD))
("navigation.shortcuts.forwardMenu", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_FORWARDMENU))
("navigation.shortcuts.refresh", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_REFRESH))
("navigation.shortcuts.reload", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_RELOAD))
("navigation.shortcuts.home", po::value<std::string>()->default_value(CONFIG_SHORTCUT_NAVIGATION_HOME))

// address bar
("addressbar.shortcuts.focus", po::value<std::string>()->default_value(CONFIG_SHORTCUT_ADDRESS_FOCUS))
("addressbar.shortcuts.menu", po::value<std::string>()->default_value(CONFIG_SHORTCUT_ADDRESS_MENU))

// subwindow
("subwindow.shortcuts.menu", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MENU))
("subwindow.shortcuts.new", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_NEWTAB))
("subwindow.shortcuts.close", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_CLOSETAB))
("subwindow.shortcuts.restoreTab", po::value<std::string>()->default_value("Ctrl+Shift+T"))
("subwindow.shortcuts.left", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TABLEFT))
("subwindow.shortcuts.moveLeft", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MOVETABLEFT))
("subwindow.shortcuts.right", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TABRIGHT))
("subwindow.shortcuts.moveRight", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MOVETABRIGHT))
("subwindow.shortcuts.fullscreen", po::value<std::string>()->default_value(CONFIG_SHORTCUT_SUBWINDOW_FULLSCREEN))

// Filter settings
("filter.hosts", po::value<std::string>()->default_value(CONFIG_PATH_FILTER))
("filter.adblock", po::value<std::string>())
("filter.header", po::value<std::vector<std::string>>())
// ("filter.cookies.block.all", po::value<bool>()->default_value(false))
// ("filter.cookies.block.thirdParty", po::value<bool>()->default_value(true))
// ("filter.cookies.path", po::value<std::string>()->default_value("~/.config/smolbote/cookies.d"))

// Plugin settings
("plugins.path", po::value<std::string>()->default_value(CONFIG_PATH_PLUGINS))

// Profile settings
// default profile name the browser should use; "" is off-the-record
("profile.default", po::value<std::string>()->default_value(CONFIG_PROFILE_DEFAULT))
("profile.path", po::value<std::string>()->default_value(CONFIG_PATH_PROFILES))
("profile.search", po::value<std::string>()->default_value(CONFIG_PROFILE_DEFAULT_SEARCH))
("profile.homepage", po::value<std::string>()->default_value(CONFIG_PROFILE_DEFAULT_HOMEPAGE))
("profile.newtab", po::value<std::string>()->default_value(CONFIG_PROFILE_DEFAULT_NEWTAB))

// Bookmark settings
("bookmarks.path", po::value<std::string>()->default_value(CONFIG_PATH_BOOKMARKS))
("bookmarks.shortcut", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_BOOKMARKS))

// Downloads settings
("downloads.path", po::value<std::string>()->default_value(CONFIG_PATH_DOWNLOADS))
("downloads.shortcut", po::value<std::string>()->default_value(CONFIG_SHORTCUT_WINDOW_DOWNLOADS))
;

// po::store will only overwrite values that are default, so:
// 1. parse command line
{
auto cmd = po::command_line_parser(argc, argv);
cmd.allow_unregistered();
cmd.options(configuration_desc);
po::store(cmd.run(), vm);
}
// 2. parse config file
{
std::ifstream f(path, std::ifstream::in);
// parse_config_file(file, options_description, allow_unregistered)
po::store(po::parse_config_file(f, configuration_desc, true), vm);
}
for(const auto &i : l) {
insert_or_assign(i.first, i.second);
}
}

QHash<QString, QString> Configuration::section(const std::string &prefix) const
void Configuration::read(std::basic_istream<char> &input)
{
QHash<QString, QString> v;
for(auto &s : configuration_desc.options()) {
if(boost::starts_with(s->long_name(), prefix)) {
v[s->long_name().c_str()] = QString::fromStdString(value<std::string>(s->long_name().c_str()).value());
std::string line, key, value;
std::istringstream is_line;

while(std::getline(input, line)) {
if(line[0] == '#' || line.length() == 0)
continue;

is_line.clear();
is_line.str(line);

if(std::getline(is_line, key, '=')) {
is_line >> value;

strip(key);
strip(value);

if(this->count(key) == 0) {
// no type has been specified for this key, assuming std::string
insert(std::make_pair(key, value));
continue;
}

auto v = at(key);
if(std::holds_alternative<std::string>(v)) {
at(key) = value;
} else if(std::holds_alternative<int>(v)) {
at(key) = std::stoi(value);
} else if(std::holds_alternative<bool>(v)) {
at(key) = (value == "true");
}

}
}
}


return v;
void Configuration::move_global(std::unique_ptr<Configuration> &&conf)
{
s_conf = std::move(conf);
}

Configuration* Configuration::instance()
{
return s_conf.get();
}

void setShortcut(QAction *action, const char *name)
{
if(!s_conf)
throw new std::runtime_error("Trying to set a shortcut, but no configuration has been set!");

if(const auto shortcutText = s_conf->value<QString>(name)) {
const QString tooltip = action->toolTip();
action->setShortcut(QKeySequence::fromString(shortcutText.value()));
action->setToolTip(QString("%1 (%2)").arg(tooltip, shortcutText.value()));
}
#ifdef QT_DEBUG
else {
std::cout << "fixme: setShortcut called for " << name << ", but no such value exists!" << std::endl;
}
#endif
}

+ 46
- 90
lib/configuration/configuration.h View File

@@ -9,121 +9,77 @@
#ifndef SMOLBOTE_CONFIGURATION_H
#define SMOLBOTE_CONFIGURATION_H

#include <QAction>
#include <QString>
#include <QStringList>
#include <QVariant>
#include <boost/program_options.hpp>
#include <optional>
#include <string>
#include <vector>
#include <unordered_map>
#include <variant>
#include <initializer_list>
#include <memory>
#include <QAction>
#include <QString>

class Configuration : public QObject
typedef std::variant<std::string, int, bool> conf_value_t;

class [[clang::consumable(unconsumed)]] Configuration : private std::unordered_map<std::string, conf_value_t>
{
Q_OBJECT

public:
explicit Configuration(int argc, char** argv, const std::string &path, QObject *parent = nullptr);
[[clang::return_typestate(unconsumed)]]
explicit Configuration();

[[clang::return_typestate(unconsumed)]]
explicit Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept;

explicit Configuration(Configuration &&other [[clang::param_typestate(unconsumed)]]) = default;

~Configuration() = default;

bool exists(const char *path)
{
return vm.count(path) ? true : false;
}
[[clang::callable_when(unconsumed)]]
void read(std::basic_istream<char> &input);

template <typename T>
std::optional<T> value(const char *path) const
[[clang::callable_when(unconsumed)]] std::optional<T> value(const char *path) const
{
// if setting doesn't exist, we crash
// in debug builds, check if setting exists
if(vm.count(path) == 0) {
if(use_global)
return instance()->value<T>(path);
if(this->count(path) == 0) {
return std::nullopt;
}

// path is guaranteed to exist, so using vm[path] is safe

if constexpr(std::is_same_v<T, QStringList>) {
QStringList r;
for(const std::string &item : vm[path].as<std::vector<std::string>>()) {
r.append(QString::fromStdString(item));
}
return std::optional<QStringList>(r);

} else if constexpr(std::is_same_v<T, std::string> || std::is_same_v<T, QString>) {

if(vm[path].value().type() == typeid(int)) {
if constexpr(std::is_same_v<T, std::string>)
return std::optional<std::string>(std::to_string(vm[path].as<int>()));
else if constexpr(std::is_same_v<T, QString>)
return std::optional<QString>(QString::number(vm[path].as<int>()));
}

if(vm[path].value().type() == typeid(bool)) {
return std::optional<T>(vm[path].as<bool>() ? "true" : "false");
}

std::string r = vm[path].as<std::string>();
// path is guaranteed to exist
const auto value = at(path);

// check if it's a path
if(r.front() == '~') {
if constexpr(std::is_same_v<T, QString> || std::is_same_v<T, std::string>) {
auto r = std::get<std::string>(value);
if(r.front() == '~')
r.replace(0, 1, m_homePath);
}

if constexpr(std::is_same_v<T, std::string>)
return std::optional<std::string>(r);
else if constexpr(std::is_same_v<T, QString>)
return std::optional<QString>(QString::fromStdString(r));
if constexpr(std::is_same_v<T, QString>)
return std::make_optional(QString::fromStdString(r));
else
return std::make_optional(r);

} else
return std::optional<T>(vm[path].as<T>());
}

template <typename T>
void setValue(const char *path, const T &value)
{
if(vm.count(path) == 0) {
qWarning("value(%s) does not exist", path);
}

vm.at(path).value() = value;

emit settingChanged(path, value);
}
} else if constexpr(std::is_same_v<T, QStringList>) {
return std::make_optional(QString::fromStdString(std::get<std::string>(value)).split(';'));

void setShortcut(QAction *action, const char *name) const
{
Q_CHECK_PTR(action);

const auto shortcutText = this->value<QString>(name);
if(shortcutText) {
const QString tooltip = action->toolTip();
action->setShortcut(QKeySequence::fromString(shortcutText.value()));
action->setToolTip(QString("%1 (%2)").arg(tooltip, shortcutText.value()));

connect(this, &Configuration::settingChanged, action, [=](const std::string &path, const QString &value) {
if(path == name) {
action->setShortcut(QKeySequence::fromString(value));
action->setToolTip(QString("%1 (%2)").arg(tooltip, value));
}
});
}
}

QHash<QString, QString> section(const std::string &prefix) const;
const boost::program_options::options_description& description() const
{
return configuration_desc;
}
} else if (std::holds_alternative<T>(value)) {
return std::optional<T>(std::get<T>(value));
} else
return std::nullopt;
} // std::optional<T> value(path) const

signals:
void settingChanged(const std::string &path, const QString &value);
static void move_global(std::unique_ptr<Configuration> &&conf);

private:
boost::program_options::options_description configuration_desc;
boost::program_options::variables_map vm;
static Configuration *instance();

const std::string m_homePath;
const bool use_global = false;
};

void setShortcut(QAction *action, const char *name);

#endif // SMOLBOTE_CONFIGURATION_H

+ 3
- 11
lib/configuration/meson.build View File

@@ -1,13 +1,5 @@
configuration_moc = mod_qt5.preprocess(
moc_headers: ['configuration.h'],
dependencies: dep_qt5
)

configuration_lib = static_library('configuration', ['configuration.cpp', configuration_moc],
dependencies: [dep_boost, dep_qt5, autogen_config]
)

dep_configuration = declare_dependency(
include_directories: include_directories('.'),
link_with: configuration_lib
include_directories: include_directories('.'),
link_with: static_library('configuration', ['configuration.cpp'], dependencies: dep_qt5)
)


+ 0
- 26
lib/pluginloader/Kconfig View File

@@ -1,26 +0,0 @@
config USEPLUGINS
bool "Enable plugins"
default y

menu "Plugin Settings"
depends on USEPLUGINS

choice PLUGIN_SIGNATURE_CHECK
bool "Plugin Signature enforcement"
default PLUGIN_SIGNATURE_CHECKED

config PLUGIN_SIGNATURE_IGNORED
bool "Don't check plugin signatures"

config PLUGIN_SIGNATURE_CHECKED
bool "Don't load plugins with invalid signatures"

config PLUGIN_SIGNATURE_ENFORCED
bool "Only load plugins with valid signatures"

endchoice

config PLUGIN_SIGNATURE_HASH
string "Hashing algorithm used by the signature"
default "SHA256"
endmenu

+ 1
- 1
lib/pluginloader/pluginloader.cpp View File

@@ -56,7 +56,7 @@ PluginLoader::VerifyState PluginLoader::verify(const char *hashName) const
if(rc != 1)
return SignatureComputeFailed;
}
delete buf;
delete[] buf;
plugin.close();

// read signature into DigestVerifyFinal

+ 4
- 4
lib/webprofile/webprofilemanager.cpp View File

@@ -11,7 +11,7 @@
#include <QFileInfo>
#include <QWebEngineSettings>

WebProfileManager::WebProfileManager(const QHash<QString, QString> &profileSection, QObject *parent)
WebProfileManager::WebProfileManager(const ProfileDefault_t &profileSection, QObject *parent)
: QObject(parent)
, defaults(profileSection)
{
@@ -62,17 +62,17 @@ WebProfile *WebProfileManager::profile(const QString &id, const QString &path, b
profile.settings->setValue("name", name);
});

profile.ptr->setSearch(profile.value("search", defaults.value("profile.search")).toString());
profile.ptr->setSearch(profile.value("search", defaults.search).toString());
connect(profile.ptr, &WebProfile::searchChanged, profile.settings, [profile](const QString &url) {
profile.settings->setValue("search", url);
});

profile.ptr->setHomepage(profile.value("homepage", defaults.value("profile.homepage")).toUrl());
profile.ptr->setHomepage(profile.value("homepage", defaults.homepage).toUrl());
connect(profile.ptr, &WebProfile::homepageChanged, profile.settings, [profile](const QUrl &url) {
profile.settings->setValue("homepage", url);
});

profile.ptr->setNewtab(profile.value("newtab", defaults.value("profile.newtab")).toUrl());
profile.ptr->setNewtab(profile.value("newtab", defaults.newtab).toUrl());
connect(profile.ptr, &WebProfile::newtabChanged, profile.settings, [profile](const QUrl &url) {
profile.settings->setValue("newtab", url);
});

+ 9
- 2
lib/webprofile/webprofilemanager.h View File

@@ -18,11 +18,18 @@
#include <QSettings>
#include <functional>

struct ProfileDefault_t
{
QString search;
QString homepage;
QString newtab;
};

class WebProfileManager : public QObject
{
Q_OBJECT
public:
explicit WebProfileManager(const QHash<QString, QString> &profileSection, QObject *parent);
explicit WebProfileManager(const ProfileDefault_t &profileSection, QObject *parent);
~WebProfileManager();

/** Create a profile with specified id
@@ -72,7 +79,7 @@ private:
};

QMap<QString, Profile> profiles;
const QHash<QString, QString> defaults;
const ProfileDefault_t defaults;
};

#endif // SMOLBOTE_PROFILEMANAGER_H

+ 59
- 42
linux/.config View File

@@ -5,17 +5,8 @@
#
CONFIG_POI_NAME="smolbote"
CONFIG_POI_ICON=":/icon.svg"

#
# Configuration defaults
#
CONFIG_PATH_CONFIG="~/.config/smolbote/smolbote.cfg"
CONFIG_PATH_FILTER="~/.config/smolbote/hosts.d"
CONFIG_PATH_PLUGINS="~/.config/smolbote/plugins.d"
CONFIG_PATH_PROFILES="~/.config/smolbote/profiles.d"
CONFIG_PATH_BOOKMARKS="~/.config/smolbote/bookmarks.xbel"
CONFIG_PATH_DOWNLOADS="~/Downloads"
CONFIG_PATH_SESSION="~/.config/smolbote/session.d"
CONFIG_POI_CFG_PATH="~/.config/smolbote/smolbote.cfg"
# end of Application

#
# Keyboard shortcuts
@@ -24,61 +15,86 @@ CONFIG_PATH_SESSION="~/.config/smolbote/session.d"
#
# Main Window shortcuts
#
CONFIG_SHORTCUT_WINDOW_NEWGROUP="Ctrl+G"
CONFIG_SHORTCUT_WINDOW_NEWWINDOW="Ctrl+N"
CONFIG_SHORTCUT_WINDOW_ABOUT="F1"
CONFIG_SHORTCUT_WINDOW_QUIT="Ctrl+Q"
CONFIG_SHORTCUT_WINDOW_SEARCH="F3"
CONFIG_SHORTCUT_WINDOW_BOOKMARKS="Ctrl+B"
CONFIG_SHORTCUT_WINDOW_DOWNLOADS="Ctrl+D"
CONFIG_shortcuts.session.save="Ctrl+S,S"
CONFIG_shortcuts.session.open="Ctrl+S,O"
CONFIG_shortcuts.window.newgroup="Ctrl+G"
CONFIG_shortcuts.window.newwindow="Ctrl+N"
CONFIG_shortcuts.window.about="Ctrl+H"
CONFIG_shortcuts.window.quit="Ctrl+Q"
CONFIG_shortcuts.window.search="F3"
CONFIG_shortcuts.window.bookmarks.show="Ctrl+B"
CONFIG_shortcuts.window.downloads.show="Ctrl+D"

#
# Navigation Bar shortcuts
#
CONFIG_SHORTCUT_NAVIGATION_BACK="Ctrl+Left"
CONFIG_SHORTCUT_NAVIGATION_BACKMENU="Ctrl+Down"
CONFIG_SHORTCUT_NAVIGATION_FORWARD="Ctrl+Right"
CONFIG_SHORTCUT_NAVIGATION_FORWARDMENU="Ctrl+Up"
CONFIG_SHORTCUT_NAVIGATION_REFRESH="F5"
CONFIG_SHORTCUT_NAVIGATION_RELOAD="Ctrl+F5"
CONFIG_SHORTCUT_NAVIGATION_HOME="Ctrl+Home"
CONFIG_shortcuts.navigation.back="Ctrl+Left"
CONFIG_shortcuts.navigation.backmenu="Ctrl+Down"
CONFIG_shortcuts.navigation.forward="Ctrl+Right"
CONFIG_shortcuts.navigation.forwardmenu="Ctrl+Up"
CONFIG_shortcuts.navigation.refresh="F5"
CONFIG_shortcuts.navigation.reload="Ctrl+F5"
CONFIG_shortcuts.navigation.home="Ctrl+Home"

#
# Address Bar shortcuts
#
CONFIG_SHORTCUT_ADDRESS_FOCUS="F4"
CONFIG_SHORTCUT_ADDRESS_MENU="F2"
CONFIG_shortcuts.address.focus="F4"
CONFIG_shortcuts.address.menu="F2"

#
# Subwindow shortcuts
#
CONFIG_SHORTCUT_SUBWINDOW_MENU="Ctrl+M"
CONFIG_SHORTCUT_SUBWINDOW_TILE="F9"
CONFIG_SHORTCUT_SUBWINDOW_CASCADE="F10"
CONFIG_SHORTCUT_SUBWINDOW_FULLSCREEN="F11"
CONFIG_SHORTCUT_SUBWINDOW_NEWTAB="Ctrl+T"
CONFIG_SHORTCUT_SUBWINDOW_CLOSETAB="Ctrl+X"
CONFIG_SHORTCUT_SUBWINDOW_TABLEFT="Ctrl+O"
CONFIG_SHORTCUT_SUBWINDOW_MOVETABLEFT="Ctrl+Shift+O"
CONFIG_SHORTCUT_SUBWINDOW_TABRIGHT="Ctrl+P"
CONFIG_SHORTCUT_SUBWINDOW_MOVETABRIGHT="Ctrl+Shift+P"
CONFIG_shortcuts.subwindow.menu="F1"
CONFIG_shortcuts.subwindow.tile="F9"
CONFIG_shortcuts.subwindow.cascade="F10"
CONFIG_shortcuts.subwindow.fullscreen="F11"
CONFIG_shortcuts.subwindow.newtab="Ctrl+T"
CONFIG_shortcuts.subwindow.closetab="Ctrl+X"
CONFIG_shortcuts.subwindow.restoretab="Ctrl+Shift+T"
CONFIG_shortcuts.subwindow.tableft="Ctrl+O"
CONFIG_shortcuts.subwindow.movetableft="Ctrl+Shift+O"
CONFIG_shortcuts.subwindow.tabright="Ctrl+P"
CONFIG_shortcuts.subwindow.movetabright="Ctrl+Shift+P"
# end of Keyboard shortcuts

#
# Main Window
#
CONFIG_mainwindow.title="smolbote"
CONFIG_mainwindow.width=1280
CONFIG_mainwindow.height=720
# end of Main Window

#
# Profile defaults
# Profile Settings
#
CONFIG_PROFILE_DEFAULT=""
CONFIG_PROFILE_DEFAULT_SEARCH="https://duckduckgo.com/?q=%1&ia=web"
CONFIG_PROFILE_DEFAULT_HOMEPAGE="about:blank"
CONFIG_PROFILE_DEFAULT_NEWTAB="about:blank"
CONFIG_profile.path="~/.config/smolbote/profiles.d"
CONFIG_profile.default=""
CONFIG_profile.search="https://duckduckgo.com/?q=%1&ia=web"
CONFIG_profile.homepage="about:blank"
CONFIG_profile.newtab="about:blank"
# end of Profile Settings

CONFIG_USEPLUGINS=y

#
# Plugin Settings
#
CONFIG_plugins.path="~/.config/smolbote/plugins.d"
# CONFIG_PLUGIN_SIGNATURE_IGNORED is not set
CONFIG_PLUGIN_SIGNATURE_CHECKED=y
# CONFIG_PLUGIN_SIGNATURE_ENFORCED is not set
CONFIG_PLUGIN_SIGNATURE_HASH="SHA256"
# end of Plugin Settings

#
# Default paths
#
CONFIG_filter.path="~/.config/smolbote/hosts.d"
CONFIG_bookmarks.path="~/.config/smolbote/bookmarks.xbel"
CONFIG_downloads.path="~/Downloads"
CONFIG_session.path="~/.config/smolbote/session.d"
# CONFIG_USEPLASMA is not set
# CONFIG_USEBREAKPAD is not set

@@ -86,3 +102,4 @@ CONFIG_PLUGIN_SIGNATURE_HASH="SHA256"
# Workarounds
#
CONFIG_QTBUG_65223=y
# end of Workarounds

+ 2
- 2
linux/makepkg/PKGBUILD View File

@@ -12,9 +12,9 @@ install="smolbote.install"
arch=('x86_64')
license=('GPL3')

depends=('qt5-webengine>=5.11.0' 'boost-libs>=1.66.0' 'spdlog')
depends=('qt5-webengine>=5.11.0' 'spdlog')
optdepends=('firejail: launch a sandboxed instance')
makedepends=('git' 'meson' 'boost' 'python-kconfiglib' 'openssl' 'qt5-tools' 'scdoc')
makedepends=('git' 'meson' 'python-kconfiglib' 'openssl' 'qt5-tools' 'scdoc')

# this is the central repository
source=("git+https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote.git"

+ 22
- 11
meson.build View File

@@ -6,8 +6,24 @@ project('smolbote', 'cpp',
)

kconfig = import('unstable-kconfig')
cdata = configuration_data(kconfig.load(host_machine.system() + '/.config'))
config_h = configure_file(output: 'config.h', configuration: cdata)
kconf = kconfig.load(host_machine.system() + '/.config')

cdata = configuration_data(kconf)

conf_init_list = '\n'
foreach key, value : kconf
n = key.split('_')[1]
if n.contains('.')
if n.endswith('.width') or n.endswith('.height')
conf_init_list += ' { "@0@", @1@ },\n'.format(n.to_lower(), value.to_int())
else
conf_init_list += ' { "@0@", std::string(@1@) },\n'.format(n.to_lower(), value)
endif
endif
endforeach
cdata.set('conf_init_list', conf_init_list)

configure_file(input: 'src/conf.hpp.in', output: 'conf.hpp', configuration: cdata)

version_h = vcs_tag(
command: [find_program('git').path(), 'describe', '--long', '--abbrev=40'],
@@ -16,11 +32,6 @@ version_h = vcs_tag(
output: 'version.h'
)

autogen_config = declare_dependency(
include_directories: include_directories('.'),
sources: [config_h]
)

# add -DQT_NO_DEBUG to non-debug builds
if not get_option('debug')
add_project_arguments('-DQT_NO_DEBUG', language: 'cpp')
@@ -37,14 +48,13 @@ add_project_arguments(cxx.get_supported_arguments([

'-mspeculative-load-hardening', # Spectre v1 mitigation

'-Wconsumed',
'-Wimplicit-fallthrough',
]), language: 'cpp')

mod_qt5 = import('qt5')
dep_qt5 = dependency('qt5', modules: ['Core', 'Network', 'Widgets', 'WebEngineWidgets', 'Concurrent'])

dep_boost = dependency('boost', modules: ['program_options'])

dep_spdlog = dependency('spdlog', fallback: ['spdlog', 'spdlog_dep'], version: '>=1.3.1')

optional_deps = []
@@ -72,7 +82,6 @@ interfaces_moc = mod_qt5.preprocess(
)

subdir('lib/about')
subdir('lib/addressbar')
subdir('lib/bookmarks')
subdir('lib/configuration')
subdir('lib/downloads')
@@ -87,6 +96,8 @@ subdir('src')
subdir('lang')
subdir('doc')

subdir('plugins/ConfigurationEditor')
#subdir('plugins/ConfigurationEditor')
subdir('plugins/ProfileEditor')

subdir('test/conf')


+ 0
- 1
meson_options.txt View File

@@ -15,5 +15,4 @@ option('translations', description: 'Generate and install translations', type: '
option('Breakpad', description: 'Enable breakpad crash reporting', type: 'feature', value: 'auto')
option('Plasma', description: 'Enable KDE plasma integration', type: 'feature', value: 'auto')
option('Python', description: 'Enable Python interpreter', type: 'feature', value: 'auto')
option('testing', description: 'Build tests (requires gtest)', type: 'feature', value: 'auto')


+ 46
- 45
src/browser.cpp View File

@@ -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) {

+ 0
- 7
src/browser.h View File

@@ -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;

+ 32
- 0
src/conf.hpp.in View File

@@ -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();
}


+ 38
- 60
src/main.cpp View File

@@ -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) {

lib/addressbar/addressbar.cpp → src/mainwindow/addressbar.cpp View File

@@ -9,16 +9,18 @@
#include "addressbar.h"
#include "ui_addressbar.h"
#include <QShortcut>
#include "configuration.h"

AddressBar::AddressBar(const QHash<QString, QString> &config, QWidget *parent)
AddressBar::AddressBar(QWidget *parent)
: QWidget(parent)
, ui(new Ui::AddressBar)
{
ui->setupUi(this);

ui->urlBar->menuAction->setShortcut(QKeySequence(config.value("addressbar.shortcuts.menu")));
Configuration conf;
ui->urlBar->menuAction->setShortcut(QKeySequence(conf.value<QString>("shortcuts.address.menu").value()));

auto *focusShortcut = new QShortcut(QKeySequence(config.value("addressbar.shortcuts.focus")), parent);
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();

lib/addressbar/addressbar.h → src/mainwindow/addressbar.h View File

@@ -21,7 +21,7 @@ class AddressBar : public QWidget
Q_OBJECT

public:
AddressBar(const QHash<QString, QString> &config, QWidget *parent = nullptr);
AddressBar(QWidget *parent = nullptr);
~AddressBar() override;

signals:

lib/addressbar/addressbar.ui → src/mainwindow/addressbar.ui View File

@@ -51,7 +51,7 @@
<customwidget>
<class>UrlLineEdit</class>
<extends>QLineEdit</extends>
<header>urllineedit.h</header>
<header>mainwindow/widgets/urllineedit.h</header>
</customwidget>
</customwidgets>
<resources/>

+ 14
- 15
src/mainwindow/mainwindow.cpp View File

@@ -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);

+ 1
- 2
src/mainwindow/mainwindow.h View File

@@ -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;

+ 20
- 22
src/mainwindow/menubar.cpp View File

@@ -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) {

+ 1
- 2
src/mainwindow/menubar.h View File

@@ -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);

lib/addressbar/completer.cpp → src/mainwindow/widgets/completer.cpp View File


lib/addressbar/completer.h → src/mainwindow/widgets/completer.h View File


+ 10
- 8
src/mainwindow/widgets/navigationbar.cpp View File

@@ -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());
});

+ 1
- 1
src/mainwindow/widgets/navigationbar.h View File

@@ -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);

lib/addressbar/urllineedit.cpp → src/mainwindow/widgets/urllineedit.cpp View File

@@ -11,8 +11,7 @@
#include <QShortcut>
#include <QApplication>
#include <QClipboard>

#include "addressbar.h"
#include "../addressbar.h"

UrlLineEdit::UrlLineEdit(QWidget *parent)
: QLineEdit(parent)

lib/addressbar/urllineedit.h → src/mainwindow/widgets/urllineedit.h View File

@@ -10,11 +10,11 @@
#define SMOLBOTE_URLLINEEDIT_H

#include "completer.h"
#include "addressbar.h"
#include <QAction>
#include <QLineEdit>
#include <QTextLayout>

class AddressBar;
class WebView;
class UrlLineEdit : public QLineEdit
{

+ 7
- 4
src/meson.build View File

@@ -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',

+ 3
- 1
src/session/sessiondialog.cpp View File

@@ -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);
}