From f3a4607d6a722a862af0eb9747a15dcdf624b6fb Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Sun, 3 Nov 2019 00:18:10 +0200 Subject: Drop boost dependency - wrote not-invented-here config file parser and conf class - spent obscene amount of time plugging in said conf class --- lib/configuration/configuration.cpp | 205 ++++++++++++++---------------------- 1 file changed, 78 insertions(+), 127 deletions(-) (limited to 'lib/configuration/configuration.cpp') 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 -#include -#include +#include +#include +#include #include -#include -#include "config.h" +#include -namespace po = boost::program_options; +static std::unique_ptr 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(), ' '))); + value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to(), ' ')).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> l) noexcept + : m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()) { - configuration_desc.add_options() - ("browser.stylesheet", po::value()) - ("browser.iconTheme", po::value(), "Icon theme") - ("browser.locale", po::value(), "Set Qt localization.") - ("browser.translation", po::value(), "Set application localization.") - - // sessions - ("browser.session.path", po::value()->default_value(CONFIG_PATH_SESSION)) - -#ifdef CONFIG_USEBREAKPAD - ("browser.crash.path", po::value()->default_value(CONFIG_PATH_CRASHDUMP)) - ("browser.crash.handler", po::value()->default_value(CONFIG_PATH_CRASHHANDLER)) -#endif - - // main window ui - ("mainwindow.height", po::value()->default_value(720)) - ("mainwindow.width", po::value()->default_value(1280)) - ("mainwindow.maximized", po::value()->default_value(true)) - ("mainwindow.title", po::value()->default_value(CONFIG_POI_NAME)) - - // main window shortcuts - ("mainwindow.shortcuts.saveSession", po::value()->default_value("Ctrl+S,S")) - ("mainwindow.shortcuts.openSession", po::value()->default_value("Ctrl+S,O")) - - ("mainwindow.shortcuts.newGroup", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_NEWGROUP)) - ("mainwindow.shortcuts.newWindow", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_NEWWINDOW)) - - ("mainwindow.shortcuts.about", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_ABOUT)) - ("mainwindow.shortcuts.quit", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_QUIT)) - - ("mainwindow.shortcuts.search", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_SEARCH)) - ("mainwindow.shortcuts.tileWindows", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TILE)) - ("mainwindow.shortcuts.cascadeWindows", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_CASCADE)) - - // navigation - ("navigation.movable", po::value()->default_value(false)) - ("navigation.shortcuts.back", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_BACK)) - ("navigation.shortcuts.backMenu", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_BACKMENU)) - ("navigation.shortcuts.forward", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_FORWARD)) - ("navigation.shortcuts.forwardMenu", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_FORWARDMENU)) - ("navigation.shortcuts.refresh", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_REFRESH)) - ("navigation.shortcuts.reload", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_RELOAD)) - ("navigation.shortcuts.home", po::value()->default_value(CONFIG_SHORTCUT_NAVIGATION_HOME)) - - // address bar - ("addressbar.shortcuts.focus", po::value()->default_value(CONFIG_SHORTCUT_ADDRESS_FOCUS)) - ("addressbar.shortcuts.menu", po::value()->default_value(CONFIG_SHORTCUT_ADDRESS_MENU)) - - // subwindow - ("subwindow.shortcuts.menu", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MENU)) - ("subwindow.shortcuts.new", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_NEWTAB)) - ("subwindow.shortcuts.close", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_CLOSETAB)) - ("subwindow.shortcuts.restoreTab", po::value()->default_value("Ctrl+Shift+T")) - ("subwindow.shortcuts.left", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TABLEFT)) - ("subwindow.shortcuts.moveLeft", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MOVETABLEFT)) - ("subwindow.shortcuts.right", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_TABRIGHT)) - ("subwindow.shortcuts.moveRight", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_MOVETABRIGHT)) - ("subwindow.shortcuts.fullscreen", po::value()->default_value(CONFIG_SHORTCUT_SUBWINDOW_FULLSCREEN)) - - // Filter settings - ("filter.hosts", po::value()->default_value(CONFIG_PATH_FILTER)) - ("filter.adblock", po::value()) - ("filter.header", po::value>()) -// ("filter.cookies.block.all", po::value()->default_value(false)) -// ("filter.cookies.block.thirdParty", po::value()->default_value(true)) -// ("filter.cookies.path", po::value()->default_value("~/.config/smolbote/cookies.d")) - - // Plugin settings - ("plugins.path", po::value()->default_value(CONFIG_PATH_PLUGINS)) - - // Profile settings - // default profile name the browser should use; "" is off-the-record - ("profile.default", po::value()->default_value(CONFIG_PROFILE_DEFAULT)) - ("profile.path", po::value()->default_value(CONFIG_PATH_PROFILES)) - ("profile.search", po::value()->default_value(CONFIG_PROFILE_DEFAULT_SEARCH)) - ("profile.homepage", po::value()->default_value(CONFIG_PROFILE_DEFAULT_HOMEPAGE)) - ("profile.newtab", po::value()->default_value(CONFIG_PROFILE_DEFAULT_NEWTAB)) - - // Bookmark settings - ("bookmarks.path", po::value()->default_value(CONFIG_PATH_BOOKMARKS)) - ("bookmarks.shortcut", po::value()->default_value(CONFIG_SHORTCUT_WINDOW_BOOKMARKS)) - - // Downloads settings - ("downloads.path", po::value()->default_value(CONFIG_PATH_DOWNLOADS)) - ("downloads.shortcut", po::value()->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 Configuration::section(const std::string &prefix) const +void Configuration::read(std::basic_istream &input) { - QHash v; - for(auto &s : configuration_desc.options()) { - if(boost::starts_with(s->long_name(), prefix)) { - v[s->long_name().c_str()] = QString::fromStdString(value(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(v)) { + at(key) = value; + } else if(std::holds_alternative(v)) { + at(key) = std::stoi(value); + } else if(std::holds_alternative(v)) { + at(key) = (value == "true"); + } + } } +} + - return v; +void Configuration::move_global(std::unique_ptr &&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(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 } -- cgit v1.2.1