mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 22:20:04 +00:00
Initial loading of JSON-based settings
This commit is contained in:
parent
28ea12cbfe
commit
1c0140fc98
8 changed files with 561 additions and 38 deletions
|
|
@ -48,9 +48,10 @@ find_package(Qt${QT_VERSION_MAJOR}
|
||||||
|
|
||||||
include(qt6-linguist.cmake)
|
include(qt6-linguist.cmake)
|
||||||
|
|
||||||
|
set(SRC_EXE_MAIN source/scwx/qt/main/main.cpp)
|
||||||
|
|
||||||
set(HDR_MAIN source/scwx/qt/main/main_window.hpp)
|
set(HDR_MAIN source/scwx/qt/main/main_window.hpp)
|
||||||
set(SRC_MAIN source/scwx/qt/main/main.cpp
|
set(SRC_MAIN source/scwx/qt/main/main_window.cpp)
|
||||||
source/scwx/qt/main/main_window.cpp)
|
|
||||||
set(UI_MAIN source/scwx/qt/main/main_window.ui)
|
set(UI_MAIN source/scwx/qt/main/main_window.ui)
|
||||||
set(HDR_GL source/scwx/qt/gl/gl.hpp
|
set(HDR_GL source/scwx/qt/gl/gl.hpp
|
||||||
source/scwx/qt/gl/shader_program.hpp
|
source/scwx/qt/gl/shader_program.hpp
|
||||||
|
|
@ -58,9 +59,11 @@ set(HDR_GL source/scwx/qt/gl/gl.hpp
|
||||||
set(SRC_GL source/scwx/qt/gl/shader_program.cpp
|
set(SRC_GL source/scwx/qt/gl/shader_program.cpp
|
||||||
source/scwx/qt/gl/text_shader.cpp)
|
source/scwx/qt/gl/text_shader.cpp)
|
||||||
set(HDR_MANAGER source/scwx/qt/manager/radar_manager.hpp
|
set(HDR_MANAGER source/scwx/qt/manager/radar_manager.hpp
|
||||||
source/scwx/qt/manager/resource_manager.hpp)
|
source/scwx/qt/manager/resource_manager.hpp
|
||||||
|
source/scwx/qt/manager/settings_manager.hpp)
|
||||||
set(SRC_MANAGER source/scwx/qt/manager/radar_manager.cpp
|
set(SRC_MANAGER source/scwx/qt/manager/radar_manager.cpp
|
||||||
source/scwx/qt/manager/resource_manager.cpp)
|
source/scwx/qt/manager/resource_manager.cpp
|
||||||
|
source/scwx/qt/manager/settings_manager.cpp)
|
||||||
set(HDR_MAP source/scwx/qt/map/map_widget.hpp
|
set(HDR_MAP source/scwx/qt/map/map_widget.hpp
|
||||||
source/scwx/qt/map/overlay_layer.hpp
|
source/scwx/qt/map/overlay_layer.hpp
|
||||||
source/scwx/qt/map/radar_layer.hpp
|
source/scwx/qt/map/radar_layer.hpp
|
||||||
|
|
@ -71,10 +74,14 @@ set(SRC_MAP source/scwx/qt/map/map_widget.cpp
|
||||||
source/scwx/qt/map/radar_layer.cpp
|
source/scwx/qt/map/radar_layer.cpp
|
||||||
source/scwx/qt/map/radar_range_layer.cpp
|
source/scwx/qt/map/radar_range_layer.cpp
|
||||||
source/scwx/qt/map/triangle_layer.cpp)
|
source/scwx/qt/map/triangle_layer.cpp)
|
||||||
|
set(HDR_SETTINGS source/scwx/qt/settings/general_settings.hpp)
|
||||||
|
set(SRC_SETTINGS source/scwx/qt/settings/general_settings.cpp)
|
||||||
set(HDR_UTIL source/scwx/qt/util/font.hpp
|
set(HDR_UTIL source/scwx/qt/util/font.hpp
|
||||||
source/scwx/qt/util/font_buffer.hpp)
|
source/scwx/qt/util/font_buffer.hpp
|
||||||
|
source/scwx/qt/util/json.hpp)
|
||||||
set(SRC_UTIL source/scwx/qt/util/font.cpp
|
set(SRC_UTIL source/scwx/qt/util/font.cpp
|
||||||
source/scwx/qt/util/font_buffer.cpp)
|
source/scwx/qt/util/font_buffer.cpp
|
||||||
|
source/scwx/qt/util/json.cpp)
|
||||||
set(HDR_VIEW source/scwx/qt/view/radar_view.hpp)
|
set(HDR_VIEW source/scwx/qt/view/radar_view.hpp)
|
||||||
set(SRC_VIEW source/scwx/qt/view/radar_view.cpp)
|
set(SRC_VIEW source/scwx/qt/view/radar_view.cpp)
|
||||||
|
|
||||||
|
|
@ -98,6 +105,8 @@ set(PROJECT_SOURCES ${HDR_MAIN}
|
||||||
${UI_MAIN}
|
${UI_MAIN}
|
||||||
${HDR_MAP}
|
${HDR_MAP}
|
||||||
${SRC_MAP}
|
${SRC_MAP}
|
||||||
|
${HDR_SETTINGS}
|
||||||
|
${SRC_SETTINGS}
|
||||||
${HDR_UTIL}
|
${HDR_UTIL}
|
||||||
${SRC_UTIL}
|
${SRC_UTIL}
|
||||||
${HDR_VIEW}
|
${HDR_VIEW}
|
||||||
|
|
@ -105,44 +114,55 @@ set(PROJECT_SOURCES ${HDR_MAIN}
|
||||||
${SHADER_FILES}
|
${SHADER_FILES}
|
||||||
${RESOURCE_FILES}
|
${RESOURCE_FILES}
|
||||||
${TS_FILES})
|
${TS_FILES})
|
||||||
|
set(EXECUTABLE_SOURCES ${SRC_EXE_MAIN})
|
||||||
|
|
||||||
source_group("Header Files\\main" FILES ${HDR_MAIN})
|
source_group("Header Files\\main" FILES ${HDR_MAIN})
|
||||||
source_group("Source Files\\main" FILES ${SRC_MAIN})
|
source_group("Source Files\\main" FILES ${SRC_MAIN})
|
||||||
source_group("Header Files\\gl" FILES ${HDR_GL})
|
source_group("Header Files\\gl" FILES ${HDR_GL})
|
||||||
source_group("Source Files\\gl" FILES ${SRC_GL})
|
source_group("Source Files\\gl" FILES ${SRC_GL})
|
||||||
source_group("Header Files\\manager" FILES ${HDR_MANAGER})
|
source_group("Header Files\\manager" FILES ${HDR_MANAGER})
|
||||||
source_group("Source Files\\manager" FILES ${SRC_MANAGER})
|
source_group("Source Files\\manager" FILES ${SRC_MANAGER})
|
||||||
source_group("UI Files\\main" FILES ${UI_MAIN})
|
source_group("UI Files\\main" FILES ${UI_MAIN})
|
||||||
source_group("Header Files\\map" FILES ${HDR_MAP})
|
source_group("Header Files\\map" FILES ${HDR_MAP})
|
||||||
source_group("Source Files\\map" FILES ${SRC_MAP})
|
source_group("Source Files\\map" FILES ${SRC_MAP})
|
||||||
source_group("Header Files\\util" FILES ${HDR_UTIL})
|
source_group("Header Files\\settings" FILES ${HDR_SETTINGS})
|
||||||
source_group("Source Files\\util" FILES ${SRC_UTIL})
|
source_group("Source Files\\settings" FILES ${SRC_SETTINGS})
|
||||||
source_group("Header Files\\view" FILES ${HDR_VIEW})
|
source_group("Header Files\\util" FILES ${HDR_UTIL})
|
||||||
source_group("Source Files\\view" FILES ${SRC_VIEW})
|
source_group("Source Files\\util" FILES ${SRC_UTIL})
|
||||||
source_group("OpenGL Shaders" FILES ${SHADER_FILES})
|
source_group("Header Files\\view" FILES ${HDR_VIEW})
|
||||||
source_group("Resources" FILES ${RESOURCE_FILES})
|
source_group("Source Files\\view" FILES ${SRC_VIEW})
|
||||||
source_group("I18N Files" FILES ${TS_FILES})
|
source_group("OpenGL Shaders" FILES ${SHADER_FILES})
|
||||||
|
source_group("Resources" FILES ${RESOURCE_FILES})
|
||||||
|
source_group("I18N Files" FILES ${TS_FILES})
|
||||||
|
|
||||||
qt_add_executable(scwx-qt
|
add_library(scwx-qt OBJECT ${PROJECT_SOURCES})
|
||||||
${PROJECT_SOURCES}
|
set_property(TARGET scwx-qt PROPERTY AUTOMOC ON)
|
||||||
)
|
|
||||||
|
qt_add_executable(supercell-wx ${EXECUTABLE_SOURCES})
|
||||||
|
|
||||||
qt6_create_translation_scwx(QM_FILES ${scwx-qt_SOURCE_DIR} ${TS_FILES})
|
qt6_create_translation_scwx(QM_FILES ${scwx-qt_SOURCE_DIR} ${TS_FILES})
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_compile_definitions(scwx-qt PRIVATE WIN32_LEAN_AND_MEAN)
|
target_compile_definitions(scwx-qt PUBLIC WIN32_LEAN_AND_MEAN)
|
||||||
|
target_compile_definitions(supercell-wx PUBLIC WIN32_LEAN_AND_MEAN)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(scwx-qt PRIVATE ${scwx-qt_SOURCE_DIR}/source
|
target_include_directories(scwx-qt PUBLIC ${scwx-qt_SOURCE_DIR}/source
|
||||||
${FTGL_INCLUDE_DIR}
|
${FTGL_INCLUDE_DIR}
|
||||||
${MBGL_INCLUDE_DIR})
|
${MBGL_INCLUDE_DIR})
|
||||||
|
|
||||||
target_link_libraries(scwx-qt PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
target_include_directories(supercell-wx PUBLIC ${scwx-qt_SOURCE_DIR}/source)
|
||||||
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
|
|
||||||
Boost::timer
|
target_link_libraries(scwx-qt PUBLIC Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
qmapboxgl
|
Qt${QT_VERSION_MAJOR}::OpenGLWidgets
|
||||||
opengl32
|
Boost::json
|
||||||
freetype-gl
|
Boost::timer
|
||||||
GeographicLib::GeographicLib
|
qmapboxgl
|
||||||
glm::glm
|
opengl32
|
||||||
wxdata)
|
freetype-gl
|
||||||
|
GeographicLib::GeographicLib
|
||||||
|
glm::glm
|
||||||
|
wxdata)
|
||||||
|
|
||||||
|
target_link_libraries(supercell-wx PRIVATE scwx-qt
|
||||||
|
wxdata)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include <scwx/qt/main/main_window.hpp>
|
#include <scwx/qt/main/main_window.hpp>
|
||||||
#include <scwx/qt/manager/resource_manager.hpp>
|
#include <scwx/qt/manager/resource_manager.hpp>
|
||||||
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
|
|
||||||
#include <boost/log/expressions.hpp>
|
#include <boost/log/expressions.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
@ -10,6 +11,9 @@ int main(int argc, char* argv[])
|
||||||
boost::log::core::get()->set_filter(boost::log::trivial::severity >=
|
boost::log::core::get()->set_filter(boost::log::trivial::severity >=
|
||||||
boost::log::trivial::debug);
|
boost::log::trivial::debug);
|
||||||
|
|
||||||
|
QCoreApplication::setApplicationName("Supercell Wx");
|
||||||
|
|
||||||
|
scwx::qt::manager::SettingsManager::Initialize();
|
||||||
scwx::qt::manager::ResourceManager::PreLoad();
|
scwx::qt::manager::ResourceManager::PreLoad();
|
||||||
|
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
|
|
||||||
116
scwx-qt/source/scwx/qt/manager/settings_manager.cpp
Normal file
116
scwx-qt/source/scwx/qt/manager/settings_manager.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
#include <scwx/qt/manager/settings_manager.hpp>
|
||||||
|
#include <scwx/qt/util/json.hpp>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace manager
|
||||||
|
{
|
||||||
|
namespace SettingsManager
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "[scwx::qt::manager::settings_manager] ";
|
||||||
|
|
||||||
|
static std::shared_ptr<settings::GeneralSettings> generalSettings_ = nullptr;
|
||||||
|
|
||||||
|
static boost::json::value ConvertSettingsToJson();
|
||||||
|
static void GenerateDefaultSettings();
|
||||||
|
static bool LoadSettings(const boost::json::object& settingsJson);
|
||||||
|
|
||||||
|
bool Initialize()
|
||||||
|
{
|
||||||
|
std::string appDataPath {
|
||||||
|
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
|
||||||
|
.toStdString()};
|
||||||
|
|
||||||
|
if (!std::filesystem::is_directory(appDataPath))
|
||||||
|
{
|
||||||
|
if (!std::filesystem::create_directories(appDataPath))
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< logPrefix_ << "Unable to create application data directory: \""
|
||||||
|
<< appDataPath << "\"";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string settingsPath {appDataPath + "/settings.json"};
|
||||||
|
|
||||||
|
ReadSettings(settingsPath);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadSettings(const std::string& settingsPath)
|
||||||
|
{
|
||||||
|
boost::json::value settingsJson = nullptr;
|
||||||
|
|
||||||
|
if (std::filesystem::exists(settingsPath))
|
||||||
|
{
|
||||||
|
settingsJson = util::json::ReadJsonFile(settingsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settingsJson == nullptr || !settingsJson.is_object())
|
||||||
|
{
|
||||||
|
GenerateDefaultSettings();
|
||||||
|
settingsJson = ConvertSettingsToJson();
|
||||||
|
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool jsonDirty = LoadSettings(settingsJson.as_object());
|
||||||
|
|
||||||
|
if (jsonDirty)
|
||||||
|
{
|
||||||
|
settingsJson = ConvertSettingsToJson();
|
||||||
|
util::json::WriteJsonFile(settingsPath, settingsJson);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<settings::GeneralSettings> general_settings()
|
||||||
|
{
|
||||||
|
return generalSettings_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boost::json::value ConvertSettingsToJson()
|
||||||
|
{
|
||||||
|
boost::json::object settingsJson;
|
||||||
|
|
||||||
|
settingsJson["general"] = generalSettings_->ToJson();
|
||||||
|
|
||||||
|
return settingsJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateDefaultSettings()
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << logPrefix_ << "Generating default settings";
|
||||||
|
|
||||||
|
generalSettings_ = settings::GeneralSettings::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool LoadSettings(const boost::json::object& settingsJson)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(info) << logPrefix_ << "Loading settings";
|
||||||
|
|
||||||
|
bool jsonDirty = false;
|
||||||
|
|
||||||
|
generalSettings_ = settings::GeneralSettings::Load(
|
||||||
|
settingsJson.if_contains("general"), jsonDirty);
|
||||||
|
|
||||||
|
return jsonDirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SettingsManager
|
||||||
|
} // namespace manager
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
22
scwx-qt/source/scwx/qt/manager/settings_manager.hpp
Normal file
22
scwx-qt/source/scwx/qt/manager/settings_manager.hpp
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace manager
|
||||||
|
{
|
||||||
|
namespace SettingsManager
|
||||||
|
{
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
void ReadSettings(const std::string& settingsPath);
|
||||||
|
|
||||||
|
std::shared_ptr<settings::GeneralSettings> general_settings();
|
||||||
|
|
||||||
|
} // namespace SettingsManager
|
||||||
|
} // namespace manager
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
98
scwx-qt/source/scwx/qt/settings/general_settings.cpp
Normal file
98
scwx-qt/source/scwx/qt/settings/general_settings.cpp
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include <scwx/qt/settings/general_settings.hpp>
|
||||||
|
#include <scwx/qt/util/json.hpp>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace settings
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "[scwx::qt::settings::general_settings] ";
|
||||||
|
|
||||||
|
static const std::string& DEFAULT_DEFAULT_RADAR_SITE = "KLSX";
|
||||||
|
|
||||||
|
class GeneralSettingsImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GeneralSettingsImpl() {}
|
||||||
|
|
||||||
|
~GeneralSettingsImpl() {}
|
||||||
|
|
||||||
|
void SetDefaults() { defaultRadarSite_ = DEFAULT_DEFAULT_RADAR_SITE; }
|
||||||
|
|
||||||
|
std::string defaultRadarSite_;
|
||||||
|
};
|
||||||
|
|
||||||
|
GeneralSettings::GeneralSettings() : p(std::make_unique<GeneralSettingsImpl>())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
GeneralSettings::~GeneralSettings() = default;
|
||||||
|
|
||||||
|
GeneralSettings::GeneralSettings(GeneralSettings&&) noexcept = default;
|
||||||
|
GeneralSettings&
|
||||||
|
GeneralSettings::operator=(GeneralSettings&&) noexcept = default;
|
||||||
|
|
||||||
|
const std::string& GeneralSettings::default_radar_site()
|
||||||
|
{
|
||||||
|
return p->defaultRadarSite_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::json::value GeneralSettings::ToJson()
|
||||||
|
{
|
||||||
|
boost::json::object json;
|
||||||
|
|
||||||
|
json["default_radar_site"] = p->defaultRadarSite_;
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<GeneralSettings> GeneralSettings::Create()
|
||||||
|
{
|
||||||
|
std::shared_ptr<GeneralSettings> generalSettings =
|
||||||
|
std::make_shared<GeneralSettings>();
|
||||||
|
|
||||||
|
generalSettings->p->SetDefaults();
|
||||||
|
|
||||||
|
return generalSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<GeneralSettings>
|
||||||
|
GeneralSettings::Load(const boost::json::value* json, bool& jsonDirty)
|
||||||
|
{
|
||||||
|
std::shared_ptr<GeneralSettings> generalSettings =
|
||||||
|
std::make_shared<GeneralSettings>();
|
||||||
|
|
||||||
|
if (json != nullptr && json->is_object())
|
||||||
|
{
|
||||||
|
jsonDirty |=
|
||||||
|
!util::json::FromJsonString(json->as_object(),
|
||||||
|
"default_radar_site",
|
||||||
|
generalSettings->p->defaultRadarSite_,
|
||||||
|
DEFAULT_DEFAULT_RADAR_SITE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (json == nullptr)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< logPrefix_ << "Key is not present, resetting to defaults";
|
||||||
|
}
|
||||||
|
else if (!json->is_object())
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< logPrefix_ << "Invalid json, resetting to defaults";
|
||||||
|
}
|
||||||
|
|
||||||
|
generalSettings->p->SetDefaults();
|
||||||
|
jsonDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return generalSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace settings
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
43
scwx-qt/source/scwx/qt/settings/general_settings.hpp
Normal file
43
scwx-qt/source/scwx/qt/settings/general_settings.hpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/json.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace settings
|
||||||
|
{
|
||||||
|
|
||||||
|
class GeneralSettingsImpl;
|
||||||
|
|
||||||
|
class GeneralSettings
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GeneralSettings();
|
||||||
|
~GeneralSettings();
|
||||||
|
|
||||||
|
GeneralSettings(const GeneralSettings&) = delete;
|
||||||
|
GeneralSettings& operator=(const GeneralSettings&) = delete;
|
||||||
|
|
||||||
|
GeneralSettings(GeneralSettings&&) noexcept;
|
||||||
|
GeneralSettings& operator=(GeneralSettings&&) noexcept;
|
||||||
|
|
||||||
|
const std::string& default_radar_site();
|
||||||
|
|
||||||
|
boost::json::value ToJson();
|
||||||
|
|
||||||
|
static std::shared_ptr<GeneralSettings> Create();
|
||||||
|
static std::shared_ptr<GeneralSettings> Load(const boost::json::value* json,
|
||||||
|
bool& jsonDirty);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<GeneralSettingsImpl> p;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace settings
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
193
scwx-qt/source/scwx/qt/util/json.cpp
Normal file
193
scwx-qt/source/scwx/qt/util/json.cpp
Normal file
|
|
@ -0,0 +1,193 @@
|
||||||
|
#include <scwx/qt/util/json.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
namespace json
|
||||||
|
{
|
||||||
|
|
||||||
|
static const std::string logPrefix_ = "[scwx::qt::util::json] ";
|
||||||
|
|
||||||
|
/* Adapted from:
|
||||||
|
* https://www.boost.org/doc/libs/1_77_0/libs/json/doc/html/json/examples.html#json.examples.pretty
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019, 2020 Vinnie Falco
|
||||||
|
* Copyright (c) 2020 Krystian Stasiowski
|
||||||
|
* Distributed under the Boost Software License, Version 1.0. (See
|
||||||
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
*/
|
||||||
|
static void PrettyPrintJson(std::ostream& os,
|
||||||
|
boost::json::value const& jv,
|
||||||
|
std::string* indent = nullptr);
|
||||||
|
|
||||||
|
bool FromJsonString(const boost::json::object& json,
|
||||||
|
const std::string& key,
|
||||||
|
std::string& value,
|
||||||
|
const std::string& defaultValue)
|
||||||
|
{
|
||||||
|
const boost::json::value* jv = json.if_contains(key);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (jv != nullptr)
|
||||||
|
{
|
||||||
|
if (jv->is_string())
|
||||||
|
{
|
||||||
|
value = boost::json::value_to<std::string>(*jv);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< logPrefix_ << key
|
||||||
|
<< " is not a string, setting to default: " << defaultValue;
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< logPrefix_ << key
|
||||||
|
<< " is not present, setting to default: " << defaultValue;
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::json::value ReadJsonFile(const std::string& path)
|
||||||
|
{
|
||||||
|
std::ifstream ifs {path};
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
boost::json::stream_parser p;
|
||||||
|
boost::json::error_code ec;
|
||||||
|
|
||||||
|
while (std::getline(ifs, line))
|
||||||
|
{
|
||||||
|
p.write(line, ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << ec.message();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p.finish(ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << logPrefix_ << ec.message();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteJsonFile(const std::string& path,
|
||||||
|
const boost::json::value& json,
|
||||||
|
bool prettyPrint)
|
||||||
|
{
|
||||||
|
std::ofstream ofs {path};
|
||||||
|
|
||||||
|
if (prettyPrint)
|
||||||
|
{
|
||||||
|
PrettyPrintJson(ofs, json);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ofs << json;
|
||||||
|
}
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrettyPrintJson(std::ostream& os,
|
||||||
|
boost::json::value const& jv,
|
||||||
|
std::string* indent)
|
||||||
|
{
|
||||||
|
std::string indent_;
|
||||||
|
if (!indent)
|
||||||
|
indent = &indent_;
|
||||||
|
switch (jv.kind())
|
||||||
|
{
|
||||||
|
case boost::json::kind::object:
|
||||||
|
{
|
||||||
|
os << "{\n";
|
||||||
|
indent->append(4, ' ');
|
||||||
|
auto const& obj = jv.get_object();
|
||||||
|
if (!obj.empty())
|
||||||
|
{
|
||||||
|
auto it = obj.begin();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
os << *indent << boost::json::serialize(it->key()) << " : ";
|
||||||
|
PrettyPrintJson(os, it->value(), indent);
|
||||||
|
if (++it == obj.end())
|
||||||
|
break;
|
||||||
|
os << ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
indent->resize(indent->size() - 4);
|
||||||
|
os << *indent << "}";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case boost::json::kind::array:
|
||||||
|
{
|
||||||
|
os << "[\n";
|
||||||
|
indent->append(4, ' ');
|
||||||
|
auto const& arr = jv.get_array();
|
||||||
|
if (!arr.empty())
|
||||||
|
{
|
||||||
|
auto it = arr.begin();
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
os << *indent;
|
||||||
|
PrettyPrintJson(os, *it, indent);
|
||||||
|
if (++it == arr.end())
|
||||||
|
break;
|
||||||
|
os << ",\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os << "\n";
|
||||||
|
indent->resize(indent->size() - 4);
|
||||||
|
os << *indent << "]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case boost::json::kind::string:
|
||||||
|
{
|
||||||
|
os << boost::json::serialize(jv.get_string());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case boost::json::kind::uint64: os << jv.get_uint64(); break;
|
||||||
|
|
||||||
|
case boost::json::kind::int64: os << jv.get_int64(); break;
|
||||||
|
|
||||||
|
case boost::json::kind::double_: os << jv.get_double(); break;
|
||||||
|
|
||||||
|
case boost::json::kind::bool_:
|
||||||
|
if (jv.get_bool())
|
||||||
|
os << "true";
|
||||||
|
else
|
||||||
|
os << "false";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case boost::json::kind::null: os << "null"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indent->empty())
|
||||||
|
os << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace json
|
||||||
|
} // namespace util
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
27
scwx-qt/source/scwx/qt/util/json.hpp
Normal file
27
scwx-qt/source/scwx/qt/util/json.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/json.hpp>
|
||||||
|
|
||||||
|
namespace scwx
|
||||||
|
{
|
||||||
|
namespace qt
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
namespace json
|
||||||
|
{
|
||||||
|
|
||||||
|
bool FromJsonString(const boost::json::object& json,
|
||||||
|
const std::string& key,
|
||||||
|
std::string& value,
|
||||||
|
const std::string& defaultValue);
|
||||||
|
|
||||||
|
boost::json::value ReadJsonFile(const std::string& path);
|
||||||
|
void WriteJsonFile(const std::string& path,
|
||||||
|
const boost::json::value& json,
|
||||||
|
bool prettyPrint = true);
|
||||||
|
|
||||||
|
} // namespace json
|
||||||
|
} // namespace util
|
||||||
|
} // namespace qt
|
||||||
|
} // namespace scwx
|
||||||
Loading…
Add table
Add a link
Reference in a new issue