diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-11-03 00:18:10 +0200 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2019-11-03 00:20:41 +0200 |
commit | f3a4607d6a722a862af0eb9747a15dcdf624b6fb (patch) | |
tree | 9885709cdff55a865be6c03c591a9757680b0396 | |
parent | Change spdlog from makedepends to depends (diff) | |
download | smolbote-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
41 files changed, 645 insertions, 655 deletions
@@ -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 diff --git a/include/browserinterface.h b/include/browserinterface.h index ef89456..4cdc63b 100644 --- a/include/browserinterface.h +++ b/include/browserinterface.h @@ -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; diff --git a/lib/about/aboutdialog.cpp b/lib/about/aboutdialog.cpp index 1ca493e..99fb7ce 100644 --- a/lib/about/aboutdialog.cpp +++ b/lib/about/aboutdialog.cpp @@ -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>" diff --git a/lib/addressbar/meson.build b/lib/addressbar/meson.build deleted file mode 100644 index 486d05d..0000000 --- a/lib/addressbar/meson.build +++ /dev/null @@ -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 -) diff --git a/lib/configuration/Kconfig b/lib/configuration/Kconfig deleted file mode 100644 index b165093..0000000 --- a/lib/configuration/Kconfig +++ /dev/null @@ -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 - diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index 952f4b2..bd7700c 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -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 } diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h index 40da50e..bc8f52e 100644 --- a/lib/configuration/configuration.h +++ b/lib/configuration/configuration.h @@ -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 diff --git a/lib/configuration/meson.build b/lib/configuration/meson.build index 19f57f4..939a493 100644 --- a/lib/configuration/meson.build +++ b/lib/configuration/meson.build @@ -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) ) + diff --git a/lib/pluginloader/Kconfig b/lib/pluginloader/Kconfig deleted file mode 100644 index 28a3b73..0000000 --- a/lib/pluginloader/Kconfig +++ /dev/null @@ -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 diff --git a/lib/pluginloader/pluginloader.cpp b/lib/pluginloader/pluginloader.cpp index f47c39e..ef17513 100644 --- a/lib/pluginloader/pluginloader.cpp +++ b/lib/pluginloader/pluginloader.cpp @@ -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 diff --git a/lib/webprofile/webprofilemanager.cpp b/lib/webprofile/webprofilemanager.cpp index b0eff93..05808ab 100644 --- a/lib/webprofile/webprofilemanager.cpp +++ b/lib/webprofile/webprofilemanager.cpp @@ -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); }); diff --git a/lib/webprofile/webprofilemanager.h b/lib/webprofile/webprofilemanager.h index f7bf52a..3d86def 100644 --- a/lib/webprofile/webprofilemanager.h +++ b/lib/webprofile/webprofilemanager.h @@ -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 diff --git a/linux/.config b/linux/.config index 3e8d40c..eea58d5 100644 --- a/linux/.config +++ b/linux/.config @@ -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 diff --git a/linux/makepkg/PKGBUILD b/linux/makepkg/PKGBUILD index 59f454d..9243405 100644 --- a/linux/makepkg/PKGBUILD +++ b/linux/makepkg/PKGBUILD @@ -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" diff --git a/meson.build b/meson.build index af2dd63..4092f5e 100644 --- a/meson.build +++ b/meson.build @@ -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') + diff --git a/meson_options.txt b/meson_options.txt index 5f56ec2..8a3dfea 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -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') 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/lib/addressbar/addressbar.cpp b/src/mainwindow/addressbar.cpp index 2ea6d5e..42fa890 100644 --- a/lib/addressbar/addressbar.cpp +++ b/src/mainwindow/addressbar.cpp @@ -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(); diff --git a/lib/addressbar/addressbar.h b/src/mainwindow/addressbar.h index 4609ac1..61d00e9 100644 --- a/lib/addressbar/addressbar.h +++ b/src/mainwindow/addressbar.h @@ -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: diff --git a/lib/addressbar/addressbar.ui b/src/mainwindow/addressbar.ui index a5b4a4d..1af1689 100644 --- a/lib/addressbar/addressbar.ui +++ b/src/mainwindow/addressbar.ui @@ -51,7 +51,7 @@ <customwidget> <class>UrlLineEdit</class> <extends>QLineEdit</extends> - <header>urllineedit.h</header> + <header>mainwindow/widgets/urllineedit.h</header> </customwidget> </customwidgets> <resources/> 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/lib/addressbar/completer.cpp b/src/mainwindow/widgets/completer.cpp index 578f745..578f745 100644 --- a/lib/addressbar/completer.cpp +++ b/src/mainwindow/widgets/completer.cpp diff --git a/lib/addressbar/completer.h b/src/mainwindow/widgets/completer.h index 656a80f..656a80f 100644 --- a/lib/addressbar/completer.h +++ b/src/mainwindow/widgets/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/lib/addressbar/urllineedit.cpp b/src/mainwindow/widgets/urllineedit.cpp index 1084f25..378945f 100644 --- a/lib/addressbar/urllineedit.cpp +++ b/src/mainwindow/widgets/urllineedit.cpp @@ -11,8 +11,7 @@ #include <QShortcut> #include <QApplication> #include <QClipboard> - -#include "addressbar.h" +#include "../addressbar.h" UrlLineEdit::UrlLineEdit(QWidget *parent) : QLineEdit(parent) diff --git a/lib/addressbar/urllineedit.h b/src/mainwindow/widgets/urllineedit.h index 4df8d21..88780a1 100644 --- a/lib/addressbar/urllineedit.h +++ b/src/mainwindow/widgets/urllineedit.h @@ -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 { 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) { diff --git a/test/conf/main.cpp b/test/conf/main.cpp new file mode 100644 index 0000000..e499a4d --- /dev/null +++ b/test/conf/main.cpp @@ -0,0 +1,54 @@ +#include <fstream> +#include <iostream> +#include <string> +#include "configuration.h" +#include <cassert> + +int main(int, char**) +{ + std::fstream fs; + fs.open("smolbote.cfg", std::fstream::in); + assert(fs.is_open()); + + { + auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({ + { "test", std::string("unknown") }, + { "integer-1", 20 }, + { "integer-2", 30 } + }); + value_map->read(fs); + + Configuration::move_global(std::move(value_map)); + fs.close(); + } + + { + Configuration g; + assert(g.value<std::string>("test") == "value"); + assert(g.value<std::string>("plugins.path") == "/usr/local/lib/smolbote/plugins"); + assert(g.value<int>("integer-1") == 20); + assert(g.value<int>("integer-2") == 22); + } + +/* + { + const Configuration conf(std::move(value_map)); + + assert(conf.value<std::string>("test") == "value"); + assert(conf.value<std::string>("plugins.path") == "/usr/local/lib/smolbote/plugins"); + assert(conf.value<int>("integer-1") == 20); + assert(conf.value<int>("integer-2") == 22); + } +*/ + // Configuration is now destroyed + + + // This should be a compiler warning + //const Configuration c(std::move(value_map)); + //assert(c.value<std::string>("test") == "value"); + + // This should be a compiler warning and runtime error + //assert(value_map.value<std::string>("test").value() == "value"); + + return 0; +} diff --git a/test/conf/meson.build b/test/conf/meson.build new file mode 100644 index 0000000..de67db7 --- /dev/null +++ b/test/conf/meson.build @@ -0,0 +1,6 @@ +e = executable('conf_test', + dependencies: [dep_qt5, dep_configuration], + sources: 'main.cpp' +) + +test('conf_test', e, workdir : meson.source_root()/'test/conf') diff --git a/test/conf/smolbote.cfg b/test/conf/smolbote.cfg new file mode 100644 index 0000000..25467ef --- /dev/null +++ b/test/conf/smolbote.cfg @@ -0,0 +1,5 @@ +# this is a comment +test = value +plugins.path = /usr/local/lib/smolbote/plugins + +integer-2 = 22 |