diff options
74 files changed, 700 insertions, 798 deletions
@@ -1,13 +1,4 @@ -# kdevelop -build* -*.kdev4 - -# qtcreator -*.user - -subprojects/* -!subprojects/*.wrap -!subprojects/packagefiles +third-party lang/*.qm .config diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c7147c4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,85 @@ +cmake_minimum_required(VERSION 3.18) + +project(smolbote VERSION 0.1.0 LANGUAGES CXX) + +include(FeatureSummary) +include(GNUInstallDirs) +include(cmake/StandardProjectSettings.cmake) +include(cmake/CompilerWarnings.cmake) +include(cmake/Sanitize.cmake) +include(cmake/ThirdParty.cmake) + +option(b_manpages "Build manpages (requires scdoc" OFF) +option(b_translations "Build translations" OFF) +option(b_tests "Build tests" ON) + +# TODO +#option(b_signPlugins "Generate OpenSSL signing key and sign plugins" ON) + +if(b_manpages) + add_subdirectory(doc/man) +endif() + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) + +if(b_tests) + enable_testing() +endif() +enable_warnings() + +find_package(Qt5 COMPONENTS Widgets Svg Network WebEngine WebEngineWidgets REQUIRED) +find_package(spdlog REQUIRED) +add_compile_options(-DSPDLOG_FMT_EXTERNAL) +find_package(Catch2) +find_package(OpenSSL REQUIRED) + +download_third_party(SingleApplication-3.1.5 + "https://github.com/itay-grudev/SingleApplication/archive/v3.1.5.tar.gz" singleapplication-v3.1.5.tar.gz + SHA256 09b1e088dae8cf69187262554819b77f4ca7b65576b3f39c5b6885823e8a2dbb) +set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication") +add_subdirectory(third-party/SingleApplication-3.1.5) + +download_third_party(rcc-0.1.2 + https://neueland.iserlohn-fortress.net/cgit/rcc/snapshot/rcc-0.1.2.tar.xz rcc-0.1.2.tar.xz + SHA256 5ee18b94401b720e6e65d8e0e38dd6ea23cab7ae4727742be313530969a69d50) +set(RCC ${CMAKE_SOURCE_DIR}/third-party/rcc-0.1.2/rcc) + +download_third_party(tabler-icons-1.34.0 + https://github.com/tabler/tabler-icons/archive/v1.34.0.tar.gz v1.34.0.tar.gz + SHA256 bc74e5bd28531445f2e50df44f3688b1116397a25a0086e6944ab52260b70ffd) +set(ICONS_PATH ${CMAKE_SOURCE_DIR}/third-party/tabler-icons-1.34.0) + +add_subdirectory(lib/bookmarks) +add_subdirectory(lib/configuration) +add_subdirectory(lib/downloads) +add_subdirectory(lib/pluginloader) +add_subdirectory(lib/session_formats) +add_subdirectory(lib/smolblok) +add_subdirectory(src) + +add_subdirectory(plugins/HostlistFilter) + +# TODO +#add_subdirectory(lang) + +add_subdirectory(linux) + +feature_summary(WHAT ALL) +message(STATUS "Project + name: ${CMAKE_PROJECT_NAME} + version: ${CMAKE_PROJECT_VERSION}") +message(STATUS "Compiler + id: ${CMAKE_CXX_COMPILER_ID} + version: ${CMAKE_CXX_COMPILER_VERSION} + compiler: ${CMAKE_CXX_COMPILER}") +message(STATUS "Install paths + prefix: ${CMAKE_INSTALL_PREFIX} + bindir: ${CMAKE_INSTALL_BINDIR} + libdir: ${CMAKE_INSTALL_LIBDIR} + datadir: ${CMAKE_INSTALL_DATADIR} + mandir: ${CMAKE_INSTALL_MANDIR}") +message(STATUS "Build options + manpages: ${b_manpages} + i18n: ${b_translations} + tests: ${b_tests}") @@ -37,7 +37,7 @@ It's a small boat. It says poi. Required dependencies - latest stable [Qt](https://www.qt.io/) -- latest stable [meson](https://mesonbuild.com/) +- [cmake](https://www.cmake.org/) 3.18+ - A compiler with C++2a support ``` @@ -45,11 +45,10 @@ Required dependencies git clone git://neueland.iserlohn-fortress.net/smolbote # configure -mkdir build -meson build +cmake -S smolbote -B smolbote.build # make -ninja -C build +cmake --build smolbote.build ``` ## It doesn't work, what now? diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake new file mode 100644 index 0000000..c53660f --- /dev/null +++ b/cmake/CompilerWarnings.cmake @@ -0,0 +1,77 @@ +# Based on: +# https://github.com/lefticus/cpp_starter_project/blob/master/cmake/CompilerWarnings.cmake +# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md + +function(enable_warnings) + # only enable warnings for debug builds + if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug") + return() + endif() + + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + + set(BASE_WARNINGS + -Wall # reasonable and standard + -Wextra + -Werror=pedantic # warn if non-standard C++ is used + + -Wunused # warn on anything being unused + -Wshadow # warn the user if a variable declaration shadows one from a parent context + + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. + # This helps catch hard to track down memory errors + -Werror=redundant-decls + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Werror=return-type + + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + + -Wconsumed + #-Wlifetime + -mspeculative-load-hardening # Spectre v1 mitigation + + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + #-Wduplicated-cond # warn if if / else chain has duplicated conditions + #-Wduplicated-branches # warn if if / else branches have duplicated code + #-Wlogical-op # warn about logical operations being used where bitwise were probably wanted + #-Wuseless-cast # warn if you perform a cast to the same type + ) + + if(MSVC) + add_compile_options(${MSVC_WARNINGS}) + message(STATUS "added ${MSVC_WARNINGS}") + else() + add_compile_options(${BASE_WARNINGS}) + message(STATUS "added ${BASE_WARNINGS}") + endif() +endfunction() diff --git a/cmake/Sanitize.cmake b/cmake/Sanitize.cmake new file mode 100644 index 0000000..29f7fa5 --- /dev/null +++ b/cmake/Sanitize.cmake @@ -0,0 +1,33 @@ +include(CheckCXXCompilerFlag) +include(CheckLinkerFlag) + +check_linker_flag(CXX -fsanitize=address cxx_asan) +check_cxx_compiler_flag(-fsanitize=leak cxx_lsan) + +function(target_sanitize target_name) + option(sanitize_address "Use address sanitizer" ${cxx_asan}) + option(sanitize_leak "Use leak sanitizer" ${cxx_lsan}) + + if(sanitize_address) + message(">>> using asan on ${target_name}") + target_compile_options(${target_name} PRIVATE -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer) + target_link_options(${target_name} PRIVATE -fsanitize=address) + endif() + + if(sanitize_leak) + message(">>> using lsan on ${target_name}") + target_compile_options(${target_name} PRIVATE -fsanitize=leak -fno-omit-frame-pointer) + target_link_options(${target_name} PRIVATE -fsanitize=leak) + endif() +endfunction() + +function(target_sanitize_fuzzer target_name) + if(NOT ${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + message("Cannot sanitize with ${CMAKE_CXX_COMPILER_ID} (needs clang)") + return() + endif() + + set_target_properties(${target_name} PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=fuzzer" + LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=fuzzer") +endfunction() diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake new file mode 100644 index 0000000..bd88a73 --- /dev/null +++ b/cmake/StandardProjectSettings.cmake @@ -0,0 +1,44 @@ +# from here: +# https://github.com/lefticus/cpp_starter_project/blob/master/cmake/StandardProjectSettings.cmake + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Set a default build type if none was specified +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE + RelWithDebInfo + CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui, ccmake + set_property( + CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo") +endif() + +# Generate compile_commands.json to make it easier to work with clang based tools +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF) +if(ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported(RESULT result OUTPUT output) + if(result) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "IPO is not supported: ${output}") + endif() +endif() + +option(VCS_TAG "Read version information from git" ON) +if(VCS_TAG) + find_program(VCS git) + execute_process(COMMAND git describe --abbrev=0 OUTPUT_VARIABLE CMAKE_PROJECT_SHORT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND git describe --long --abbrev=40 OUTPUT_VARIABLE CMAKE_PROJECT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + set(CMAKE_PROJECT_SHORT_VERSION ${CMAKE_PROJECT_VERSION}) +endif()
\ No newline at end of file diff --git a/cmake/ThirdParty.cmake b/cmake/ThirdParty.cmake new file mode 100644 index 0000000..8e5b1cc --- /dev/null +++ b/cmake/ThirdParty.cmake @@ -0,0 +1,17 @@ +function(download_third_party path url archive hash_type hash) + + if(NOT EXISTS ${CMAKE_SOURCE_DIR}/third-party/${path}) + + if(NOT EXISTS ${CMAKE_BINARY_DIR}/${archive}) + message("${CMAKE_BINARY_DIR}/${archive} missing") + message("Downloading ${url}...") + file(DOWNLOAD ${url} ${CMAKE_BINARY_DIR}/${archive} + TIMEOUT 60 TLS_VERIFY ON + EXPECTED_HASH ${hash_type}=${hash}) + endif() + + file(ARCHIVE_EXTRACT INPUT ${CMAKE_BINARY_DIR}/${archive} + DESTINATION ${CMAKE_SOURCE_DIR}/third-party) + endif() + +endfunction() diff --git a/cmake/lcov.cmake b/cmake/lcov.cmake new file mode 100644 index 0000000..d6f990d --- /dev/null +++ b/cmake/lcov.cmake @@ -0,0 +1,4 @@ +function(target_lcov target_name) + target_compile_options(${target_name} INTERFACE --coverage -O0 -g) + target_link_libraries(${target_name} INTERFACE --coverage) +endfunction() diff --git a/doc/man/CMakeLists.txt b/doc/man/CMakeLists.txt new file mode 100644 index 0000000..309ff7c --- /dev/null +++ b/doc/man/CMakeLists.txt @@ -0,0 +1,9 @@ +set(MANPAGES smolbote.1;smolbote-profile.5;smolboterc.5) + +find_program(SCDOC scdoc) +foreach(F ${MANPAGES}) + add_custom_command(OUTPUT ${F} COMMAND ${SCDOC} < ${CMAKE_CURRENT_SOURCE_DIR}/${F}.scd > ${F} VERBATIM) +endforeach() + +add_custom_target(man DEPENDS ${MANPAGES}) +install(FILES smolbote.1 DESTINATION /usr/local/man) diff --git a/doc/meson.build b/doc/meson.build deleted file mode 100644 index 6490969..0000000 --- a/doc/meson.build +++ /dev/null @@ -1,16 +0,0 @@ -if not get_option('manpage') - subdir_done() -endif - -sh = find_program('sh', required: true, native: true, disabler: true) - -foreach f : [ 'smolbote.1', 'smolboterc.5', 'smolbote-profile.5' ] -manpage = custom_target(f, - input: 'man'/f+'.scd', - output: '@BASENAME@', - capture: true, - command: [ sh, meson.current_source_dir()/'man/genroff.sh', '@INPUT@' ], - install: true, - install_dir: get_option('mandir') -) -endforeach diff --git a/include/meson.build b/include/meson.build deleted file mode 100644 index 1372c86..0000000 --- a/include/meson.build +++ /dev/null @@ -1,7 +0,0 @@ -plugininterfaces_include = include_directories('.') -smolbote_include = include_directories('.') - -install_headers('smolbote/plugininterface.hpp', 'smolbote/filterinterface.hpp', 'smolbote/session.hpp', - subdir: 'smolbote' -) - diff --git a/lang/CMakeLists.txt b/lang/CMakeLists.txt new file mode 100644 index 0000000..319c706 --- /dev/null +++ b/lang/CMakeLists.txt @@ -0,0 +1,10 @@ +# https://wiki.qt.io/How_to_create_a_multi_language_application + +# generating .ts files +# lupdate -verbose src/ -ts output.ts + +# updating .ts files +# lupdate -verbose -no-obsolete src/ -ts output.ts + +# creating the binary language files (.qm) +# lrelease -compress -removeidentical input.ts [-qm output.qm] diff --git a/lang/meson.build b/lang/meson.build deleted file mode 100644 index 8c4a820..0000000 --- a/lang/meson.build +++ /dev/null @@ -1,4 +0,0 @@ - -# translations -mod_qt5.compile_translations(ts_files: 'bg.ts', install: get_option('translations').enabled(), install_dir: get_option('datadir') / 'smolbote/translations' , build_by_default: false) - diff --git a/lib/bookmarks/CMakeLists.txt b/lib/bookmarks/CMakeLists.txt new file mode 100644 index 0000000..50c2942 --- /dev/null +++ b/lib/bookmarks/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(bookmarks STATIC + bookmarkmodel.h + bookmarkformat.cpp bookmarkitem.cpp bookmarkmodel.cpp + formats/xbel.cpp formats/ffjson.cpp) +target_link_libraries(bookmarks PUBLIC Qt5::Widgets) +target_include_directories(bookmarks PUBLIC .) 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..6484a70 --- /dev/null +++ b/lib/configuration/CMakeLists.txt @@ -0,0 +1,24 @@ +add_library(configuration STATIC configuration.cpp qt_specialization.cpp) +target_link_libraries(configuration PUBLIC Qt5::Widgets) +target_include_directories(configuration INTERFACE .) + +add_executable(conf_parser test/main.cpp) +target_compile_definitions(conf_parser PRIVATE NO_QT_SPEC) +target_sanitize(conf_parser) +target_link_libraries(conf_parser PRIVATE configuration Catch2::Catch2) + +add_executable(conf_parser_qt test/qt.cpp) +target_link_libraries(conf_parser_qt PRIVATE configuration Catch2::Catch2) + +add_test(NAME conf_parser COMMAND conf_parser + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/test") +add_test(NAME conf_parser_qt COMMAND conf_parser_qt -platform offscreen + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/test") +set_tests_properties(conf_parser PROPERTIES ENVIRONMENT "CONFIGFILE=${CMAKE_CURRENT_SOURCE_DIR}/test/defaultrc.ini") +set_tests_properties(conf_parser_qt PROPERTIES ENVIRONMENT "CONFIGFILE=${CMAKE_CURRENT_SOURCE_DIR}/test/defaultrc.ini") + +if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + add_executable(conf_fuzzer configuration.cpp) + target_compile_definitions(conf_fuzzer PRIVATE FUZZER NO_QT_SPEC) + target_sanitize_fuzzer(conf_fuzzer) +endif() diff --git a/lib/configuration/configuration.cpp b/lib/configuration/configuration.cpp index 66617ed..d11b342 100644 --- a/lib/configuration/configuration.cpp +++ b/lib/configuration/configuration.cpp @@ -10,19 +10,18 @@ #include <algorithm> #include <fstream> #include <iostream> -#include <sstream> #include <stdexcept> #ifndef NO_QT_SPEC #include <QStandardPaths> #endif -static Configuration *s_conf = nullptr; +static const Configuration *s_conf = nullptr; Configuration::Configuration() : use_global(true) { - if(!s_conf) { + if(s_conf == nullptr) { throw std::runtime_error("Trying to use default Configuration, but none has been set!"); } } @@ -139,8 +138,7 @@ void Configuration::read(std::basic_istream<char> &input) void Configuration::setValue(const std::string &key, const std::string &value) { if(use_global) { - s_conf->setValue(key, value); - return; + throw std::runtime_error("Global configuration is read-only!"); } if(this->count(key) == 0) { @@ -167,7 +165,7 @@ bool Configuration::make_global() return true; } -Configuration *Configuration::instance() +const Configuration *Configuration::instance() { return s_conf; } diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h index af55f62..a80d8e5 100644 --- a/lib/configuration/configuration.h +++ b/lib/configuration/configuration.h @@ -29,7 +29,7 @@ #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; @@ -131,7 +131,7 @@ public: bool make_global(); private: - static Configuration *instance(); + static const Configuration *instance(); const std::string m_homePath; const bool use_global = false; diff --git a/lib/configuration/meson.build b/lib/configuration/meson.build deleted file mode 100644 index 5e3e4b2..0000000 --- a/lib/configuration/meson.build +++ /dev/null @@ -1,22 +0,0 @@ -dep_configuration = declare_dependency( - include_directories: include_directories('.'), - link_with: static_library('configuration', ['configuration.cpp', 'qt_specialization.cpp'], dependencies: dep_qt5) -) - -test('conf parser', executable('configuration-parser', - sources: [ 'test/main.cpp' ], - dependencies: [ dep_qt5, dep_catch, dep_configuration ] - ), - env: 'CONFIGFILE='+meson.current_source_dir()/'test/defaultrc.ini', - args: [ '-platform', 'offscreen' ], - workdir: meson.current_source_dir()/'test' -) - -if meson.get_compiler('cpp').has_multi_arguments('-g', '-fsanitize=fuzzer') -executable('configuration-fuzzer', - sources: 'configuration.cpp', - cpp_args: [ '-g', '-fsanitize=fuzzer', '-DNO_QT_SPEC', '-DFUZZER' ], - link_args: [ '-fsanitize=fuzzer' ] -# args: [ '-seed=1', '-max_total_time=24', meson.current_source_dir()/'test/corpus' ] -) -endif diff --git a/lib/configuration/test/main.cpp b/lib/configuration/test/main.cpp index d83f7af..9c83f8b 100644 --- a/lib/configuration/test/main.cpp +++ b/lib/configuration/test/main.cpp @@ -1,9 +1,7 @@ -#define CATCH_CONFIG_RUNNER - // clazy:excludeall=non-pod-global-static +#define CATCH_CONFIG_MAIN #include "configuration.h" -#include <QApplication> #include <catch2/catch.hpp> SCENARIO("Configuration") @@ -32,7 +30,7 @@ SCENARIO("Configuration") WHEN("reading default values") { REQUIRE(conf.value<std::string>("name")); - REQUIRE(conf.value<std::string>("name").value() == std::string()); + REQUIRE(conf.value<std::string>("name").value().empty()); REQUIRE(conf.value<int>("number")); REQUIRE(conf.value<int>("number").value() == 0); REQUIRE(conf.value<bool>("toggle")); @@ -43,7 +41,7 @@ SCENARIO("Configuration") REQUIRE(!conf.value<std::string>("nullopt")); REQUIRE(conf.value<std::string>("main/name")); - REQUIRE(conf.value<std::string>("main/name").value() == std::string()); + REQUIRE(conf.value<std::string>("main/name").value().empty()); REQUIRE(conf.value<int>("main/number")); REQUIRE(conf.value<int>("main/number").value() == 0); REQUIRE(conf.value<bool>("main/toggle")); @@ -101,30 +99,6 @@ SCENARIO("Configuration") REQUIRE(conf.value<std::string>("toggle").value() == "true"); REQUIRE(conf.value<std::string>("main/toggle").value() == "false"); } - - THEN("Qt cast specialization") - { - REQUIRE(conf.value<QString>("name").value() == "Top level"); - REQUIRE(conf.value<QString>("number").value() == "12"); - REQUIRE(conf.value<QString>("toggle").value() == "true"); - REQUIRE(conf.value<QString>("main/toggle").value() == "false"); - REQUIRE(!conf.value<QString>("nullopt")); - - REQUIRE(conf.value<QStringList>("list").value() == QStringList({ "one", "two", "three", "for four" })); - REQUIRE(!conf.value<QStringList>("nullopt")); - } - - THEN("Qt shortcut") - { - REQUIRE(conf.value<std::string>("qt/shortcut") == "Ctrl+Q"); - QAction action; - REQUIRE(conf.shortcut<QAction>(action, "qt/shortcut").shortcut().toString() == "Ctrl+Q"); - REQUIRE(conf.shortcut<QAction>(action, "qt/nil").shortcut().toString() == "Ctrl+Q"); - - QKeySequence sequence; - REQUIRE(conf.shortcut<QKeySequence>(sequence, "qt/shortcut").toString() == "Ctrl+Q"); - REQUIRE(conf.shortcut<QKeySequence>(sequence, "qt/nil").toString() == "Ctrl+Q"); - } } } @@ -167,10 +141,3 @@ SCENARIO("Configuration") } } } - -int main(int argc, char **argv) -{ - QApplication app(argc, argv); - int result = Catch::Session().run(argc, argv); - return result; -} diff --git a/lib/configuration/test/qt.cpp b/lib/configuration/test/qt.cpp new file mode 100644 index 0000000..44114df --- /dev/null +++ b/lib/configuration/test/qt.cpp @@ -0,0 +1,71 @@ +// clazy:excludeall=non-pod-global-static +#define CATCH_CONFIG_RUNNER + +#include "configuration.h" +#include <QApplication> +#include <catch2/catch.hpp> + +SCENARIO("Configuration") +{ + GIVEN("a Configuration object with some initial values") + { + Configuration conf{ + { "name", std::string() }, + { "over", std::string() }, + // this entry is not in the conf file + { "other", std::string("not in cfg") }, + // commented out entry in the conf file + { "comment", std::string("123.456") }, + { "number", 0 }, + { "toggle", false }, + + { "main/name", std::string() }, + { "main/number", 0 }, + { "main/toggle", true }, + + { "extra/name", std::string() }, + { "extra/number", 0 }, + { "extra/toggle", false }, + }; + + WHEN("reading default values") + { + } + + WHEN("reading configuration file") + { + conf.read_file(std::getenv("CONFIGFILE")); + + THEN("Qt cast specialization") + { + REQUIRE(conf.value<QString>("name").value() == "Top level"); + REQUIRE(conf.value<QString>("number").value() == "12"); + REQUIRE(conf.value<QString>("toggle").value() == "true"); + REQUIRE(conf.value<QString>("main/toggle").value() == "false"); + REQUIRE(!conf.value<QString>("nullopt")); + + REQUIRE(conf.value<QStringList>("list").value() == QStringList({ "one", "two", "three", "for four" })); + REQUIRE(!conf.value<QStringList>("nullopt")); + } + + THEN("Qt shortcut") + { + REQUIRE(conf.value<std::string>("qt/shortcut") == "Ctrl+Q"); + QAction action; + REQUIRE(conf.shortcut<QAction>(action, "qt/shortcut").shortcut().toString() == "Ctrl+Q"); + REQUIRE(conf.shortcut<QAction>(action, "qt/nil").shortcut().toString() == "Ctrl+Q"); + + QKeySequence sequence; + REQUIRE(conf.shortcut<QKeySequence>(sequence, "qt/shortcut").toString() == "Ctrl+Q"); + REQUIRE(conf.shortcut<QKeySequence>(sequence, "qt/nil").toString() == "Ctrl+Q"); + } + } + } +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/lib/downloads/CMakeLists.txt b/lib/downloads/CMakeLists.txt new file mode 100644 index 0000000..984d332 --- /dev/null +++ b/lib/downloads/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(downloads + downloadswidget.h downloadswidget.cpp downloadsform.ui + widgets/downloaditemwidget.h widgets/downloaditemwidget.cpp widgets/downloaditemform.ui + widgets/elidedlabel.h widgets/elidedlabel.cpp) +target_link_libraries(downloads PUBLIC Qt5::WebEngineWidgets) +target_include_directories(downloads PUBLIC .) 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/pluginloader/CMakeLists.txt b/lib/pluginloader/CMakeLists.txt new file mode 100644 index 0000000..e0c8270 --- /dev/null +++ b/lib/pluginloader/CMakeLists.txt @@ -0,0 +1,54 @@ +find_program(SSL openssl) +find_program(PYTHON python3) + +# generate a keypair +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/keypair.pem" + COMMAND ${SSL} genrsa -out "${CMAKE_CURRENT_BINARY_DIR}/keypair.pem" 4096) + +# export public key +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pubkey.pem" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/keypair.pem" + COMMAND ${SSL} rsa -in "${CMAKE_CURRENT_BINARY_DIR}/keypair.pem" -pubout -out "${CMAKE_CURRENT_BINARY_DIR}/pubkey.pem") + +# turn the public key into a header +add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/publicKey.h" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pubkey.pem" + COMMAND ${PYTHON} "${CMAKE_CURRENT_SOURCE_DIR}/ssl-keygen.py" + --private "${CMAKE_CURRENT_BINARY_DIR}/keypair.pem" + --public "${CMAKE_CURRENT_BINARY_DIR}/pubkey.pem" + --output "${CMAKE_CURRENT_BINARY_DIR}/publicKey.h" --array-name=publicKey_pem) + +add_library(pluginloader STATIC pluginloader.h pluginloader.cpp "${CMAKE_CURRENT_BINARY_DIR}/publicKey.h") +target_link_libraries(pluginloader PUBLIC OpenSSL::SSL Qt5::Core) +target_include_directories(pluginloader PUBLIC . PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + +## Testing +# sigmatch +add_executable(pluginloader_sigmatch test/pluginloader-sigmatch.cpp) +target_link_libraries(pluginloader_sigmatch PRIVATE pluginloader Catch2::Catch2 fmt) +#target_sanitize(pluginloader_sigmatch) + +# load +add_executable(pluginloader_load test/pluginloader-load.cpp) +target_link_libraries(pluginloader_load PRIVATE pluginloader Catch2::Catch2 fmt) +target_sanitize(pluginloader_load) + +# generate a random file and properly sign it +add_test(NAME good.dat COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/write-random.py --output=good.dat) +add_test(NAME good.dat.sig COMMAND ${SSL} dgst -sha256 -sign=keypair.pem -out=good.dat.sig good.dat) +set_tests_properties(good.dat.sig PROPERTIES DEPENDS good.dat) +# generate a random file and improperly sign it +add_test(NAME bad.dat COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/write-random.py --output=bad.dat) +add_test(NAME bad.dat.sig COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/write-random.py --output=bad.dat.sig) +# generate a random file and don't sign it +add_test(NAME none.dat COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/write-random.py --output=none.dat) + +add_test(NAME pluginloader_sigmatch COMMAND pluginloader_sigmatch) +set_tests_properties(pluginloader_sigmatch PROPERTIES + DEPENDS "good.dat;good.dat.sig;bad.dat;bad.dat.sig;none.dat" + REQUIRED_FILES "good.dat;good.dat.sig;bad.dat;bad.dat.sig;none.dat" + ENVIRONMENT "SIGNEDFILE=${CMAKE_CURRENT_BINARY_DIR}/good.dat;UNSIGNEDFILE=${CMAKE_CURRENT_BINARY_DIR}/none.dat;BADSIGNEDFILE=${CMAKE_CURRENT_BINARY_DIR}/bad.dat") + +# make sure this fails when no plugin or an invalid file is passed +#test('load', poi_plugin_loader, suite: 'pluginloader', should_fail: true) +#test('load', poi_plugin_loader, suite: 'pluginloader', args: files('meson.build'), should_fail: true) diff --git a/lib/pluginloader/meson.build b/lib/pluginloader/meson.build deleted file mode 100644 index 5e7c39c..0000000 --- a/lib/pluginloader/meson.build +++ /dev/null @@ -1,68 +0,0 @@ -python = import('python') -python3 = python.find_installation('python3') - -openssl = find_program('openssl', required: true) - -private_pem = custom_target('privateKey.pem', - output: 'privateKey.pem', - command: [ openssl, 'genrsa', '-out', '@OUTPUT@', '4096' ] -) - -public_pem = custom_target('publicKey.pem', - input: private_pem, - output: 'publicKey.pem', - command: [ openssl, 'rsa', '-in', '@INPUT@', '-pubout', '-out', '@OUTPUT@' ] -) - -publicKey_h = custom_target('publicKey_h', - input: files('ssl-keygen.py'), - output: 'publicKey.h', - command: [python3, '@INPUT@', - '--private', private_pem, '--public', public_pem, - '--output=@OUTPUT@', '--array-name=publicKey_pem'] -) - -dep_pluginloader = declare_dependency( - include_directories: include_directories('.'), - link_with: static_library('plugin', - ['pluginloader.cpp', publicKey_h], - include_directories: include_directories('.'), - dependencies: [dep_qt5, dependency('openssl', required: true)]) -) - -# generate a test file that would be signed -unsignedfile_dat = custom_target('unsignedfile.dat', input: 'write-random.py', output: 'unsignedfile.dat', command: [ python3, '@INPUT@', '--output=@OUTPUT@' ]) - -signedfile_dat = custom_target('signedfile.dat', input: 'write-random.py', output: 'signedfile.dat', command: [ python3, '@INPUT@', '--output=@OUTPUT@' ]) - -badsignedfile_dat = custom_target('badsignedfile.dat', input: 'write-random.py', output: 'badsignedfile.dat', command: [ python3, '@INPUT@', '--output=@OUTPUT@' ]) -badsignedfile_sig = custom_target('badsignedfile.dat.sig', input: 'write-random.py', output: 'badsignedfile.dat.sig', command: [ python3, '@INPUT@', '--output=@OUTPUT@' ]) - -# sign test file -signedfile_sig = custom_target('signedfile.dat.sig', - input: signedfile_dat, - output: 'signedfile.dat.sig', - command: [ openssl, 'dgst', '-sha256', '-sign', private_pem, '-out', '@OUTPUT@', '@INPUT@' ] -) - -signedfile_idep = declare_dependency(sources: [ unsignedfile_dat, signedfile_dat, signedfile_sig, badsignedfile_dat, badsignedfile_sig ]) - -pluginloader_sigmatch = executable('pluginloader-sigmatch', - sources: [ 'test/pluginloader-sigmatch.cpp' ], - dependencies: [ dep_qt5, dep_catch, dep_pluginloader, signedfile_idep ] -) - -test('signature matching', pluginloader_sigmatch, suite: 'pluginloader', - env: { - 'SIGNEDFILE' : signedfile_dat.full_path(), - 'UNSIGNEDFILE': unsignedfile_dat.full_path(), - 'BADSIGNEDFILE': badsignedfile_dat.full_path() - }, -) - -poi_plugin_loader = executable('poi-plugin-load', dependencies: [ dep_qt5, dep_spdlog, dep_pluginloader ], sources: 'test/pluginloader-load.cpp') - -# make sure this fails when no plugin or an invalid file is passed -test('load', poi_plugin_loader, suite: 'pluginloader', should_fail: true) -test('load', poi_plugin_loader, suite: 'pluginloader', args: files('meson.build'), should_fail: true) - diff --git a/lib/pluginloader/pluginloader.cpp b/lib/pluginloader/pluginloader.cpp index ce84c7a..d4c3dff 100644 --- a/lib/pluginloader/pluginloader.cpp +++ b/lib/pluginloader/pluginloader.cpp @@ -17,8 +17,8 @@ bool PluginLoader::verify(const char *hashName) { const std::filesystem::path plugin_path(fileName().toStdString()); - if(!std::filesystem::is_regular_file(plugin_path)) { - m_sigError = tr("A plugin is required, but none was found."); + if(!std::filesystem::exists(plugin_path)) { + m_sigError = tr("Plugin doesn't exist."); return false; } diff --git a/lib/pluginloader/pluginloader.h b/lib/pluginloader/pluginloader.h index cc67901..bb5e1e0 100644 --- a/lib/pluginloader/pluginloader.h +++ b/lib/pluginloader/pluginloader.h @@ -16,13 +16,12 @@ public: SigChecked = (1 << 1), SigEnforced = (1 << 2), }; - typedef unsigned int signature_state_t; - static signature_state_t signature_state(bool ignore, bool check, bool enforce) + static constexpr signature_level signature_state(bool ignore, bool check, bool enforce) { - return (static_cast<unsigned int>(enforce) << 2) | (static_cast<unsigned int>(check) << 1) | static_cast<unsigned int>(ignore); + return enforce ? signature_level::SigEnforced : (check ? signature_level::SigChecked : signature_level::SigIgnored); } - PluginLoader(const QString &fileName, const signature_state_t state, QObject *parent = nullptr) + PluginLoader(const QString &fileName, const signature_level state, QObject *parent = nullptr) : QPluginLoader(fileName, parent) , m_state(state) { @@ -45,6 +44,6 @@ public: bool verify(const char *hashName = "SHA256"); private: - const signature_state_t m_state; + const signature_level m_state; QString m_sigError; }; diff --git a/lib/pluginloader/test/pluginloader-sigmatch.cpp b/lib/pluginloader/test/pluginloader-sigmatch.cpp index 0f4789a..fab8b5a 100644 --- a/lib/pluginloader/test/pluginloader-sigmatch.cpp +++ b/lib/pluginloader/test/pluginloader-sigmatch.cpp @@ -23,28 +23,40 @@ TEST_CASE("PluginLoader::signature_state") REQUIRE(PluginLoader::signature_state(true, true, true) >= PluginLoader::SigEnforced); } -TEST_CASE("files") +SCENARIO("PluginLoader") { - REQUIRE(qEnvironmentVariableIsSet("UNSIGNEDFILE")); - REQUIRE(qEnvironmentVariableIsSet("SIGNEDFILE")); - REQUIRE(qEnvironmentVariableIsSet("BADSIGNEDFILE")); -} - -TEST_CASE("PluginLoader::verify missing plugin") -{ - const auto state = PluginLoader::signature_state(false, false, false); - PluginLoader loader("", state); - - REQUIRE_FALSE(loader.verify()); - REQUIRE_FALSE(loader.errorString().isEmpty()); -} - -TEST_CASE("PluginLoader::verify signature ignored") -{ - const auto state = PluginLoader::signature_state(true, false, false); - PluginLoader loader(qgetenv("UNSIGNEDFILE"), state); - - REQUIRE(loader.verify()); + GIVEN("no plugin") { + const auto state = PluginLoader::signature_state(false, false, false); + PluginLoader loader("", state); + + CHECK_FALSE(loader.verify()); + CHECK_FALSE(loader.errorString().isEmpty()); + } + + GIVEN("A plugin with no signature") + { + const auto f = qgetenv("UNSIGNEDFILE"); + REQUIRE(!f.isEmpty()); + + WHEN("sig is ignored") { + const auto state = PluginLoader::signature_state(true, false, false); + PluginLoader loader(f, state); + + THEN("verify ok") { + REQUIRE(loader.verify()); + } + } + } + + GIVEN("A signed plugin") + { + REQUIRE(qEnvironmentVariableIsSet("SIGNEDFILE")); + } + + GIVEN("A badly signed plugin") + { + REQUIRE(qEnvironmentVariableIsSet("BADSIGNEDFILE")); + } } TEST_CASE("PluginLoader::verify signature checked [avialable]") @@ -96,4 +108,4 @@ TEST_CASE("PluginLoader::verify signature enforced [bad]") REQUIRE_FALSE(loader.verify()); REQUIRE_FALSE(loader.errorString().isEmpty()); -} +}
\ No newline at end of file diff --git a/lib/session_formats/CMakeLists.txt b/lib/session_formats/CMakeLists.txt new file mode 100644 index 0000000..75a472c --- /dev/null +++ b/lib/session_formats/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(session_formats STATIC session_json.hpp session_json.cpp) +target_link_libraries(session_formats PUBLIC Qt5::Core) +target_include_directories(session_formats INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC "${CMAKE_SOURCE_DIR}/include") + +add_executable(session_json test/json.cpp) +target_link_libraries(session_json PRIVATE session_formats Catch2::Catch2) +target_sanitize(session_json) +add_test(NAME session-json_format COMMAND session_json)
\ No newline at end of file diff --git a/lib/session_formats/meson.build b/lib/session_formats/meson.build deleted file mode 100644 index d5680cb..0000000 --- a/lib/session_formats/meson.build +++ /dev/null @@ -1,9 +0,0 @@ -lib_session_formats = declare_dependency( - include_directories: [ '.', plugininterfaces_include ], - link_with: static_library('sessionformats', [ 'session_json.cpp' ], include_directories: plugininterfaces_include, dependencies: dep_qt5) -) - -test('session-json format', executable('session_json', - sources: 'test/json.cpp', - dependencies: [ dep_qt5, dep_catch, lib_session_formats ] -)) diff --git a/lib/session_formats/session_json.hpp b/lib/session_formats/session_json.hpp index 142d9ef..2de6f5b 100644 --- a/lib/session_formats/session_json.hpp +++ b/lib/session_formats/session_json.hpp @@ -10,7 +10,7 @@ #define SESSION_JSON_HPP #include <QJsonObject> -#include "smolbote/session.hpp" +#include <smolbote/session.hpp> class JsonSession : public Session { diff --git a/lib/smolblok/CMakeLists.txt b/lib/smolblok/CMakeLists.txt new file mode 100644 index 0000000..80d419a --- /dev/null +++ b/lib/smolblok/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(smolblok STATIC smolblok.hpp smolblok.cpp) +target_link_libraries(smolblok PUBLIC Qt5::WebEngineWidgets) +target_include_directories(smolblok + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC "${CMAKE_SOURCE_DIR}/include") + +add_executable(smolblok-load test/loader.cpp) +target_link_libraries(smolblok-load PRIVATE smolblok fmt spdlog)
\ No newline at end of file diff --git a/lib/smolblok/meson.build b/lib/smolblok/meson.build deleted file mode 100644 index ea9e715..0000000 --- a/lib/smolblok/meson.build +++ /dev/null @@ -1,15 +0,0 @@ -dep_smolblok = declare_dependency( - include_directories: [ '.', smolbote_interfaces ], - link_with: library('smolblok', [ 'smolblok.cpp' ], include_directories: smolbote_interfaces, dependencies: dep_qt5) -) - -poi_sourceset.add(dep_smolblok) - -smolblok_load = executable('smolblok-load', - dependencies: [ dep_qt5, dep_spdlog, dep_smolblok ], - sources: [ 'test/loader.cpp' ] -) - -test('load', smolblok_load, suite: 'smolblok', should_fail: true) -test('load', smolblok_load, suite: 'smolblok', args: files('meson.build'), should_fail: true) - diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..f9937ff --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,8 @@ +find_program(XDG_VALIDATE desktop-file-validate) + +add_test(NAME verify_poi.desktop COMMAND ${XDG_VALIDATE} poi.desktop + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + +install(FILES firejail/poi.profile DESTINATION ${CMAKE_INSTALL_LIBDIR}/smolbote) +install(FILES ${CMAKE_SOURCE_DIR}/data/poi.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps) +install(FILES poi.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) diff --git a/linux/meson.build b/linux/meson.build deleted file mode 100644 index 87154f9..0000000 --- a/linux/meson.build +++ /dev/null @@ -1,18 +0,0 @@ -# application icon -install_data('../data/poi.svg', install_dir: get_option('datadir') / 'icons/hicolor/scalable/apps') - -# firejail profile -install_data('firejail/poi.profile', install_dir: get_option('libdir') / 'smolbote') - -# .desktop files -conf = configuration_data({ - 'exec_poi': get_option('prefix')/get_option('bindir')/get_option('poi'), - 'firejail': get_option('firejail'), - 'firejail_profile': get_option('prefix')/get_option('libdir')/'smolbote/poi.profile' -}) -desktop_files = ['poi.desktop', 'poi_firejail.desktop', 'poi_picksession.desktop'] -desktop_dir = get_option('datadir')/'applications' -foreach f : desktop_files - configure_file(input: f + '.in', output: f, configuration: conf, install_dir: desktop_dir) -endforeach - diff --git a/linux/poi.desktop.in b/linux/poi.desktop index a31a84c..56c3217 100644 --- a/linux/poi.desktop.in +++ b/linux/poi.desktop @@ -1,21 +1,21 @@ [Desktop Entry] +# (required) Application, Link or Directory +Type=Application +# The version of the desktop entry specification to which this file complies Version=1.0 + +# (required) Name=smolbote GenericName=Web Browser Comment=yet another no-frills browser -Exec=@exec_poi@ %u +Exec=poi %u Icon=poi Terminal=false -Type=Application MimeType=text/html;text/xml;application/xhtml+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https; Categories=Network;WebBrowser; Keywords=web;browser;internet; -Actions=pickSession;configure +Actions=pickSession [Desktop Action pickSession] Name=Pick Session -Exec=@exec_poi@ --pick-session - -[Desktop Action configure] -Name=Configure smolbote -Exec=@exec_poi@ configure +Exec=poi session --pick diff --git a/linux/poi.fish b/linux/poi.fish deleted file mode 100644 index d0b3e21..0000000 --- a/linux/poi.fish +++ /dev/null @@ -1,11 +0,0 @@ -# -c short option <short> -# -l long option <long> -# -a accepts option "option1 option2" - -complete -c poi -s h -l help --description 'Display command-line options list.' -complete -c poi -s v -l version --description 'Display version information.' -complete -c poi -l build --description 'Display build commit.' -complete -c poi -s c -l config -r --description 'Set configuration file.' -complete -c poi -l no-remote --description 'Do not accept or send remote commands.' -complete -c poi -s s -l session -r --description 'Open the selected session' -complete -c poi -l pick-session --description 'Show all available sessions and select which one to open.' diff --git a/linux/poi_firejail.desktop.in b/linux/poi_firejail.desktop.in deleted file mode 100644 index 31e5b64..0000000 --- a/linux/poi_firejail.desktop.in +++ /dev/null @@ -1,21 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=smolbote (in firejail) -GenericName=Web Browser -Comment=yet another no-frills browser -Exec=@firejail@ --profile=@firejail_profile@ @exec_poi@ --mainwindow.title="[[smolbote]]" %u -Icon=poi -Terminal=false -Type=Application -MimeType=text/html;text/xml;application/xhtml+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https; -Categories=Network;WebBrowser; -Keywords=web;browser;internet; -Actions=pickSession;configure - -[Desktop Action pickSession] -Name=Pick Session -Exec=@firejail@ --profile=@firejail_profile@ @exec_poi@ --pick-session - -[Desktop Action configure] -Name=Configure smolbote -Exec=@firejail@ --profile=@firejail_profile@ @exec_poi@ configure diff --git a/linux/poi_picksession.desktop.in b/linux/poi_picksession.desktop.in deleted file mode 100644 index 7cfb7a9..0000000 --- a/linux/poi_picksession.desktop.in +++ /dev/null @@ -1,13 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=smolbote (Pick Session) -GenericName=Web Browser -Comment=yet another no-frills browser -Exec=@exec_poi@ --pick-session -Icon=poi -Terminal=false -Type=Application -MimeType=text/html;text/xml;application/xhtml+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https; -Categories=Network;WebBrowser; -Keywords=web;browser;internet; - diff --git a/meson.build b/meson.build deleted file mode 100644 index e53a2e8..0000000 --- a/meson.build +++ /dev/null @@ -1,141 +0,0 @@ -project('smolbote', ['cpp'], - version: '0.1.0', - default_options: ['cpp_std=c++2a', 'warning_level=3'], - license: 'GPL3', - meson_version: '>=0.55.0' -) - -summary({ - 'prefix': get_option('prefix'), - 'bindir': get_option('bindir'), - 'libdir': get_option('libdir'), - 'datadir': get_option('datadir') -}, section: 'Install locations') - -kconfig = import('unstable-keyval') -cdata = configuration_data(kconfig.load(host_machine.system() + '/.config')) - -version_h = vcs_tag( - command: [find_program('git').full_path(), 'describe', '--long', '--abbrev=40'], - #fallback: defaults to meson.project_version(), - input: 'src/version.h.in', - output: 'version.h' -) - -# add -DQT_NO_DEBUG to non-debug builds -if not get_option('debug') - add_project_arguments('-DQT_NO_DEBUG', language: 'cpp') -endif - -sourceset = import('sourceset') - -cxx = meson.get_compiler('cpp') -summary({ - 'id': cxx.get_id(), - 'version': cxx.version(), - 'linker': cxx.get_linker_id(), -}, section: 'Compiler') - -# add some specific flags -add_project_arguments(cxx.get_supported_arguments([ - '-ffunction-sections', # Place each function into its own section, better ASLR but larger executables - '-fstack-protector-all', # Emit code to check for buffer overflows on all functions - '-fstack-clash-protection', # Emit code to check for stack clash attacks - - # gcc specific - '-fconcepts', # gcc9 c++20 compat - - # clang specific - '-mspeculative-load-hardening', # Spectre v1 mitigation - '-Xclang -plugin-arg-clazy -Xclang level0,level1', # clazy default warning level - - ## warnings - # variables - '-Wunused', # warn on anything being unused - '-Wshadow', # if variable declaration shadows one from a parent context - # functions - '-Wnon-virtual-dtor', # if class with virtual functions has non-virtual dtor - '-Wmissing-declarations', # missing function declarations in header files - '-Werror=redundant-decls', - '-Woverloaded-virtual', # warn if you overload (not override) a virtual function - '-Werror=return-type', - # style - '-Wformat=2', # security issues around printf - '-Wdate-time', # __TIME__ and __DATE__ macros - '-Werror=missing-field-initializers', - # objects - '-Wnull-dereference', - '-Wconsumed', # use-after-move warnings - '-Wlifetime', # object lifetime issues - # logic - '-Wlogical-op', # logical operations being used where bitwise were probably wanted - '-Wimplicit-fallthrough', - '-Wduplicated-cond', # if/else chain has duplicated conditions - '-Wduplicated-branches', # if/else branches have duplicated code - # casts - '-Wold-style-cast', - '-Wcast-align', # potential performance problem casts - '-Wuseless-cast', # cast to same type - '-Wconversion', # type conversions that may lose data - '-Wsign-conversion', # sign conversions - '-Wdouble-promotion', # float is promoted to double - # others - '-Werror=pedantic', # if non-standard c++ is used - #'-Weffc++', -]), language: 'cpp') - -# Dependencies -mod_qt5 = import('qt5') -dep_qt5 = dependency('qt5', - modules: [ 'Core', 'Network', 'Widgets', 'Svg', 'WebEngine', 'WebEngineWidgets', 'Concurrent' ], - include_type: 'system' -) - -dep_spdlog = dependency('spdlog', fallback: ['spdlog', 'spdlog_dep'], version: '>=1.3.1') -dep_catch = dependency('catch2', required: true, fallback: ['catch2', 'catch2_dep'] ) -dep_SingleApplication = dependency('singleapplication', fallback: [ 'singleapplication', 'SingleApplication_dep' ]) - -# Generate config header -poi_sourceset = sourceset.source_set() - -subdir('include') -smolbote_interfaces = include_directories('include') - -subdir('lib/bookmarks') -subdir('lib/configuration') -subdir('lib/downloads') -subdir('lib/pluginloader') -subdir('lib/session_formats') -subdir('lib/smolblok') - -subdir('src') -subdir('lang') -subdir('doc') - -subdir('plugins/ProfileEditor') -subdir('plugins/HostlistFilter') -subdir('plugins/AdblockFilter') - -subdir('test/firefox-bookmarks-json-parser') - -ssconfig = poi_sourceset.apply(cdata) - -poi_exe = executable(get_option('poi'), - cpp_args: ['-DQAPPLICATION_CLASS=QApplication'], - sources: [ssconfig.sources()], - include_directories: [ plugininterfaces_include, include_directories('src') ], - dependencies: [ dep_qt5, dep_spdlog, dep_SingleApplication, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, ssconfig.dependencies(), lib_session_formats ], - install: true, -) - -test('poi-bookmarks_xbel', poi_exe, args: [ 'bookmarks', '-x', files('test/bookmarks.xbel'), '--output=stdout' ]) - -subdir(host_machine.system()) - -# cppcheck target -cppcheck = find_program('cppcheck', required: false) -if cppcheck.found() -run_target('cppcheck', - command: [cppcheck, '--enable=all', '--project=' + meson.build_root() / 'compile_commands.json'] -) -endif diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index 32c25cb..0000000 --- a/meson_options.txt +++ /dev/null @@ -1,9 +0,0 @@ -option('poi', description: 'Executable name', type: 'string', value: 'poi') -option('firejail', description: 'firejail executable name', type: 'string', value: '/usr/bin/firejail') - -option('manpage', description: 'Generate and install manpage', type: 'boolean', value: 'true') -option('translations', description: 'Generate and install translations', type: 'feature', value: 'auto') -option('updater', description: 'Build updater component', type: 'feature', value: 'auto') - -# Build options -option('signPlugins', description: 'Generate OpenSSL signing key', type: 'feature', value: 'auto') diff --git a/plugins/HostlistFilter/CMakeLists.txt b/plugins/HostlistFilter/CMakeLists.txt new file mode 100644 index 0000000..b477967 --- /dev/null +++ b/plugins/HostlistFilter/CMakeLists.txt @@ -0,0 +1,33 @@ +# interface +add_library(hostlist INTERFACE) +target_sources(hostlist INTERFACE filterlist.h filterlist.cpp) +target_link_libraries(hostlist INTERFACE Qt5::WebEngine) +target_include_directories(hostlist INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include) + +# plugin +add_library(hostlistPlugin MODULE plugin/plugin.cpp) +target_link_libraries(hostlistPlugin PRIVATE hostlist) + +# tests + +add_executable(hostlistRule_test test/rule.cpp) +target_link_libraries(hostlistRule_test PRIVATE hostlist) +target_sanitize(hostlistRule_test) +add_test(NAME hostlist_rule COMMAND hostlistRule_test) + +add_executable(hostlistFilter_test test/filterlist.cpp) +target_link_libraries(hostlistFilter_test PRIVATE hostlist) +target_sanitize(hostlistFilter_test) +add_test(NAME hostlist_filter COMMAND hostlistFilter_test) +set_tests_properties(hostlist_filter PROPERTIES ENVIRONMENT "HOSTLIST_TXT=${CMAKE_CURRENT_SOURCE_DIR}/test/hostlist.txt") + +# plugin load test +add_test(NAME hostlist_load COMMAND pluginloader_load $<TARGET_FILE:hostlistPlugin>) + +# fuzzer +if(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + add_executable(hostlistFilter_fuzzer filterlist.cpp) + target_link_libraries(hostlistFilter_fuzzer PRIVATE hostlist) + target_compile_definitions(hostlistFilter_fuzzer PRIVATE FUZZER) + target_sanitize_fuzzer(hostlistFilter_fuzzer) +endif() diff --git a/plugins/HostlistFilter/meson.build b/plugins/HostlistFilter/meson.build deleted file mode 100644 index 1562524..0000000 --- a/plugins/HostlistFilter/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -dep_hostlistfilter = declare_dependency( - include_directories: [ '.', smolbote_interfaces ], - link_with: static_library('hostlistfilter', [ 'filterlist.cpp' ], include_directories: smolbote_interfaces, dependencies: [dep_qt5]) -) - -# plugin -plugin = shared_library('smolblokHostlistPlugin', - [ 'plugin/plugin.cpp', mod_qt5.preprocess(include_directories: smolbote_interfaces, moc_headers: 'plugin/plugin.h', dependencies: dep_qt5) ], - include_directories: smolbote_interfaces, - dependencies: [ dep_hostlistfilter, dep_qt5 ], - install: true, - install_dir: get_option('libdir')/'smolbote/plugins' -) - -# tests -test('rule', executable('rule', sources: 'test/rule.cpp', dependencies: [dep_qt5, dep_catch, dep_hostlistfilter]), suite: 'hostlist') - -test('filterlist', executable('filterlist', - sources: 'test/filterlist.cpp', - dependencies: [dep_qt5, dep_catch, dep_hostlistfilter]), - env: 'HOSTLIST_TXT='+meson.current_source_dir()/'test/hostlist.txt', - suite: 'hostlist' -) -test('plugin', executable('filterlist-plugin', - sources: [ 'test/plugin.cpp', 'plugin/plugin.cpp', - mod_qt5.preprocess(include_directories: smolbote_interfaces, moc_headers: 'plugin/plugin.h', dependencies: dep_qt5) ], - dependencies: [dep_qt5, dep_catch, dep_hostlistfilter]), - env: 'HOSTLIST_TXT='+meson.current_source_dir()/'test/hostlist.txt', - suite: 'hostlist' -) - -test('smolblok-load', smolblok_load, workdir: meson.build_root(), args: plugin.full_path(), suite: 'hostlist') - -# fuzzer -if meson.get_compiler('cpp').has_multi_arguments('-g', '-fsanitize=fuzzer') -executable('hostlist-fuzzer', - sources: 'filterlist.cpp', - include_directories: smolbote_interfaces, - dependencies: dep_qt5, - cpp_args: [ '-g', '-fsanitize=fuzzer', '-DFUZZER' ], - link_args: [ '-fsanitize=fuzzer' ] -) -endif diff --git a/plugins/HostlistFilter/plugin/smolblokHostlistPlugin.json b/plugins/HostlistFilter/smolblokHostlistPlugin.json index aa53cdd..aa53cdd 100644 --- a/plugins/HostlistFilter/plugin/smolblokHostlistPlugin.json +++ b/plugins/HostlistFilter/smolblokHostlistPlugin.json diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..8754e54 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,43 @@ +add_subdirectory(autogen) +add_subdirectory(about) +add_subdirectory(cmd) +add_subdirectory(webengine) + +add_executable(poi + bookmarks/builtin.cpp + bookmarks/bookmarkswidget.h bookmarks/bookmarkswidget.cpp bookmarks/bookmarksform.ui + bookmarks/bookmarkstoolbar.h bookmarks/bookmarkstoolbar.cpp + bookmarks/editbookmarkdialog.h bookmarks/editbookmarkdialog.cpp bookmarks/editbookmarkdialog.ui + + cmd/cmd.hpp + configuration/builtin.cpp + + mainwindow/widgets/completer.h mainwindow/widgets/completer.cpp + mainwindow/widgets/dockwidget.h mainwindow/widgets/dockwidget.cpp + mainwindow/widgets/menusearch.h mainwindow/widgets/menusearch.cpp + mainwindow/widgets/navigationbar.h mainwindow/widgets/navigationbar.cpp + mainwindow/widgets/searchform.h mainwindow/widgets/searchform.cpp mainwindow/widgets/searchform.ui + mainwindow/widgets/urllineedit.h mainwindow/widgets/urllineedit.cpp + mainwindow/addressbar.h mainwindow/addressbar.cpp mainwindow/addressbar.ui + mainwindow/mainwindow.h mainwindow/mainwindow.cpp + mainwindow/menubar.h mainwindow/menubar.cpp + + session/builtin.cpp + session/savesessiondialog.h session/savesessiondialog.cpp session/savesessiondialog.ui + session/sessiondialog.h session/sessiondialog.cpp session/sessiondialog.ui + + subwindow/subwindow.h subwindow/subwindow.cpp + subwindow/tabwidget.h subwindow/tabwidget.cpp + + main.cpp + applicationmenu.h applicationmenu.cpp + browser.h browser.cpp + util.h util.cpp) + +target_link_libraries(poi PRIVATE Qt5::Widgets Qt5::WebEngineWidgets Qt5::Svg + SingleApplication::SingleApplication fmt spdlog + about_dialog about_plugin webengine + bookmarks configuration downloads pluginloader session_formats smolblok) +target_include_directories(poi PRIVATE . + ${CMAKE_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/about/CMakeLists.txt b/src/about/CMakeLists.txt new file mode 100644 index 0000000..027d509 --- /dev/null +++ b/src/about/CMakeLists.txt @@ -0,0 +1,11 @@ +add_library(about_dialog INTERFACE) +target_sources(about_dialog INTERFACE aboutdialog.h aboutdialog.cpp aboutdialog.ui) +target_include_directories(about_dialog INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(about_dialog INTERFACE autogen Qt5::Widgets Qt5::Svg) + +add_library(about_plugin INTERFACE) +target_sources(about_plugin INTERFACE aboutplugin.h aboutplugin.cpp aboutplugin.ui) + +add_executable(test_about test/main.cpp) +target_link_libraries(test_about PRIVATE about_dialog Catch2::Catch2) +target_sanitize(test_about)
\ No newline at end of file diff --git a/src/about/aboutdialog.cpp b/src/about/aboutdialog.cpp index 6fa4127..643b87c 100644 --- a/src/about/aboutdialog.cpp +++ b/src/about/aboutdialog.cpp @@ -7,9 +7,9 @@ */ #include "aboutdialog.h" -#include "../poi_logos.h" +#include "poi_logos.h" #include "ui_aboutdialog.h" -#include <version.h> +#include "version.h" // compiler // clang also defines __GNUC__, so we need to check for clang first @@ -55,7 +55,7 @@ AboutDialog::AboutDialog(QWidget *parent) "<p>This program is distributed in the hope that it will be useful, but without any warranty.</p>" "<p>You can read the full terms of the license on <a href='https://www.gnu.org/licenses/gpl-3.0.en.html'>the GNU website</a>.</p>")); - ui->detailsLabel->setText(tr("<p>Version " poi_Version "</p>" + ui->detailsLabel->setText(tr("<p>Version " POI_VERSION "</p>" "<p>Compiled with " compiler "</p>" "<p>Libraries: <ul>" "<li><a href='https://www.qt.io/'>Qt5</a> " QT_VERSION_STR "</li>" diff --git a/src/about/meson.build b/src/about/meson.build deleted file mode 100644 index 49274a8..0000000 --- a/src/about/meson.build +++ /dev/null @@ -1,21 +0,0 @@ -about_moc = mod_qt5.preprocess( - moc_headers: ['aboutdialog.h', 'aboutplugin.h'], - ui_files: ['aboutdialog.ui', 'aboutplugin.ui'], - dependencies: dep_qt5 -) - -dep_about = declare_dependency( - include_directories: '.', - link_with: static_library('about', - [ 'aboutdialog.cpp', 'aboutplugin.cpp', about_moc, version_h], - dependencies: [dep_qt5]) -) - -poi_sourceset.add(dep_about) - -test('about dialog', executable('about', - sources: 'test/main.cpp', - dependencies: [ dep_qt5, dep_about, dep_catch ]), - args: [ '-platform', 'offscreen' ], - env: 'autoclose=1' -) diff --git a/src/about/test/main.cpp b/src/about/test/main.cpp index 18037e1..1b71c8e 100644 --- a/src/about/test/main.cpp +++ b/src/about/test/main.cpp @@ -1,12 +1,13 @@ #include <QApplication> #include <QTimer> #include "aboutdialog.h" +#include "version.h" int main(int argc, char **argv) { QApplication app(argc, argv); - app.setApplicationName("about"); - app.setApplicationVersion("1.2.3"); + app.setApplicationName(POI_NAME); + app.setApplicationVersion(POI_SHORT_VERSION); AboutDialog dlg; QObject::connect(&dlg, &AboutDialog::finished, &app, &QApplication::quit); @@ -17,5 +18,4 @@ int main(int argc, char **argv) } return app.exec(); -} - +}
\ No newline at end of file diff --git a/src/applicationmenu.cpp b/src/applicationmenu.cpp index 112e790..f69260d 100644 --- a/src/applicationmenu.cpp +++ b/src/applicationmenu.cpp @@ -7,7 +7,7 @@ */ #include "applicationmenu.h" -#include "aboutdialog.h" +#include "about/aboutdialog.h" #include "browser.h" #include "configuration.h" #include "session/savesessiondialog.h" diff --git a/src/autogen/CMakeLists.txt b/src/autogen/CMakeLists.txt new file mode 100644 index 0000000..66065ee --- /dev/null +++ b/src/autogen/CMakeLists.txt @@ -0,0 +1,31 @@ +find_program(PYTHON python3) + +# version.h +configure_file(version.h.in version.h @ONLY) + +# settings.h +add_custom_command(OUTPUT settings.h DEPENDS settings.h.in + COMMAND ${PYTHON} ${CMAKE_SOURCE_DIR}/scripts/gen-default-cfg.py + --kconfig=${CMAKE_SOURCE_DIR}/Kconfig --dotconfig=${CMAKE_SOURCE_DIR}/linux/.config + --input=${CMAKE_CURRENT_SOURCE_DIR}/settings.h.in --output=settings.h) + +# poi_logos.h +set(poi_logos ${CMAKE_SOURCE_DIR}/data/poi.svg ${CMAKE_SOURCE_DIR}/data/poi_window.svg) +add_custom_command(OUTPUT poi_logos.h DEPENDS ${poi_logos} + COMMAND ${PYTHON} ${RCC} -o=poi_logos.h dump -ns=logos ${poi_logos}) + +# poi_icons.h +set(poi_icons icons/arrow-left.svg icons/arrow-right.svg icons/circle-x.svg icons/refresh.svg icons/home.svg) +foreach(f ${poi_icons}) + list(REMOVE_ITEM poi_icons ${f}) + list(APPEND poi_icons ${ICONS_PATH}/${f}) +endforeach() +add_custom_command(OUTPUT poi_icons.h DEPENDS ${poi_icons} + COMMAND ${PYTHON} ${RCC} -o=poi_icons.h dump -ns=icons ${poi_icons}) + +# autogen target +add_custom_target(py_autogen DEPENDS settings.h poi_logos.h poi_icons.h) + +add_library(autogen INTERFACE) +target_include_directories(autogen INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) +add_dependencies(autogen py_autogen) diff --git a/src/settings.h.in b/src/autogen/settings.h.in index 51b2bd0..51b2bd0 100644 --- a/src/settings.h.in +++ b/src/autogen/settings.h.in diff --git a/src/version.h.in b/src/autogen/version.h.in index 231fb7c..4d50885 100644 --- a/src/version.h.in +++ b/src/autogen/version.h.in @@ -9,8 +9,13 @@ #ifndef SMOLBOTE_VERSION_H #define SMOLBOTE_VERSION_H -// output of 'git describe --long --abbrev=40': -// x.y.z-0-g0123456789012345678901234567890123456789 -#define poi_Version "@VCS_TAG@" +/* + * This is an automatically generated file, any changes to it may be overwritten. + * Edit src/version.h.in instead. + */ + +#define POI_NAME "@CMAKE_PROJECT_NAME@" +#define POI_VERSION "@CMAKE_PROJECT_VERSION@" +#define POI_SHORT_VERSION "@CMAKE_PROJECT_SHORT_VERSION@" #endif // SMOLBOTE_VERSION_H diff --git a/src/bookmarks/builtin.cpp b/src/bookmarks/builtin.cpp index 1ef516b..b8b925c 100644 --- a/src/bookmarks/builtin.cpp +++ b/src/bookmarks/builtin.cpp @@ -11,7 +11,6 @@ #include "configuration.h" #include <QBuffer> #include <QCommandLineParser> -#include <QCoreApplication> #include <QFile> #include <cstdlib> #include <iostream> diff --git a/src/bookmarks/meson.build b/src/bookmarks/meson.build deleted file mode 100644 index 8fc93f0..0000000 --- a/src/bookmarks/meson.build +++ /dev/null @@ -1,8 +0,0 @@ -poi_sourceset.add(files('builtin.cpp', - 'bookmarkswidget.cpp', 'editbookmarkdialog.cpp', 'bookmarkstoolbar.cpp'), -mod_qt5.preprocess( - moc_headers: ['bookmarkswidget.h', 'editbookmarkdialog.h'], - ui_files: ['bookmarksform.ui', 'editbookmarkdialog.ui'], - dependencies: dep_qt5 -)) - diff --git a/src/browser.cpp b/src/browser.cpp index b05c620..c9ed395 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -7,7 +7,7 @@ */ #include "browser.h" -#include "aboutplugin.h" +#include "about/aboutplugin.h" #include "applicationmenu.h" #include "bookmarks/bookmarkswidget.h" #include "configuration.h" @@ -17,18 +17,14 @@ #include "mainwindow/menubar.h" #include "session_json.hpp" #include "settings.h" -#include "smolbote/plugininterface.hpp" -#include "subwindow/subwindow.h" #include "util.h" #include "webengine/webprofile.h" #include "webengine/webprofilemanager.h" -#include "webengine/webview.h" #include <QAction> #include <QLibraryInfo> #include <QPluginLoader> #include <QTimer> #include <QTranslator> -#include <QVersionNumber> #include <pluginloader.h> #include <spdlog/spdlog.h> #include <version.h> @@ -36,10 +32,9 @@ Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) { - //setApplicationName(conf.value<QString>("poi.name").value()); - setApplicationName("smolbote"); + setApplicationName(POI_NAME); setWindowIcon(Util::icon<Util::AppWindowIcon>()); - setApplicationVersion(QVersionNumber::fromString(QLatin1String(poi_Version)).toString()); + setApplicationVersion(POI_SHORT_VERSION); } Browser::~Browser() diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt new file mode 100644 index 0000000..31563c9 --- /dev/null +++ b/src/cmd/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(cmd_test test.cpp) +target_link_libraries(cmd_test PRIVATE autogen Qt5::Core) +target_sanitize(cmd_test) + +add_test(NAME cmd_parser COMMAND cmd_test)
\ No newline at end of file diff --git a/src/cmd/cmd.hpp b/src/cmd/cmd.hpp index 37bb3ce..1aad060 100644 --- a/src/cmd/cmd.hpp +++ b/src/cmd/cmd.hpp @@ -24,7 +24,7 @@ using map = std::unordered_map<std::string, subcommand_fn<T>>; // a helper function to join the keys of a command_map into a string template <typename T> -[[nodiscard]] inline QString join_keys(const map<T> &map, const QString sep = ", ") +[[nodiscard]] inline QString join_keys(const map<T> &map, const QString &sep = ", ") { QString k; for(auto it = map.cbegin(); it != map.cend(); ++it) { @@ -59,7 +59,7 @@ template <typename T> parser.process(app); if(parser.isSet(build)) { - std::cout << app.applicationName().toStdString() << " " << poi_Version << std::endl; + std::cout << app.applicationName().toStdString() << " " << POI_VERSION << std::endl; exit(0); } diff --git a/src/cmd/meson.build b/src/cmd/meson.build deleted file mode 100644 index 466647f..0000000 --- a/src/cmd/meson.build +++ /dev/null @@ -1,2 +0,0 @@ -test('command line parser', executable('cmd_test', ['test.cpp', version_h], dependencies: [ dep_qt5 ])) - diff --git a/src/configuration/meson.build b/src/configuration/meson.build deleted file mode 100644 index 5ba8ffd..0000000 --- a/src/configuration/meson.build +++ /dev/null @@ -1 +0,0 @@ -poi_sourceset.add(files('builtin.cpp')) diff --git a/src/main.cpp b/src/main.cpp index 135d0ee..65c8c26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,10 +10,7 @@ #include "cmd/cmd.hpp" #include "configuration.h" #include "util.h" -#include <QFile> -#include <QPluginLoader> #include <QStandardPaths> -#include <pluginloader.h> #include <spdlog/spdlog.h> namespace builtins @@ -26,10 +23,11 @@ int sub_session(const QStringList &l, Browser &); int main(int argc, char **argv) { // spdlog pattern - if(const char *env_spdlog = std::getenv("POI_LOG_PATTERN")) + if(const char *env_spdlog = std::getenv("POI_LOG_PATTERN")) { spdlog::set_pattern(env_spdlog); - else + } else { spdlog::set_pattern("[%^%l%$] [%P:%t] %v"); + } #ifdef QT_DEBUG spdlog::set_level(spdlog::level::debug); // Set global log level to debug diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 1529a95..0000000 --- a/src/meson.build +++ /dev/null @@ -1,61 +0,0 @@ -python = import('python') -python3 = python.find_installation('python3') - -rcc_exe = subproject('rcc').get_variable('rcc_exe') -icons = subproject('tabler-icons').get_variable('smolbote_icons') - -poi_settings_h = custom_target('default_config_value', - input: files('../scripts/gen-default-cfg.py', '../Kconfig', '..'/host_machine.system()/'.config', 'settings.h.in'), - output: 'settings.h', - command: [ python3, '@INPUT0@', '--kconfig=@INPUT1@', '--dotconfig=@INPUT2@', '--input=@INPUT3@', '--output=@OUTPUT@' ] -) - -poi_logos_h = custom_target('poi_logos_h', - input: files('../data/poi.svg', '../data/poi_window.svg'), - output: 'poi_logos.h', - command: [ python3, rcc_exe, '-o=@OUTPUT@', 'dump', '-ns=logos', '@INPUT@' ]) -poi_icons_h = custom_target('poi_icons_h', - input: icons, - output: 'poi_icons.h', - command: [ python3, rcc_exe, '-o=@OUTPUT@', 'dump', '-ns=icons', '@INPUT@' ]) - -subdir('about') -subdir('bookmarks') -subdir('configuration') -subdir('cmd') -subdir('session') -subdir('webengine') - -poi_sourceset.add(mod_qt5.preprocess( - moc_headers: ['browser.h', 'applicationmenu.h', - 'mainwindow/mainwindow.h', 'mainwindow/addressbar.h', 'mainwindow/menubar.h', 'mainwindow/widgets/completer.h', 'mainwindow/widgets/urllineedit.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', - 'session/savesessiondialog.h', 'session/sessiondialog.h', - 'subwindow/subwindow.h', 'subwindow/tabwidget.h' ], - ui_files: [ - 'mainwindow/addressbar.ui', 'mainwindow/widgets/searchform.ui', - 'session/savesessiondialog.ui', 'session/sessiondialog.ui' ], - dependencies: dep_qt5 -)) - -poi_sourceset.add(files( - 'main.cpp', 'browser.cpp', 'applicationmenu.cpp', 'util.cpp', - - 'mainwindow/mainwindow.cpp', - 'mainwindow/addressbar.cpp', - 'mainwindow/menubar.cpp', - 'mainwindow/widgets/completer.cpp', - 'mainwindow/widgets/urllineedit.cpp', - 'mainwindow/widgets/dockwidget.cpp', - 'mainwindow/widgets/menusearch.cpp', - 'mainwindow/widgets/navigationbar.cpp', - 'mainwindow/widgets/searchform.cpp', - - 'session/savesessiondialog.cpp', - 'session/sessiondialog.cpp', - - 'subwindow/subwindow.cpp', - 'subwindow/tabwidget.cpp', -), - version_h, poi_settings_h, poi_icons_h, poi_logos_h -) - diff --git a/src/session/meson.build b/src/session/meson.build deleted file mode 100644 index 5ba8ffd..0000000 --- a/src/session/meson.build +++ /dev/null @@ -1 +0,0 @@ -poi_sourceset.add(files('builtin.cpp')) diff --git a/src/util.cpp b/src/util.cpp index 3dc5f8d..f18b682 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -16,8 +16,7 @@ const QStringList Util::files(const QString &location, const QStringList &nameFilters) { - if(location.isEmpty()) - return QStringList(); + if(location.isEmpty()) return QStringList(); QStringList filelist; diff --git a/src/webengine/CMakeLists.txt b/src/webengine/CMakeLists.txt new file mode 100644 index 0000000..5d2769d --- /dev/null +++ b/src/webengine/CMakeLists.txt @@ -0,0 +1,22 @@ +add_library(webengine INTERFACE) +target_sources(webengine INTERFACE + webprofile.h webprofile.cpp webprofilemanager.h webprofilemanager.cpp + webpage.h webpage.cpp + webview.h webview.cpp webviewcontextmenu.h webviewcontextmenu.cpp + urlinterceptor.h urlinterceptor.cpp) +target_include_directories(webengine INTERFACE ${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(webengine INTERFACE Qt5::WebEngineWidgets fmt) + +# tests +add_executable(profile_test test/profile.cpp) +target_link_libraries(profile_test PRIVATE webengine Catch2::Catch2) +#target_sanitize(profile_test) + +add_executable(profilemanager_test test/profilemanager.cpp) +target_link_libraries(profilemanager_test PRIVATE webengine Catch2::Catch2) +#target_sanitize(profilemanager_test) + +add_test(NAME webengine_profile COMMAND profile_test) +add_test(NAME webengine_profilemanager COMMAND profilemanager_test) +set_tests_properties(webengine_profile webengine_profilemanager PROPERTIES + ENVIRONMENT "PROFILE=${CMAKE_CURRENT_SOURCE_DIR}/test/testing.profile")
\ No newline at end of file diff --git a/src/webengine/meson.build b/src/webengine/meson.build deleted file mode 100644 index da59006..0000000 --- a/src/webengine/meson.build +++ /dev/null @@ -1,27 +0,0 @@ -webengine_moc = mod_qt5.preprocess( - moc_headers: [ 'webprofile.h', 'webpage.h', 'webview.h' ], - dependencies: dep_qt5 -) - -dep_webengine = declare_dependency( - include_directories: [ '.', smolbote_include ], - link_with: static_library('webengine', dependencies: [ dep_qt5, dep_spdlog ], - include_directories: smolbote_include, - sources: [ 'webprofile.cpp', 'urlinterceptor.cpp', 'webprofilemanager.cpp', 'webpage.cpp', 'webview.cpp', 'webviewcontextmenu.cpp', webengine_moc ]) -) - -poi_sourceset.add(dep_webengine) - -test('profile', executable('profile', 'test/profile.cpp', dependencies: [ dep_qt5, dep_webengine, dep_catch ]), - env: { 'PROFILE' : meson.current_source_dir()/'test/testing.profile' }, - suite: 'webengine') - -test('profilemanager', executable('profilemanager', 'test/profilemanager.cpp', dependencies: [ dep_qt5, dep_webengine, dep_catch ]), - env: { 'PROFILES' : meson.current_source_dir()/'test/testing.profile' }, - suite: 'webengine') - -test('view', executable('view', 'test/view.cpp', dependencies: [ dep_qt5, dep_webengine, dep_catch ]), - #args: [ '-platform', 'offscreen' ], - env: { 'PROFILE' : meson.current_source_dir()/'test/testing.profile', - 'URL' : meson.current_source_dir()/'test/sample.html' }, - suite: 'webengine') diff --git a/src/webengine/test/profilemanager.cpp b/src/webengine/test/profilemanager.cpp index dc7c903..8f6a34f 100644 --- a/src/webengine/test/profilemanager.cpp +++ b/src/webengine/test/profilemanager.cpp @@ -60,9 +60,9 @@ SCENARIO("WebProfileManager") GIVEN("a number of profiles, default undefined") { - REQUIRE(qEnvironmentVariableIsSet("PROFILES")); + REQUIRE(qEnvironmentVariableIsSet("PROFILE")); - WebProfileManager<false> profiles(QString::fromLatin1(qgetenv("PROFILES")).split(';'), default_id, search, homepage, newtab); + WebProfileManager<false> profiles(QString::fromLatin1(qgetenv("PROFILE")).split(';'), default_id, search, homepage, newtab); REQUIRE(profiles.idList().count() == 2); REQUIRE(profiles.profile(default_id) == WebProfile::defaultProfile()); @@ -94,9 +94,9 @@ SCENARIO("WebProfileManager") GIVEN("a number of profiles, default defined") { - REQUIRE(qEnvironmentVariableIsSet("PROFILES")); + REQUIRE(qEnvironmentVariableIsSet("PROFILE")); - WebProfileManager<false> profiles(QString::fromLatin1(qgetenv("PROFILES")).split(';'), "testing", search, homepage, newtab); + WebProfileManager<false> profiles(QString::fromLatin1(qgetenv("PROFILE")).split(';'), "testing", search, homepage, newtab); REQUIRE(profiles.idList().count() == 1); REQUIRE(profiles.profile("testing") == WebProfile::defaultProfile()); diff --git a/subprojects/catch2.wrap b/subprojects/catch2.wrap deleted file mode 100644 index 2e20085..0000000 --- a/subprojects/catch2.wrap +++ /dev/null @@ -1,10 +0,0 @@ -[wrap-file] -directory = Catch2-2.11.3 - -source_url = https://github.com/catchorg/Catch2/archive/v2.11.3.zip -source_filename = Catch2-2.11.3.zip -source_hash = c5a0a7510379c6f37f70b329986a335a7b8489d67ac417ce8f4262d0cae4cc5d - -patch_url = https://wrapdb.mesonbuild.com/v1/projects/catch2/2.11.3/1/get_zip -patch_filename = catch2-2.11.3-1-wrap.zip -patch_hash = 63c09cb68280435040ad304b3dd87ecfe69dbc216608991d0a82569a63119e57 diff --git a/subprojects/packagefiles/tabler-icons-1.34.0_patch.tar.xz b/subprojects/packagefiles/tabler-icons-1.34.0_patch.tar.xz Binary files differdeleted file mode 100644 index 65933c3..0000000 --- a/subprojects/packagefiles/tabler-icons-1.34.0_patch.tar.xz +++ /dev/null diff --git a/subprojects/rcc.wrap b/subprojects/rcc.wrap deleted file mode 100644 index 28c6548..0000000 --- a/subprojects/rcc.wrap +++ /dev/null @@ -1,6 +0,0 @@ -[wrap-file] -directory = rcc-0.1.2 -source_url = https://neueland.iserlohn-fortress.net/cgit/rcc/snapshot/rcc-0.1.2.tar.xz -source_filename = rcc-0.1.2.tar.xz -source_hash = 5ee18b94401b720e6e65d8e0e38dd6ea23cab7ae4727742be313530969a69d50 - diff --git a/subprojects/singleapplication.wrap b/subprojects/singleapplication.wrap deleted file mode 100644 index ac817db..0000000 --- a/subprojects/singleapplication.wrap +++ /dev/null @@ -1,6 +0,0 @@ -[wrap-file] -directory = SingleApplication-3.1.1a - -source_url = https://neueland.iserlohn-fortress.net/releases/SingleApplication-3.1.1a.tar.xz -source_filename = SingleApplication-3.1.1a.tar.xz -source_hash = df21800c9f3b254048ed34f6cfe96e5a540dc8ab4533b327a6982a6030f77080 diff --git a/subprojects/spdlog.wrap b/subprojects/spdlog.wrap deleted file mode 100644 index 51e0ddb..0000000 --- a/subprojects/spdlog.wrap +++ /dev/null @@ -1,9 +0,0 @@ -[wrap-file] -directory = spdlog-1.8.0 -source_url = https://github.com/gabime/spdlog/archive/v1.8.0.tar.gz -source_filename = v1.8.0.tar.gz -source_hash = 1e68e9b40cf63bb022a4b18cdc1c9d88eb5d97e4fd64fa981950a9cacf57a4bf -patch_url = https://wrapdb.mesonbuild.com/v1/projects/spdlog/1.8.0/1/get_zip -patch_filename = spdlog-1.8.0-1-wrap.zip -patch_hash = f783da51f6bebc99624504ca16fc1265b92add514956db9aa669a287d85b5049 - diff --git a/subprojects/tabler-icons.wrap b/subprojects/tabler-icons.wrap deleted file mode 100644 index 5df4f83..0000000 --- a/subprojects/tabler-icons.wrap +++ /dev/null @@ -1,7 +0,0 @@ -[wrap-file] -directory = tabler-icons-1.34.0 -source_url = https://github.com/tabler/tabler-icons/archive/v1.34.0.tar.gz -source_filename = v1.34.0.tar.gz -source_hash = bc74e5bd28531445f2e50df44f3688b1116397a25a0086e6944ab52260b70ffd -patch_filename = tabler-icons-1.34.0_patch.tar.xz -patch_hash = 5844ca9c3b69507abb50b50bebf23828fd60313a2c8c514d595e274a89a05456 diff --git a/windows/.config b/windows/.config deleted file mode 100644 index 235612f..0000000 --- a/windows/.config +++ /dev/null @@ -1,78 +0,0 @@ -# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) - -# -# Application -# -CONFIG_POI_NAME="smolbote" -CONFIG_POI_ICON=":/icons/poi.svg" - -# -# Configuration defaults -# -CONFIG_PATH_CONFIG="smolbote.cfg" -CONFIG_PATH_FILTER="hosts" -CONFIG_PATH_PLUGINS="plugins" -CONFIG_PATH_PROFILES="profiles" -CONFIG_PATH_BOOKMARKS="bookmarks.xbel" -CONFIG_PATH_DOWNLOADS="~/Downloads" - -# -# Keyboard shortcuts -# - -# -# Main Window shortcuts -# -CONFIG_SHORTCUT_WINDOW_NEWGROUP="Ctrl+G" -CONFIG_SHORTCUT_WINDOW_NEWWINDOW="Ctrl+N" -CONFIG_SHORTCUT_WINDOW_ABOUT="Ctrl+H" -CONFIG_SHORTCUT_WINDOW_QUIT="Ctrl+Q" -CONFIG_SHORTCUT_WINDOW_SEARCH="F3" -CONFIG_SHORTCUT_WINDOW_BOOKMARKS="Ctrl+B" -CONFIG_SHORTCUT_WINDOW_DOWNLOADS="Ctrl+D" - -# -# Navigation Bar shortcuts -# -CONFIG_SHORTCUT_NAVIGATION_BACK="Ctrl+Left" -CONFIG_SHORTCUT_NAVIGATION_BACKMENU="Ctrl+Down" -CONFIG_SHORTCUT_NAVIGATION_FORWARD="Ctrl+Right" -CONFIG_SHORTCUT_NAVIGATION_FORWARDMENU="Ctrl+Up" -CONFIG_SHORTCUT_NAVIGATION_REFRESH="F5" -CONFIG_SHORTCUT_NAVIGATION_RELOAD="Ctrl+F5" -CONFIG_SHORTCUT_NAVIGATION_HOME="Ctrl+Home" - -# -# Address Bar shortcuts -# -CONFIG_SHORTCUT_ADDRESS_FOCUS="F4" -CONFIG_SHORTCUT_ADDRESS_MENU="F2" - -# -# Subwindow shortcuts -# -CONFIG_SHORTCUT_SUBWINDOW_MENU="F1" -CONFIG_SHORTCUT_SUBWINDOW_TILE="F9" -CONFIG_SHORTCUT_SUBWINDOW_CASCADE="F10" -CONFIG_SHORTCUT_SUBWINDOW_FULLSCREEN="F11" -CONFIG_SHORTCUT_SUBWINDOW_NEWTAB="Ctrl+T" -CONFIG_SHORTCUT_SUBWINDOW_CLOSETAB="Ctrl+X" -CONFIG_SHORTCUT_SUBWINDOW_TABLEFT="Ctrl+O" -CONFIG_SHORTCUT_SUBWINDOW_MOVETABLEFT="Ctrl+Shift+O" -CONFIG_SHORTCUT_SUBWINDOW_TABRIGHT="Ctrl+P" -CONFIG_SHORTCUT_SUBWINDOW_MOVETABRIGHT="Ctrl+Shift+P" - -# -# Profile defaults -# -CONFIG_PROFILE_DEFAULT="" -CONFIG_PROFILE_DEFAULT_SEARCH="https://duckduckgo.com/?q=%1&ia=web" -CONFIG_PROFILE_DEFAULT_HOMEPAGE="about:blank" -CONFIG_PROFILE_DEFAULT_NEWTAB="about:blank" -# CONFIG_USEPLASMA is not set -# CONFIG_USEBREAKPAD is not set - -# -# Workarounds -# -CONFIG_QTBUG_65223=y |