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 /lib | |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/about/aboutdialog.cpp | 3 | ||||
-rw-r--r-- | lib/addressbar/addressbar.cpp | 61 | ||||
-rw-r--r-- | lib/addressbar/addressbar.h | 42 | ||||
-rw-r--r-- | lib/addressbar/addressbar.ui | 59 | ||||
-rw-r--r-- | lib/addressbar/completer.cpp | 81 | ||||
-rw-r--r-- | lib/addressbar/completer.h | 35 | ||||
-rw-r--r-- | lib/addressbar/meson.build | 15 | ||||
-rw-r--r-- | lib/addressbar/urllineedit.cpp | 158 | ||||
-rw-r--r-- | lib/addressbar/urllineedit.h | 51 | ||||
-rw-r--r-- | lib/configuration/Kconfig | 131 | ||||
-rw-r--r-- | lib/configuration/configuration.cpp | 205 | ||||
-rw-r--r-- | lib/configuration/configuration.h | 136 | ||||
-rw-r--r-- | lib/configuration/meson.build | 14 | ||||
-rw-r--r-- | lib/pluginloader/Kconfig | 26 | ||||
-rw-r--r-- | lib/pluginloader/pluginloader.cpp | 2 | ||||
-rw-r--r-- | lib/webprofile/webprofilemanager.cpp | 8 | ||||
-rw-r--r-- | lib/webprofile/webprofilemanager.h | 11 |
17 files changed, 143 insertions, 895 deletions
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/addressbar.cpp b/lib/addressbar/addressbar.cpp deleted file mode 100644 index 2ea6d5e..0000000 --- a/lib/addressbar/addressbar.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "addressbar.h" -#include "ui_addressbar.h" -#include <QShortcut> - -AddressBar::AddressBar(const QHash<QString, QString> &config, QWidget *parent) - : QWidget(parent) - , ui(new Ui::AddressBar) -{ - ui->setupUi(this); - - ui->urlBar->menuAction->setShortcut(QKeySequence(config.value("addressbar.shortcuts.menu"))); - - auto *focusShortcut = new QShortcut(QKeySequence(config.value("addressbar.shortcuts.focus")), parent); - connect(focusShortcut, &QShortcut::activated, ui->urlBar, [=]() { - ui->urlBar->setFocus(); - ui->urlBar->selectAll(); - }); - - connect(ui->urlBar, &UrlLineEdit::textEdited, [=](const QString &text) { - std::function<void(QStringList &)> callback = std::bind(&UrlLineEdit::updateCompleter, ui->urlBar, std::placeholders::_1); - emit complete(text, callback); - }); - - connect(ui->urlBar, &UrlLineEdit::returnPressed, [=]() { - const QUrl url = QUrl::fromUserInput(ui->urlBar->text()); - - // check if url contains \w+:// (matches protocol://) or contains a '.' (matches site.domain) - // this is because single words are valid URLs for QUrl (searchterm becomes http://searchterm) - // check for protocol://site because \. wouldn't match it (localhost is a search term; http://localhost is an address) - if(ui->urlBar->text().contains(QRegularExpression("\\w+://|\\.")) && url.isValid()) { - emit load(url); - } else { - emit search(ui->urlBar->text()); - } - }); -} - -AddressBar::~AddressBar() -{ - disconnect(this); -} - -void AddressBar::setUrl(const QUrl &url) -{ - if(url.isEmpty()) - ui->urlBar->clear(); - else - ui->urlBar->setUrl(url); -} - -void AddressBar::setProgress(int value) { - ui->loadingBar->setValue(std::min(value, 100)); -} diff --git a/lib/addressbar/addressbar.h b/lib/addressbar/addressbar.h deleted file mode 100644 index 4609ac1..0000000 --- a/lib/addressbar/addressbar.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef SMOLBOTE_ADDRESSBAR_H -#define SMOLBOTE_ADDRESSBAR_H - -#include <QWidget> -#include <functional> - -namespace Ui { -class AddressBar; -} - -class AddressBar : public QWidget -{ - Q_OBJECT - -public: - AddressBar(const QHash<QString, QString> &config, QWidget *parent = nullptr); - ~AddressBar() override; - -signals: - void complete(const QString &term, std::function<void(QStringList &)> callback); - - void search(const QString &term); - void load(const QUrl &url); - void giveFocus(); - -public slots: - void setUrl(const QUrl &url); - void setProgress(int value); - -private: - Ui::AddressBar *ui; -}; - -#endif // SMOLBOTE_ADDRESSBAR_H diff --git a/lib/addressbar/addressbar.ui b/lib/addressbar/addressbar.ui deleted file mode 100644 index a5b4a4d..0000000 --- a/lib/addressbar/addressbar.ui +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>AddressBar</class> - <widget class="QWidget" name="AddressBar"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>400</width> - <height>31</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="UrlLineEdit" name="urlBar"/> - </item> - <item> - <widget class="QProgressBar" name="loadingBar"> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>5</height> - </size> - </property> - <property name="textVisible"> - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>UrlLineEdit</class> - <extends>QLineEdit</extends> - <header>urllineedit.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/lib/addressbar/completer.cpp b/lib/addressbar/completer.cpp deleted file mode 100644 index 578f745..0000000 --- a/lib/addressbar/completer.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "completer.h" -#include <QKeyEvent> - -Completer::Completer(QWidget *parent) - : QListView(parent) -{ - setObjectName("Completer"); - setWindowFlags(Qt::ToolTip); - setEditTriggers(QAbstractItemView::NoEditTriggers); - - connect(this, &Completer::activated, [=](const QModelIndex &index) { - hide(); - emit completionActivated(index.data().toString()); - }); -} - -bool Completer::updateItems(const QStringList &list) -{ - if(list.isEmpty()) - return false; - - auto *model = new QStringListModel(list, this); - setModel(model); - - delete completionModel; - completionModel = model; - - return true; -} - -bool Completer::keyPressed(QKeyEvent *event) -{ - if(isHidden()) - return false; - - Q_CHECK_PTR(completionModel); - - int count = completionModel->rowCount(); - const QModelIndex currentIndex = this->currentIndex(); - - switch(event->key()) { - case Qt::Key_Down: - if(currentIndex.row() + 1 >= count) { - setCurrentIndex(completionModel->index(0, 0)); - } else { - setCurrentIndex(completionModel->index(currentIndex.row() + 1, 0)); - } - break; - - case Qt::Key_Up: - if(currentIndex.row() == 0) { - setCurrentIndex(completionModel->index(count - 1, 0)); - } else { - setCurrentIndex(completionModel->index(currentIndex.row() - 1, 0)); - } - break; - - case Qt::Key_Escape: - hide(); - break; - - case Qt::Key_Enter: - case Qt::Key_Return: - hide(); - emit completionActivated(currentIndex.data().toString()); - break; - - default: - return false; - } - - return true; -} diff --git a/lib/addressbar/completer.h b/lib/addressbar/completer.h deleted file mode 100644 index 656a80f..0000000 --- a/lib/addressbar/completer.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef SMOLBOTE_COMPLETER_H -#define SMOLBOTE_COMPLETER_H - -#include <QListView> -#include <QStringListModel> -#include <QTreeWidgetItem> - -class Completer : public QListView -{ - - Q_OBJECT - -public: - explicit Completer(QWidget *parent = nullptr); - - bool updateItems(const QStringList &list); - - bool keyPressed(QKeyEvent *event); - -signals: - void completionActivated(const QString &url); - -private: - QStringListModel *completionModel = nullptr; -}; - -#endif //SMOLBOTE_COMPLETER_H diff --git a/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/addressbar/urllineedit.cpp b/lib/addressbar/urllineedit.cpp deleted file mode 100644 index 1084f25..0000000 --- a/lib/addressbar/urllineedit.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "urllineedit.h" -#include <QMenu> -#include <QShortcut> -#include <QApplication> -#include <QClipboard> - -#include "addressbar.h" - -UrlLineEdit::UrlLineEdit(QWidget *parent) - : QLineEdit(parent) - , m_listView(new Completer(this)) -{ - setObjectName("UrlBar"); - setPlaceholderText(tr("Enter address")); - - m_listView->setVisible(false); - connect(m_listView, &Completer::completionActivated, this, &UrlLineEdit::setText); - - addressbar = qobject_cast<AddressBar *>(parent); - Q_CHECK_PTR(addressbar); - - auto *copyAction = new QAction(tr("Copy URL"), this); - connect(copyAction, &QAction::triggered, this, [this]() { - qApp->clipboard()->setText(this->text()); - }); - actions.append(copyAction); - - auto *pasteAction = new QAction(tr("Paste URL"), this); - connect(pasteAction, &QAction::triggered, this, [this]() { - this->setText(qApp->clipboard()->text()); - this->setFocus(); - }); - actions.append(pasteAction); - - auto *loadAction = new QAction(tr("Paste and load"), this); - connect(loadAction, &QAction::triggered, this, [=]() { - emit addressbar->load(QUrl::fromUserInput(qApp->clipboard()->text())); - }); - actions.append(loadAction); - - auto *searchAction = new QAction(tr("Paste and search"), this); - connect(searchAction, &QAction::triggered, this, [=]() { - emit addressbar->search(qApp->clipboard()->text()); - }); - actions.append(searchAction); - - menuAction = addAction(style()->standardIcon(QStyle::SP_DriveNetIcon), QLineEdit::LeadingPosition); - connect(menuAction, &QAction::triggered, this, [this]() { - auto *menu = new QMenu(); - menu->setAttribute(Qt::WA_DeleteOnClose, true); - menu->setMinimumWidth(240); - menu->addActions(actions); - - menu->exec(this->mapToGlobal(QPoint(0, height()))); - }); - - auto *goAction = addAction(style()->standardIcon(QStyle::SP_DialogOkButton), QLineEdit::TrailingPosition); - connect(goAction, &QAction::triggered, this, [this]() { - emit returnPressed(); - }); - - QTextCharFormat hostnameFormat; - hostnameFormat.setFontWeight(QFont::Bold); - m_hostFormat.format = hostnameFormat; -} - -void UrlLineEdit::setUrl(const QUrl &url) -{ - QString urlText = url.toString(); - QString domain = url.host(); - - m_hostFormat.start = urlText.indexOf(domain); - m_hostFormat.length = domain.length(); - - clear(); - clearTextFormat(); - setTextFormat(m_hostFormat); - setText(urlText); -} - -void UrlLineEdit::updateCompleter(const QStringList &l) -{ - if(!m_listView->updateItems(l)) { - m_listView->hide(); - return; - } - - // positioning - m_listView->setFixedWidth(width()); - m_listView->move(mapToGlobal(QPoint(0, height()))); - m_listView->show(); -} - -void UrlLineEdit::focusInEvent(QFocusEvent *event) -{ - // a context menu event also causes a focusInEvent, so if text is selected - // skip the formatting step - if(event->reason() == Qt::PopupFocusReason) { - QLineEdit::focusInEvent(event); - return; - } - - clearTextFormat(); - QLineEdit::focusInEvent(event); -} - -void UrlLineEdit::focusOutEvent(QFocusEvent *event) -{ - // a context menu event causes a focusOutEvent, and setUrl will clear the - // selection, and this would prevent the menu from working properly - if(event->reason() == Qt::PopupFocusReason) { - QLineEdit::focusOutEvent(event); - return; - } - - const QUrl url = QUrl::fromUserInput(text()); - if(url.isValid()) - setUrl(url); - - emit addressbar->giveFocus(); - QLineEdit::focusOutEvent(event); -} - -void UrlLineEdit::keyPressEvent(QKeyEvent *event) -{ - if(m_listView->keyPressed(event)) { - event->accept(); - return; - } else if(event->key() == Qt::Key::Key_Escape) { - clearFocus(); - event->accept(); - return; - } - - QLineEdit::keyPressEvent(event); -} - -// formatting taken from: https://forum.qt.io/topic/60962/setting-qlineedit-text-bold -void UrlLineEdit::setTextFormat(const QTextLayout::FormatRange &format) -{ - QList<QInputMethodEvent::Attribute> attributes; - attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, format.start, format.length, format.format)); - QInputMethodEvent ev(QString(), attributes); - event(&ev); -} - -void UrlLineEdit::clearTextFormat() -{ - setTextFormat(QTextLayout::FormatRange()); -} diff --git a/lib/addressbar/urllineedit.h b/lib/addressbar/urllineedit.h deleted file mode 100644 index 4df8d21..0000000 --- a/lib/addressbar/urllineedit.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#ifndef SMOLBOTE_URLLINEEDIT_H -#define SMOLBOTE_URLLINEEDIT_H - -#include "completer.h" -#include "addressbar.h" -#include <QAction> -#include <QLineEdit> -#include <QTextLayout> - -class WebView; -class UrlLineEdit : public QLineEdit -{ - Q_OBJECT -public: - explicit UrlLineEdit(QWidget *parent = nullptr); - -public slots: - void setUrl(const QUrl &url); - - void updateCompleter(const QStringList &l); - -public: - QAction *menuAction = nullptr; - -protected: - void focusInEvent(QFocusEvent *event) override; - void focusOutEvent(QFocusEvent *event) override; - void keyPressEvent(QKeyEvent *event) override; - -private: - void setTextFormat(const QTextLayout::FormatRange &format); - void clearTextFormat(); - - QList<QAction *> actions; - - QTextLayout::FormatRange m_hostFormat; - - // completer - Completer *m_listView; - AddressBar *addressbar; -}; - -#endif // SMOLBOTE_URLLINEEDIT_H diff --git a/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 |