aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/bookmarks/CMakeLists.txt9
-rw-r--r--lib/bookmarks/formats/ffjson.cpp7
-rw-r--r--lib/bookmarks/formats/xbel.cpp17
-rw-r--r--lib/bookmarks/meson.build16
-rw-r--r--lib/configuration/CMakeLists.txt24
-rw-r--r--lib/configuration/configuration.cpp118
-rw-r--r--lib/configuration/configuration.h61
-rwxr-xr-xlib/configuration/gen-default-cfg.py43
-rw-r--r--lib/configuration/init_global.cpp.in25
-rw-r--r--lib/configuration/qt_specialization.cpp31
-rw-r--r--lib/configuration/qt_specialization.h8
-rw-r--r--lib/configuration/test/configuration.cpp57
-rw-r--r--lib/downloads/CMakeLists.txt8
-rw-r--r--lib/downloads/downloadswidget.cpp2
-rw-r--r--lib/downloads/downloadswidget.h4
-rw-r--r--lib/downloads/meson.build19
-rw-r--r--lib/downloads/widgets/downloaditemwidget.cpp27
-rw-r--r--lib/downloads/widgets/downloaditemwidget.h10
-rw-r--r--lib/pluginloader/CMakeLists.txt0
-rw-r--r--lib/session_formats/CMakeLists.txt5
-rw-r--r--lib/urlfilter/CMakeLists.txt27
-rw-r--r--lib/urlfilter/meson.build26
22 files changed, 351 insertions, 193 deletions
diff --git a/lib/bookmarks/CMakeLists.txt b/lib/bookmarks/CMakeLists.txt
new file mode 100644
index 0000000..d4bd3c7
--- /dev/null
+++ b/lib/bookmarks/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_library(bookmarks STATIC
+ bookmarkformat.cpp bookmarkformat.h
+ bookmarkitem.cpp bookmarkitem.h
+ bookmarkmodel.cpp bookmarkmodel.h
+ formats/xbel.cpp formats/xbel.h
+ formats/ffjson.cpp formats/ffjson.h
+)
+target_link_libraries(bookmarks PUBLIC Qt6::Widgets)
+target_include_directories(bookmarks PUBLIC ${CMAKE_CURRENT_LIST_DIR})
diff --git a/lib/bookmarks/formats/ffjson.cpp b/lib/bookmarks/formats/ffjson.cpp
index f9e0866..f95d0d8 100644
--- a/lib/bookmarks/formats/ffjson.cpp
+++ b/lib/bookmarks/formats/ffjson.cpp
@@ -8,11 +8,12 @@
#include "ffjson.h"
#include "bookmarkitem.h"
+#include <QDateTime>
+#include <QDebug>
+#include <QIODevice>
+#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
-#include <QJsonArray>
-#include <QDebug>
-#include <QDateTime>
inline auto asDate(const QJsonValue &v)
{
diff --git a/lib/bookmarks/formats/xbel.cpp b/lib/bookmarks/formats/xbel.cpp
index 7ff79a9..a0a553f 100644
--- a/lib/bookmarks/formats/xbel.cpp
+++ b/lib/bookmarks/formats/xbel.cpp
@@ -15,28 +15,28 @@
inline void readChildElements(QXmlStreamReader &reader, BookmarkItem *parent)
{
while(reader.readNextStartElement()) {
- if(reader.name() == "title") {
+ if(reader.name() == QLatin1String("title")) {
parent->setData(BookmarkItem::Title, reader.readElementText());
- } else if(reader.name() == "dateAdded") {
+ } else if(reader.name() == QLatin1String("dateAdded")) {
parent->setData(BookmarkItem::DateAdded, QDateTime::fromString(reader.readElementText(), Qt::RFC2822Date));
- } else if(reader.name() == "lastModified") {
+ } else if(reader.name() == QLatin1String("lastModified")) {
parent->setData(BookmarkItem::LastModified, QDateTime::fromString(reader.readElementText(), Qt::RFC2822Date));
- } else if(reader.name() == "tags") {
+ } else if(reader.name() == QLatin1String("tags")) {
parent->setData(BookmarkItem::Tags, reader.readElementText().split(";"));
- } else if(reader.name() == "description") {
+ } else if(reader.name() == QLatin1String("description")) {
parent->setData(BookmarkItem::Description, reader.readElementText());
- } else if(reader.name() == "folder") {
+ } else if(reader.name() == QLatin1String("folder")) {
auto *item = new BookmarkItem({}, BookmarkItem::Folder, parent);
item->setExpanded(!(reader.attributes().value("folded") == QLatin1String("yes")));
parent->appendChild(item);
readChildElements(reader, item);
- } else if(reader.name() == "bookmark") {
+ } else if(reader.name() == QLatin1String("bookmark")) {
auto *item = new BookmarkItem({}, BookmarkItem::Bookmark, parent);
item->setData(BookmarkItem::Href, reader.attributes().value("href").toString());
parent->appendChild(item);
@@ -53,7 +53,8 @@ void Xbel::read(QIODevice *device, BookmarkItem *item)
QXmlStreamReader qXmlStreamReader(device);
if(qXmlStreamReader.readNextStartElement()) {
- if(!(qXmlStreamReader.name() == "xbel" && qXmlStreamReader.attributes().value("version") == "1.0")) {
+ if(!(qXmlStreamReader.name() == QLatin1String("xbel")
+ && qXmlStreamReader.attributes().value("version") == QLatin1String("1.0"))) {
return;
}
diff --git a/lib/bookmarks/meson.build b/lib/bookmarks/meson.build
deleted file mode 100644
index 81c1ece..0000000
--- a/lib/bookmarks/meson.build
+++ /dev/null
@@ -1,16 +0,0 @@
-bookmarks_moc = mod_qt5.preprocess(
- moc_headers: [ 'bookmarkmodel.h' ],
- dependencies: dep_qt5
-)
-
-bookmarks_lib = static_library('bookmarks',
- [ bookmarks_moc,
- 'bookmarkformat.cpp', 'formats/xbel.cpp', 'formats/ffjson.cpp',
- 'bookmarkitem.cpp', 'bookmarkmodel.cpp' ],
- dependencies: dep_qt5
-)
-
-dep_bookmarks = declare_dependency(
- include_directories: include_directories('.'),
- link_with: bookmarks_lib
-)
diff --git a/lib/configuration/CMakeLists.txt b/lib/configuration/CMakeLists.txt
new file mode 100644
index 0000000..2e77782
--- /dev/null
+++ b/lib/configuration/CMakeLists.txt
@@ -0,0 +1,24 @@
+# generate init_global.cpp
+add_custom_command(
+ OUTPUT init_global.cpp
+ COMMAND ${CMAKE_CURRENT_LIST_DIR}/gen-default-cfg.py
+ --config ${PROJECT_SOURCE_DIR}/linux/config.yaml
+ --template ${CMAKE_CURRENT_LIST_DIR}/init_global.cpp.in
+ --output init_global.cpp
+ DEPENDS
+ ${CMAKE_CURRENT_LIST_DIR}/gen-default-cfg.py
+ ${PROJECT_SOURCE_DIR}/linux/config.yaml
+)
+add_library(configuration STATIC
+ configuration.cpp configuration.h
+ init_global.cpp
+ qt_specialization.cpp qt_specialization.h
+)
+target_link_libraries(configuration PUBLIC Qt6::Gui spdlog::spdlog)
+target_include_directories(configuration PUBLIC ${CMAKE_CURRENT_LIST_DIR})
+
+add_executable(test_configuration test/configuration.cpp)
+target_link_libraries(test_configuration PUBLIC configuration GTest::gtest_main)
+gtest_add_tests(TARGET test_configuration
+ SOURCES test/configuration.cpp
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/test)
diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp
index 75f863c..f2a2218 100644
--- a/lib/configuration/configuration.cpp
+++ b/lib/configuration/configuration.cpp
@@ -10,13 +10,15 @@
#include <algorithm>
#include <fstream>
#include <iostream>
-#include <sstream>
#include <stdexcept>
+#include <variant>
#ifndef NO_QT_SPEC
#include <QStandardPaths>
#endif
+using namespace std::placeholders;
+
static std::unique_ptr<Configuration> s_conf;
Configuration::Configuration()
@@ -27,66 +29,64 @@ Configuration::Configuration()
}
}
-Configuration::Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept
+Configuration::Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> p_list) noexcept
#ifndef NO_QT_SPEC
: m_homePath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString())
#endif
{
- for(const auto &i : l) {
- insert_or_assign(i.first, i.second);
+ for(const auto &item : p_list) {
+ insert_or_assign(item);
}
}
-void Configuration::read_file(const std::string &location)
+bool Configuration::read_file(const std::string &location)
{
- std::fstream fs(location, std::fstream::in);
- if(fs.is_open()) {
- read(fs);
- fs.close();
+ std::fstream fstream(location, std::fstream::in);
+ bool result = false;
+
+ if(fstream.is_open()) {
+ read(fstream);
+ fstream.close();
+ result = true;
}
+
+ return result;
}
inline auto strip(std::string &value)
{
- 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());
+ // strip whitespace at the begining
+ value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind(std::not_equal_to<>(), ' ', _1)));
+
+ // strip whitespace from the end
+ value.erase(std::find_if(value.rbegin(), value.rend(), std::bind(std::not_equal_to<>(), ' ', _1)).base(), value.end());
+
return value;
}
-inline auto parse(const std::string &line, std::string &section)
+inline std::optional<Configuration::kv_pair> parse_line(const std::string &line, /* in/out */ std::string &section)
{
- struct {
- bool pair = false;
- std::string key;
- std::string value;
- } ret;
-
- if(line[0] == '#' || line.length() == 0) {
- return ret;
- }
-
if(line.front() == '[' && line.back() == ']') {
section = line.substr(1, line.length() - 2) + '/';
- return ret;
+ return std::nullopt;
}
const auto pos = line.find_first_of('=');
if(pos == std::string::npos) {
- return ret;
+ return std::nullopt;
}
- ret.key = line.substr(0, pos);
- strip(ret.key);
- if(ret.key.empty()) {
- return ret;
- }
- ret.key = section + ret.key;
+ std::string key = line.substr(0, pos);
+ std::string val = line.substr(pos + 1);
+ strip(key);
+ strip(val);
- ret.value = line.substr(pos + 1);
- strip(ret.value);
+ if(key.empty()) {
+ return std::nullopt;
+ }
+ key = section + key;
- ret.pair = true;
- return ret;
+ return std::make_optional<Configuration::kv_pair>({ key, val });
}
#ifdef FUZZER
@@ -100,9 +100,16 @@ extern "C" int LLVMFuzzerTestOneInput(const char *Data, long long Size)
void Configuration::read(std::basic_istream<char> &input)
{
- std::string line, section;
+ std::string line;
+ std::string section;
while(std::getline(input, line)) {
+ // skip empty lines and comments
+ if(line.length() == 0 || line[0] == '#') {
+ continue;
+ }
+
+ // include file
if(line.rfind("@@") == 0) {
if(line.rfind("@@include ") == 0) {
read_file(line.substr(10));
@@ -110,23 +117,30 @@ void Configuration::read(std::basic_istream<char> &input)
continue;
}
- const auto pair = parse(line, section);
- if(pair.pair) {
+ const auto pair = parse_line(line, section);
+ if(pair) {
+ insert_or_assign(*pair);
+ }
+ }
+}
- if(this->count(pair.key) == 0) {
- // no type has been specified for this key, assuming std::string
- insert(std::make_pair(pair.key, pair.value));
- continue;
- }
+void Configuration::insert_or_assign(const Configuration::kv_pair &pair)
+{
+ // insert
+ if(count(pair.first) == 0) {
+ insert(pair);
+ } else {
+ // when assigning we have to keep the same type
+ const auto old_value = at(pair.first);
- auto v = at(pair.key);
- if(std::holds_alternative<std::string>(v)) {
- at(pair.key) = pair.value;
- } else if(std::holds_alternative<int>(v)) {
- at(pair.key) = std::stoi(pair.value);
- } else if(std::holds_alternative<bool>(v)) {
- at(pair.key) = (pair.value == "true");
- }
+ if(std::holds_alternative<std::string>(old_value)) {
+ at(pair.first) = pair.second;
+
+ } else if(std::holds_alternative<int>(old_value)) {
+ at(pair.first) = std::stoi(std::get<std::string>(pair.second));
+
+ } else if(std::holds_alternative<bool>(old_value)) {
+ at(pair.first) = (std::get<std::string>(pair.second) == "true");
}
}
}
@@ -150,9 +164,7 @@ std::ostream &operator<<(std::ostream &out, const Configuration &obj)
// unordered_map is, well, unordered, so grab the keys and sort them before printing them
std::vector<std::string> keys;
- for(const auto &pair : obj) {
- keys.emplace_back(pair.first);
- }
+ std::transform(obj.cbegin(), obj.cend(), std::inserter(keys, keys.end()), [](const auto &pair) { return pair.first; });
std::sort(keys.begin(), keys.end());
for(const auto &key : keys) {
diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h
index cd3c244..f2de92f 100644
--- a/lib/configuration/configuration.h
+++ b/lib/configuration/configuration.h
@@ -12,52 +12,44 @@
#include <initializer_list>
#include <memory>
#include <optional>
+#include <source_location>
+#include <spdlog/spdlog.h>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <variant>
-#if defined(__clang__)
-#define consumable(X) [[clang::consumable(X)]]
-#define return_typestate(X) [[clang::return_typestate(X)]]
-#define callable_when(X) [[clang::callable_when(X)]]
-#define param_typestate(X) [[clang::param_typestate(X)]]
-#else
-#define consumable(X)
-#define return_typestate(X)
-#define callable_when(X)
-#define param_typestate(X)
-#endif
-
-typedef std::variant<std::string, int, bool> conf_value_t;
+using conf_value_t = std::variant<std::string, int, bool>;
template <typename T>
-concept concept_value_t = std::is_arithmetic<T>::value || std::is_same<T, bool>::value || std::is_constructible<T, std::string>::value;
+concept concept_value_t = std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_constructible_v<T, std::string>;
-class consumable(unconsumed) Configuration : private std::unordered_map<std::string, conf_value_t>
+class Configuration : private std::unordered_map<std::string, conf_value_t>
{
friend std::ostream &operator<<(std::ostream &out, const Configuration &obj);
public:
- return_typestate(unconsumed) Configuration();
- return_typestate(unconsumed) Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept;
+ using kv_pair = std::pair<std::string, conf_value_t>;
+
+ Configuration();
+ Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> p_list) noexcept;
Configuration(const Configuration &) = delete;
Configuration &operator=(const Configuration &) = delete;
- return_typestate(unconsumed) Configuration(Configuration && other param_typestate(unconsumed)) = default;
+ Configuration(Configuration &&other) = default;
Configuration &operator=(Configuration &&) = delete;
~Configuration() = default;
- callable_when(unconsumed) void read_file(const std::string &location);
- callable_when(unconsumed) void read(std::basic_istream<char> & input);
+ bool read_file(const std::string &location);
+ void read(std::basic_istream<char> &input);
template <typename T>
- callable_when(unconsumed) [[nodiscard]] std::optional<T> value(const char *path) const
+ [[nodiscard]] std::optional<T> value(const char *path, const std::source_location location = std::source_location::current()) const
{
if(use_global) {
- return instance()->value<T>(path);
+ return instance()->value<T>(path, location);
}
if(count(path) == 0) {
@@ -68,18 +60,19 @@ public:
}
template <concept_value_t T>
- callable_when(unconsumed) [[nodiscard]] std::optional<T> value(const char *path) const
+ [[nodiscard]] std::optional<T> value(const char *p_path, const std::source_location location = std::source_location::current()) const
{
if(use_global) {
- return instance()->value<T>(path);
+ return instance()->value<T>(p_path, location);
}
- if(this->count(path) == 0) {
+ if(this->count(p_path) == 0) {
+ spdlog::warn("requested non-existent configuration value {} at {}:{}", p_path, location.file_name(), location.line());
return std::nullopt;
}
// path is guaranteed to exist
- const auto value = at(path);
+ const auto value = at(p_path);
if(std::holds_alternative<int>(value)) {
if constexpr(std::is_arithmetic<T>::value) {
@@ -89,9 +82,11 @@ public:
}
} else if(std::holds_alternative<bool>(value)) {
- if constexpr(std::is_constructible<T, bool>::value) {
+ if constexpr(std::is_constructible_v<T, bool> || std::is_same_v<T, bool>) {
return std::get<bool>(value);
- } else if constexpr(std::is_constructible<T, const char *>::value) {
+ } else if constexpr(std::is_arithmetic_v<T>) {
+ return static_cast<T>(std::get<bool>(value));
+ } else if constexpr(std::is_constructible_v<T, const char *>) {
return std::get<bool>(value) ? T{ "true" } : T{ "false" };
}
@@ -99,7 +94,9 @@ public:
auto str = std::get<std::string>(value);
try {
- if constexpr(std::is_floating_point<T>::value) {
+ if constexpr(std::is_same_v<T, bool>) {
+ return (str == "true");
+ } else if constexpr(std::is_floating_point<T>::value) {
return static_cast<T>(std::stod(str));
} else if constexpr(std::is_arithmetic<T>::value) {
return static_cast<T>(std::stol(str));
@@ -121,13 +118,17 @@ public:
}
template <typename T>
- callable_when(unconsumed) T &shortcut(T & /* unused */, const char * /* unused */) const
+ T &shortcut(T & /* unused */, const char * /* unused */, const std::source_location location = std::source_location::current()) const
{
return T{};
}
+ static std::string init_global(const std::string &p_path);
static void move_global(std::unique_ptr<Configuration> && conf);
+protected:
+ void insert_or_assign(const kv_pair &pair);
+
private:
static Configuration *instance();
diff --git a/lib/configuration/gen-default-cfg.py b/lib/configuration/gen-default-cfg.py
new file mode 100755
index 0000000..5d9f8da
--- /dev/null
+++ b/lib/configuration/gen-default-cfg.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+import sys
+import argparse
+import yaml
+
+def v_to_str(value):
+ if type(value) is str:
+ return f"std::string(\"{value}\")"
+ if type(value) is int:
+ return value
+ if type(value) is bool:
+ return "true" if True else "false"
+
+def kv_pairs_to_str(section, pairs):
+ pairs_str = "\n".join([f" {{ \"{section}/{key}\", {v_to_str(pairs[key])} }}," for key in pairs])
+ return pairs_str
+
+def writeConfigInitList(config, file):
+ for node in config:
+ for section, pairs in node.items():
+ print(kv_pairs_to_str(section, pairs), file=file)
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--config", type=argparse.FileType('r'), required=True, help="configuration yaml")
+ parser.add_argument("--template", type=argparse.FileType('r'), required=True, help="settings.h.in")
+ parser.add_argument("--output", type=argparse.FileType('w'), default=sys.stdout, help="Output location")
+ args = parser.parse_args()
+
+ config = yaml.safe_load(args.config)
+ print("config: ", config)
+
+ print("/* Autogenerated file", file=args.output)
+ print(" * config: {}".format(args.config), file=args.output)
+ print(" */", file=args.output)
+
+ for line in args.template:
+ if "@__DEFAULT_CFG__" in line:
+ writeConfigInitList(config, args.output)
+ else:
+ print(line, end='', file=args.output)
diff --git a/lib/configuration/init_global.cpp.in b/lib/configuration/init_global.cpp.in
new file mode 100644
index 0000000..9179130
--- /dev/null
+++ b/lib/configuration/init_global.cpp.in
@@ -0,0 +1,25 @@
+/*
+ * This is a generated file.
+ *
+ * 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/cgit/smolbote.git
+ *
+ * SPDX-License-Identifier: GPL-3.0
+ */
+
+#include "configuration.h"
+
+std::string Configuration::init_global(const std::string &p_path)
+{
+ auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({
+ /* @__DEFAULT_CFG__ */
+ });
+
+ // load the actual configuration file
+ const auto cfgpath = p_path.empty() ? value_map->value<std::string>("poi/config").value() : p_path;
+ value_map->read_file(cfgpath);
+
+ move_global(std::move(value_map));
+ return cfgpath;
+}
diff --git a/lib/configuration/qt_specialization.cpp b/lib/configuration/qt_specialization.cpp
index 8487e62..cd7a99a 100644
--- a/lib/configuration/qt_specialization.cpp
+++ b/lib/configuration/qt_specialization.cpp
@@ -1,36 +1,39 @@
#include "configuration.h"
-#include <stdexcept>
template <>
-callable_when(unconsumed) [[nodiscard]] std::optional<QString> Configuration::value(const char *path) const
+[[nodiscard]] std::optional<QString> Configuration::value(const char *path, std::source_location location) const
{
- const auto v = value<std::string>(path);
- return v ? std::make_optional(QString::fromStdString(v.value())) : std::nullopt;
+ const auto result = value<std::string>(path, location);
+ return result ? std::make_optional(QString::fromStdString(result.value())) : std::nullopt;
}
template <>
-callable_when(unconsumed) [[nodiscard]] std::optional<QStringList> Configuration::value(const char *path) const
+[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path, std::source_location location) const
{
- const auto v = value<std::string>(path);
- return v ? std::make_optional(QString::fromStdString(v.value()).split(';')) : std::nullopt;
+ const auto result = value<std::string>(path, location);
+ return result ? std::make_optional(QString::fromStdString(result.value()).split(';')) : std::nullopt;
}
template <>
-callable_when(unconsumed) QAction &Configuration::shortcut(QAction &action, const char *name) const
+QAction &Configuration::shortcut(QAction &action, const char *name, const std::source_location location) const
{
- if(const auto shortcut = value<QString>(name)) {
+ if(const auto result = value<QString>(name, location)) {
const QString old_tooltip = action.toolTip();
- action.setShortcut(QKeySequence::fromString(shortcut.value()));
- action.setToolTip(QString("%1 (%2)").arg(old_tooltip, shortcut.value()));
+ const auto &result_value = result.value();
+
+ action.setShortcut(QKeySequence::fromString(result_value));
+ action.setToolTip(QString("%1 (%2)").arg(old_tooltip, result_value));
}
return action;
}
template <>
-callable_when(unconsumed) QKeySequence &Configuration::shortcut(QKeySequence &sequence, const char *name) const
+QKeySequence &Configuration::shortcut(QKeySequence &sequence, const char *name, const std::source_location location) const
{
- if(const auto shortcut = value<QString>(name)) {
- sequence = QKeySequence::fromString(shortcut.value());
+ if(const auto result = value<QString>(name, location)) {
+ const auto &result_value = result.value();
+
+ sequence = QKeySequence::fromString(result_value);
}
return sequence;
}
diff --git a/lib/configuration/qt_specialization.h b/lib/configuration/qt_specialization.h
index 9634261..26f9593 100644
--- a/lib/configuration/qt_specialization.h
+++ b/lib/configuration/qt_specialization.h
@@ -5,11 +5,11 @@
#include <QStringList>
template <>
-callable_when(unconsumed) [[nodiscard]] std::optional<QString> Configuration::value(const char *path) const;
+[[nodiscard]] std::optional<QString> Configuration::value(const char *path, std::source_location location) const;
template <>
-callable_when(unconsumed) [[nodiscard]] std::optional<QStringList> Configuration::value(const char *path) const;
+[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path, std::source_location location) const;
template <>
-callable_when(unconsumed) QAction &Configuration::shortcut(QAction &, const char *) const;
+QAction &Configuration::shortcut(QAction &, const char *, const std::source_location) const;
template <>
-callable_when(unconsumed) QKeySequence &Configuration::shortcut(QKeySequence &, const char *) const;
+QKeySequence &Configuration::shortcut(QKeySequence &, const char *, const std::source_location) const;
diff --git a/lib/configuration/test/configuration.cpp b/lib/configuration/test/configuration.cpp
new file mode 100644
index 0000000..0796c11
--- /dev/null
+++ b/lib/configuration/test/configuration.cpp
@@ -0,0 +1,57 @@
+#include "configuration.h"
+#include <gtest/gtest.h>
+
+TEST(Configuration, ctor_empty_initializer_list)
+{
+ Configuration conf({});
+
+ std::cout << conf;
+}
+
+TEST(Configuration, ctor_initializer_list)
+{
+ Configuration conf({
+ { "some_string", "value1" },
+ { "some_bool", true },
+ { "some_int", 42 },
+ });
+
+ // operator<< should not throw exceptions
+ std::cout << conf;
+
+ EXPECT_EQ(*conf.value<std::string>("some_string"), "value1");
+ EXPECT_EQ(*conf.value<bool>("some_bool"), true);
+ EXPECT_EQ(*conf.value<int>("some_int"), 42);
+
+ EXPECT_FALSE(conf.value<int>("no_int"));
+}
+
+TEST(Configuration, read_file)
+{
+ // because the init_list is empty, all types are strings
+ Configuration conf({});
+
+ EXPECT_TRUE(conf.read_file("defaultrc.ini"));
+
+ std::cout << "---------\n";
+ std::cout << conf;
+ std::cout << "---------\n";
+
+ // defaultrc.ini contents
+ EXPECT_EQ(*conf.value<std::string>("name"), "Top level");
+ EXPECT_FALSE(conf.value<std::string>("comment"));
+
+ EXPECT_EQ(*conf.value<std::string>("main/name"), "Section Testing");
+
+ // casting a string to an integer
+ EXPECT_EQ(*conf.value<int>("number"), 12);
+
+ // casting a string to a boolean
+ EXPECT_EQ(*conf.value<std::string>("toggle"), "true");
+ EXPECT_EQ(*conf.value<bool>("toggle"), true);
+ EXPECT_EQ(*conf.value<bool>("main/toggle"), false);
+
+ // extrarc.ini contents
+ EXPECT_EQ(*conf.value<std::string>("over"), "extra");
+ EXPECT_EQ(*conf.value<std::string>("extra/name"), "extra section");
+}
diff --git a/lib/downloads/CMakeLists.txt b/lib/downloads/CMakeLists.txt
new file mode 100644
index 0000000..b310e3a
--- /dev/null
+++ b/lib/downloads/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_library(downloads STATIC
+ downloadsform.ui
+ downloadswidget.cpp downloadswidget.h
+ widgets/downloaditemform.ui widgets/downloaditemwidget.cpp widgets/downloaditemwidget.h
+ widgets/elidedlabel.cpp widgets/elidedlabel.h
+)
+target_link_libraries(downloads PUBLIC Qt6::Widgets Qt6::WebEngineWidgets)
+target_include_directories(downloads PUBLIC ${CMAKE_CURRENT_LIST_DIR})
diff --git a/lib/downloads/downloadswidget.cpp b/lib/downloads/downloadswidget.cpp
index 02ed08a..2f192e9 100644
--- a/lib/downloads/downloadswidget.cpp
+++ b/lib/downloads/downloadswidget.cpp
@@ -28,7 +28,7 @@ DownloadsWidget::~DownloadsWidget()
delete ui;
}
-void DownloadsWidget::addDownload(QWebEngineDownloadItem *item)
+void DownloadsWidget::addDownload(QWebEngineDownloadRequest *item)
{
const QString filepath = QFileDialog::getSaveFileName(this, tr("Save File"), m_downloadPath + "/" + item->downloadFileName());
diff --git a/lib/downloads/downloadswidget.h b/lib/downloads/downloadswidget.h
index eb4ce57..d0aa2b4 100644
--- a/lib/downloads/downloadswidget.h
+++ b/lib/downloads/downloadswidget.h
@@ -10,7 +10,7 @@
#define SMOLBOTE_DOWNLOADDIALOG_H
#include <QDialog>
-#include <QWebEngineDownloadItem>
+#include <QWebEngineDownloadRequest>
namespace Ui
{
@@ -26,7 +26,7 @@ public:
~DownloadsWidget() override;
public slots:
- void addDownload(QWebEngineDownloadItem *item);
+ void addDownload(QWebEngineDownloadRequest *item);
private:
Ui::DownloadDialog *ui;
diff --git a/lib/downloads/meson.build b/lib/downloads/meson.build
deleted file mode 100644
index 9b86391..0000000
--- a/lib/downloads/meson.build
+++ /dev/null
@@ -1,19 +0,0 @@
-downloads_inc = include_directories('.')
-downloads_moc = mod_qt5.preprocess(
- moc_headers: ['downloadswidget.h', 'widgets/downloaditemwidget.h', 'widgets/elidedlabel.h'],
- ui_files: ['downloadsform.ui', 'widgets/downloaditemform.ui'],
- dependencies: dep_qt5
-)
-
-downloads_lib = static_library('downloads',
- ['downloadswidget.cpp', downloads_moc,
- 'widgets/downloaditemwidget.cpp', 'widgets/elidedlabel.cpp'],
- dependencies: dep_qt5
-)
-
-dep_downloads = declare_dependency(
- include_directories: downloads_inc,
- link_with: downloads_lib,
- sources: ['downloadswidget.cpp', downloads_moc,
- 'widgets/downloaditemwidget.cpp', 'widgets/elidedlabel.cpp']
-)
diff --git a/lib/downloads/widgets/downloaditemwidget.cpp b/lib/downloads/widgets/downloaditemwidget.cpp
index e0c8a60..169ba6f 100644
--- a/lib/downloads/widgets/downloaditemwidget.cpp
+++ b/lib/downloads/widgets/downloaditemwidget.cpp
@@ -30,7 +30,7 @@ inline QString sizeString(qint64 size)
return QString("%1 GB").arg(size / (1024 * 1024 * 1024));
}
-DownloadItemWidget::DownloadItemWidget(QWebEngineDownloadItem *m_item, QWidget *parent)
+DownloadItemWidget::DownloadItemWidget(QWebEngineDownloadRequest *m_item, QWidget *parent)
: QWidget(parent)
, ui(new Ui::DownloadItemForm)
{
@@ -51,11 +51,11 @@ DownloadItemWidget::DownloadItemWidget(QWebEngineDownloadItem *m_item, QWidget *
ui->path_label->setText(QString("%1<br>%2").arg(item->downloadDirectory(), item->downloadFileName()));
this->updateState(item->state());
- connect(item, &QWebEngineDownloadItem::stateChanged, this, &DownloadItemWidget::updateState);
- connect(item, &QWebEngineDownloadItem::downloadProgress, this, &DownloadItemWidget::updateProgress);
- connect(item, &QWebEngineDownloadItem::finished, this, &DownloadItemWidget::updateFinished);
+ connect(item, &QWebEngineDownloadRequest::stateChanged, this, &DownloadItemWidget::updateState);
+ connect(item, &QWebEngineDownloadRequest::receivedBytesChanged, this, &DownloadItemWidget::updateProgress);
+ connect(item, &QWebEngineDownloadRequest::isFinishedChanged, this, &DownloadItemWidget::updateFinished);
- connect(ui->abort_toolButton, &QToolButton::clicked, item, &QWebEngineDownloadItem::cancel);
+ connect(ui->abort_toolButton, &QToolButton::clicked, item, &QWebEngineDownloadRequest::cancel);
connect(ui->pause_toolButton, &QToolButton::clicked, item, [m_item](bool clicked) {
clicked ? m_item->pause() : m_item->resume();
});
@@ -69,34 +69,34 @@ DownloadItemWidget::~DownloadItemWidget()
delete ui;
}
-void DownloadItemWidget::updateState(QWebEngineDownloadItem::DownloadState state)
+void DownloadItemWidget::updateState(QWebEngineDownloadRequest::DownloadState state)
{
switch(state) {
- case QWebEngineDownloadItem::DownloadRequested:
+ case QWebEngineDownloadRequest::DownloadRequested:
ui->status_label->setText(tr("Requested"));
ui->pause_toolButton->setEnabled(true);
ui->abort_toolButton->setEnabled(true);
ui->open_toolButton->setEnabled(false);
break;
- case QWebEngineDownloadItem::DownloadInProgress:
+ case QWebEngineDownloadRequest::DownloadInProgress:
ui->status_label->setText(tr("In progress"));
ui->pause_toolButton->setEnabled(true);
ui->abort_toolButton->setEnabled(true);
ui->open_toolButton->setEnabled(false);
break;
- case QWebEngineDownloadItem::DownloadCompleted:
+ case QWebEngineDownloadRequest::DownloadCompleted:
ui->status_label->setText(tr("Completed"));
ui->pause_toolButton->setEnabled(false);
ui->abort_toolButton->setEnabled(false);
ui->open_toolButton->setEnabled(true);
break;
- case QWebEngineDownloadItem::DownloadCancelled:
+ case QWebEngineDownloadRequest::DownloadCancelled:
ui->status_label->setText(tr("Cancelled"));
ui->pause_toolButton->setEnabled(false);
ui->abort_toolButton->setEnabled(false);
ui->open_toolButton->setEnabled(false);
break;
- case QWebEngineDownloadItem::DownloadInterrupted:
+ case QWebEngineDownloadRequest::DownloadInterrupted:
ui->status_label->setText(tr("Interrupted"));
ui->pause_toolButton->setEnabled(false);
ui->abort_toolButton->setEnabled(false);
@@ -107,8 +107,11 @@ void DownloadItemWidget::updateState(QWebEngineDownloadItem::DownloadState state
}
}
-void DownloadItemWidget::updateProgress(qint64 value, qint64 total)
+void DownloadItemWidget::updateProgress()
{
+ const auto value = item->receivedBytes();
+ const auto total = item->totalBytes();
+
ui->progressBar->setValue(static_cast<int>((static_cast<long double>(value) / static_cast<long double>(total)) * 100));
ui->progressBar->setFormat(QString("%1 / %2").arg(sizeString(value), sizeString(total)));
}
diff --git a/lib/downloads/widgets/downloaditemwidget.h b/lib/downloads/widgets/downloaditemwidget.h
index a1de175..5d540a3 100644
--- a/lib/downloads/widgets/downloaditemwidget.h
+++ b/lib/downloads/widgets/downloaditemwidget.h
@@ -9,7 +9,7 @@
#ifndef SMOLBOTE_DOWNLOADITEMFORM_H
#define SMOLBOTE_DOWNLOADITEMFORM_H
-#include <QWebEngineDownloadItem>
+#include <QWebEngineDownloadRequest>
#include <QWidget>
namespace Ui
@@ -22,17 +22,17 @@ class DownloadItemWidget : public QWidget
Q_OBJECT
public:
- explicit DownloadItemWidget(QWebEngineDownloadItem *m_item, QWidget *parent = 0);
+ explicit DownloadItemWidget(QWebEngineDownloadRequest *m_item, QWidget *parent = 0);
~DownloadItemWidget() override;
private slots:
- void updateState(QWebEngineDownloadItem::DownloadState state);
- void updateProgress(qint64 value, qint64 total);
+ void updateState(QWebEngineDownloadRequest::DownloadState state);
+ void updateProgress();
void updateFinished();
private:
Ui::DownloadItemForm *ui;
- QWebEngineDownloadItem *item = nullptr;
+ QWebEngineDownloadRequest *item = nullptr;
};
#endif // SMOLBOTE_DOWNLOADITEMFORM_H
diff --git a/lib/pluginloader/CMakeLists.txt b/lib/pluginloader/CMakeLists.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/pluginloader/CMakeLists.txt
diff --git a/lib/session_formats/CMakeLists.txt b/lib/session_formats/CMakeLists.txt
new file mode 100644
index 0000000..c043559
--- /dev/null
+++ b/lib/session_formats/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_library(session_formats STATIC
+ session_json.cpp session_json.hpp
+)
+target_link_libraries(session_formats PUBLIC Qt6::Core)
+target_include_directories(session_formats PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${PROJECT_SOURCE_DIR}/include)
diff --git a/lib/urlfilter/CMakeLists.txt b/lib/urlfilter/CMakeLists.txt
new file mode 100644
index 0000000..012839d
--- /dev/null
+++ b/lib/urlfilter/CMakeLists.txt
@@ -0,0 +1,27 @@
+add_library(urlfilter STATIC
+ matcher.h urlfilter.h
+ adblock/adblocklist.cpp adblock/adblocklist.h
+ adblock/parser.cpp adblock/parser.h
+ hostlist/hostlist.cpp hostlist/hostlist.h
+)
+target_link_libraries(urlfilter PUBLIC Qt6::WebEngineCore)
+target_include_directories(urlfilter PUBLIC ${CMAKE_CURRENT_LIST_DIR})
+
+
+add_executable(test_urlfilter_matcher test/matcher.cpp)
+target_link_libraries(test_urlfilter_matcher PUBLIC urlfilter GTest::gtest_main)
+gtest_add_tests(TARGET test_urlfilter_matcher
+ SOURCES test/matcher.cpp
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/test)
+
+add_executable(test_urlfilter_hostlist test/hostlist.cpp)
+target_link_libraries(test_urlfilter_hostlist PUBLIC urlfilter GTest::gtest_main)
+gtest_add_tests(TARGET test_urlfilter_hostlist
+ SOURCES test/hostlist.cpp
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/test)
+
+add_executable(test_urlfilter_adblock test/adblock.cpp)
+target_link_libraries(test_urlfilter_adblock PUBLIC urlfilter GTest::gtest_main)
+gtest_add_tests(TARGET test_urlfilter_adblock
+ SOURCES test/adblock.cpp
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/test)
diff --git a/lib/urlfilter/meson.build b/lib/urlfilter/meson.build
deleted file mode 100644
index 2591028..0000000
--- a/lib/urlfilter/meson.build
+++ /dev/null
@@ -1,26 +0,0 @@
-urlfilter_lib = static_library('urlfilter',
- ['urlfilter.h', 'matcher.h',
- 'hostlist/hostlist.cpp', 'hostlist/hostlist.h',
- 'adblock/adblocklist.cpp', 'adblock/adblocklist.h', 'adblock/parser.cpp', 'adblock/parser.h'],
- dependencies: dep_qt5
-)
-
-dep_urlfilter = declare_dependency(
- include_directories: include_directories('.'),
- link_with: urlfilter_lib
-)
-
-if dep_gtest.found()
- test('urlfilter: matcher',
- executable('urlfilter-matcher', dependencies: [dep_qt5, dep_gtest, dep_urlfilter], sources: ['test/matcher.cpp']),
- workdir: meson.current_source_dir() / 'test'
- )
- test('urlfilter: host list',
- executable('urlfilter-hostlist', dependencies: [dep_qt5, dep_gtest, dep_urlfilter], sources: ['test/hostlist.cpp']),
- workdir: meson.current_source_dir() / 'test'
- )
- test('urlfilter: adblock list',
- executable('urlfilter-adblocklist', dependencies: [dep_qt5, dep_gtest, dep_urlfilter], sources: ['test/adblock.cpp']),
- workdir: meson.current_source_dir() / 'test'
- )
-endif