diff --git a/CMakeLists.txt b/CMakeLists.txt index 4885f29..b97ad10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,12 @@ CPMAddPackage( GIT_TAG 10.0.0 EXCLUDE_FROM_ALL YES ) +CPMAddPackage( + NAME tomlplusplus + GITHUB_REPOSITORY marzer/tomlplusplus + GIT_TAG ad55bae8a11a6eee39e2292b01e95b529b105767 + EXCLUDE_FROM_ALL YES +) CPMAddPackage( NAME spdlog GITHUB_REPOSITORY gabime/spdlog @@ -99,6 +105,7 @@ add_executable(${PROJECT_NAME} src/cpu.cpp src/cpu.hpp src/pacmanconf_repo.cpp src/pacmanconf_repo.hpp src/initcpio.cpp src/initcpio.hpp + src/chwd_profiles.cpp src/chwd_profiles.hpp src/disk.cpp src/disk.hpp src/drivers.cpp src/drivers.hpp src/widgets.cpp src/widgets.hpp @@ -134,7 +141,7 @@ if(COS_INSTALLER_BUILD_TESTS) add_subdirectory(tests) endif() -target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component range-v3::range-v3 ctre::ctre) +target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component range-v3::range-v3 ctre::ctre tomlplusplus::tomlplusplus) if(NOT ENABLE_DEVENV) target_link_libraries(${PROJECT_NAME} PRIVATE cpr::cpr) endif() diff --git a/src/chwd_profiles.cpp b/src/chwd_profiles.cpp new file mode 100644 index 0000000..c94e1cc --- /dev/null +++ b/src/chwd_profiles.cpp @@ -0,0 +1,73 @@ +#include "chwd_profiles.hpp" +#include "utils.hpp" + +#include // for any_of, sort, for_each + +#include +#include + +#define TOML_EXCEPTIONS 0 // disable exceptions +#include + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuseless-cast" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +#include +#include +#include + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +namespace detail::chwd { + +auto get_all_profile_names(std::string_view profile_type) noexcept -> std::optional> { + const auto& file_path = fmt::format(FMT_COMPILE("/var/lib/chwd/db/pci/{}/profiles.toml"), profile_type); + toml::parse_result config = toml::parse_file(file_path); + /* clang-format off */ + if (config.failed()) { return {}; } + /* clang-format on */ + + std::vector profile_names{}; + for (auto&& [key, value] : config.table()) { + if (value.is_table()) { + for (auto&& [nested_key, nested_value] : *value.as_table()) { + /* clang-format off */ + if (!nested_value.is_table()) { continue; } + /* clang-format on */ + + const auto& nested_profile_name = fmt::format(FMT_COMPILE("{}.{}"), std::string_view{key}, std::string_view{nested_key}); + profile_names.push_back(nested_profile_name); + } + profile_names.push_back(std::string(key)); + } + } + + return profile_names; +} + +auto get_available_profile_names(std::string_view profile_type) noexcept -> std::optional> { + auto&& all_profile_names = get_all_profile_names(profile_type); + /* clang-format off */ + if (!all_profile_names.has_value()) { return {}; } + /* clang-format on */ + + const auto& available_profile_names = utils::make_multiline(utils::exec("chwd --list -d | grep Name | awk '{print $4}'")); + + std::vector filtered_profile_names{}; + const auto& functor = [available_profile_names](auto&& profile_name) { return ranges::any_of(available_profile_names, [profile_name](auto&& available_profile) { return available_profile == profile_name; }); }; + + ranges::for_each(all_profile_names.value() | ranges::views::filter(functor), [&](auto&& rng) { filtered_profile_names.push_back(std::forward(rng)); }); + return filtered_profile_names; +} + +} // namespace detail::chwd diff --git a/src/chwd_profiles.hpp b/src/chwd_profiles.hpp new file mode 100644 index 0000000..85900d0 --- /dev/null +++ b/src/chwd_profiles.hpp @@ -0,0 +1,16 @@ +#ifndef CHWD_PROFILES_HPP +#define CHWD_PROFILES_HPP + +#include // for optional +#include // for string +#include // for string_view +#include // for vector + +namespace detail::chwd { + +auto get_all_profile_names(std::string_view profile_type) noexcept -> std::optional>; +auto get_available_profile_names(std::string_view profile_type) noexcept -> std::optional>; + +} // namespace detail::chwd + +#endif // CHWD_PROFILES_HPP diff --git a/src/drivers.cpp b/src/drivers.cpp index e8335f1..d28479e 100644 --- a/src/drivers.cpp +++ b/src/drivers.cpp @@ -2,6 +2,7 @@ #include "config.hpp" #include "utils.hpp" #include "widgets.hpp" +#include "chwd_profiles.hpp" /* clang-format off */ #include // for ofstream @@ -54,8 +55,12 @@ static void setup_graphics_card() noexcept { /// TODO(vnepogodin): parse toml DBs { static constexpr auto UseSpaceBar = "\nUse [Spacebar] to de/select options listed.\n"; - const auto& cmd = utils::exec("mhwd -l | awk '/ video-/{print $1}' | awk '$0=$0' | sort | uniq"); - const auto& radiobox_list = utils::make_multiline(cmd); + const auto& profile_names = ::detail::chwd::get_available_profile_names("graphic_drivers"); + if (!profile_names.has_value()) { + spdlog::error("failed to get profile names"); + return; + } + const auto& radiobox_list = profile_names.value(); auto screen = ScreenInteractive::Fullscreen(); std::int32_t selected{};