diff options
Diffstat (limited to 'lib')
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 §ion) +inline std::optional<Configuration::kv_pair> parse_line(const std::string &line, /* in/out */ std::string §ion) { - 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 |