#include "pch.h" #include "settings_objects.h" #include "settings_helpers.h" namespace PowerToysSettings { Settings::Settings(const HINSTANCE hinstance, std::wstring_view powertoy_name) { m_instance = hinstance; m_json.SetNamedValue(L"version", json::value(L"1.0")); m_json.SetNamedValue(L"name", json::value(powertoy_name)); m_json.SetNamedValue(L"properties", json::JsonObject{}); } void Settings::set_description(UINT resource_id) { m_json.SetNamedValue(L"description", json::value(get_resource(resource_id))); } void Settings::set_description(std::wstring_view description) { m_json.SetNamedValue(L"description", json::value(description)); } void Settings::set_icon_key(std::wstring_view icon_key) { m_json.SetNamedValue(L"icon_key", json::value(icon_key)); } void Settings::set_overview_link(std::wstring_view overview_link) { m_json.SetNamedValue(L"overview_link", json::value(overview_link)); } void Settings::set_video_link(std::wstring_view video_link) { m_json.SetNamedValue(L"video_link", json::value(video_link)); } // add_bool_toogle overloads. void Settings::add_bool_toogle(std::wstring_view name, UINT description_resource_id, bool value) { add_bool_toogle(name, get_resource(description_resource_id), value); } void Settings::add_bool_toogle(std::wstring_view name, std::wstring_view description, bool value) { json::JsonObject toggle; toggle.SetNamedValue(L"display_name", json::value(description)); toggle.SetNamedValue(L"editor_type", json::value(L"bool_toggle")); toggle.SetNamedValue(L"value", json::value(value)); toggle.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, toggle); } // add_int_spinner overloads. void Settings::add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step) { add_int_spinner(name, get_resource(description_resource_id), value, min, max, step); } void Settings::add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step) { json::JsonObject spinner; spinner.SetNamedValue(L"display_name", json::value(description)); spinner.SetNamedValue(L"editor_type", json::value(L"int_spinner")); spinner.SetNamedValue(L"value", json::value(value)); spinner.SetNamedValue(L"min", json::value(min)); spinner.SetNamedValue(L"max", json::value(max)); spinner.SetNamedValue(L"step", json::value(step)); spinner.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, spinner); } // add_string overloads. void Settings::add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { add_string(name, get_resource(description_resource_id), value); } void Settings::add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { json::JsonObject string; string.SetNamedValue(L"display_name", json::value(description)); string.SetNamedValue(L"editor_type", json::value(L"string_text")); string.SetNamedValue(L"value", json::value(value)); string.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, string); } // add_multiline_string overloads. void Settings::add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { add_multiline_string(name, get_resource(description_resource_id), value); } void Settings::add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value) { json::JsonObject ml_string; ml_string.SetNamedValue(L"display_name", json::value(description)); ml_string.SetNamedValue(L"editor_type", json::value(L"string_text")); ml_string.SetNamedValue(L"value", json::value(value)); ml_string.SetNamedValue(L"order", json::value(++m_curr_priority)); ml_string.SetNamedValue(L"multiline", json::value(true)); m_json.GetNamedObject(L"properties").SetNamedValue(name, ml_string); } // add_color_picker overloads. void Settings::add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value) { add_color_picker(name, get_resource(description_resource_id), value); } void Settings::add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value) { json::JsonObject picker; picker.SetNamedValue(L"display_name", json::value(description)); picker.SetNamedValue(L"editor_type", json::value(L"color_picker")); picker.SetNamedValue(L"value", json::value(value)); picker.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, picker); } void Settings::add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey) { add_hotkey(name, get_resource(description_resource_id), hotkey); } void Settings::add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey_obj) { json::JsonObject hotkey; hotkey.SetNamedValue(L"display_name", json::value(description)); hotkey.SetNamedValue(L"editor_type", json::value(L"hotkey")); hotkey.SetNamedValue(L"value", hotkey_obj.get_json()); hotkey.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, hotkey); } void Settings::add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids) { std::vector> keys_and_texts; keys_and_texts.reserve(keys_and_text_ids.size()); for (const auto& kv : keys_and_text_ids) { keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); } add_choice_group(name, get_resource(description_resource_id), value, keys_and_texts); } void Settings::add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts) { json::JsonObject choice_group; choice_group.SetNamedValue(L"display_name", json::value(description)); choice_group.SetNamedValue(L"editor_type", json::value(L"choice_group")); json::JsonArray options; for (const auto& [key, text] : keys_and_texts) { json::JsonObject entry; entry.SetNamedValue(L"key", json::value(key)); entry.SetNamedValue(L"text", json::value(text)); options.Append(std::move(entry)); } choice_group.SetNamedValue(L"options", std::move(options)); choice_group.SetNamedValue(L"value", json::value(value)); choice_group.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, choice_group); } void Settings::add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector>& keys_and_text_ids) { std::vector> keys_and_texts; keys_and_texts.reserve(keys_and_text_ids.size()); for (const auto& kv : keys_and_text_ids) { keys_and_texts.emplace_back(kv.first, get_resource(kv.second)); } add_dropdown(name, get_resource(description_resource_id), value, keys_and_texts); } void Settings::add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector>& keys_and_texts) { json::JsonObject dropdown; dropdown.SetNamedValue(L"display_name", json::value(description)); dropdown.SetNamedValue(L"editor_type", json::value(L"dropdown")); json::JsonArray options; for (const auto& [key, text] : keys_and_texts) { json::JsonObject entry; entry.SetNamedValue(L"key", json::value(key)); entry.SetNamedValue(L"text", json::value(text)); options.Append(std::move(entry)); } dropdown.SetNamedValue(L"options", std::move(options)); dropdown.SetNamedValue(L"value", json::value(value)); dropdown.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, dropdown); } // add_custom_action overloads. void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id) { add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), get_resource(ext_description_resource_id)); } void Settings::add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value) { add_custom_action(name, get_resource(description_resource_id), get_resource(button_text_resource_id), value); } void Settings::add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value) { json::JsonObject custom_action; custom_action.SetNamedValue(L"display_name", json::value(description)); custom_action.SetNamedValue(L"button_text", json::value(button_text)); custom_action.SetNamedValue(L"editor_type", json::value(L"custom_action")); custom_action.SetNamedValue(L"value", json::value(value)); custom_action.SetNamedValue(L"order", json::value(++m_curr_priority)); m_json.GetNamedObject(L"properties").SetNamedValue(name, custom_action); } // Serialization methods. std::wstring Settings::serialize() { return m_json.Stringify().c_str(); } bool Settings::serialize_to_buffer(wchar_t* buffer, int* buffer_size) { auto result = m_json.Stringify(); const int result_len = (int)result.size() + 1; if (buffer == nullptr || *buffer_size < result_len) { *buffer_size = result_len; return false; } else { wcscpy_s(buffer, *buffer_size, result.c_str()); return true; } } // Resource helper. std::wstring Settings::get_resource(UINT resource_id) { if (resource_id != 0) { wchar_t* res_ptr; const size_t resource_length = LoadStringW(m_instance, resource_id, reinterpret_cast(&res_ptr), 0); if (resource_length != 0) { return { *reinterpret_cast(&res_ptr), resource_length }; } } return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id); } PowerToyValues::PowerToyValues(std::wstring_view powertoy_name) { _name = powertoy_name; set_version(); m_json.SetNamedValue(L"name", json::value(powertoy_name)); m_json.SetNamedValue(L"properties", json::JsonObject{}); } PowerToyValues PowerToyValues::from_json_string(std::wstring_view json) { PowerToyValues result = PowerToyValues(); result.m_json = json::JsonValue::Parse(json).GetObjectW(); result._name = result.m_json.GetNamedString(L"name"); return result; } PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_name) { PowerToyValues result = PowerToyValues(); result.m_json = PTSettingsHelper::load_module_settings(powertoy_name); result._name = powertoy_name; return result; } inline bool has_property(const json::JsonObject& o, std::wstring_view name, const json::JsonValueType type) { const json::JsonObject props = o.GetNamedObject(L"properties", json::JsonObject{}); return json::has(props, name) && json::has(props.GetNamedObject(name), L"value", type); } std::optional PowerToyValues::get_bool_value(std::wstring_view property_name) { if (!has_property(m_json, property_name, json::JsonValueType::Boolean)) { return std::nullopt; } return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedBoolean(L"value"); } std::optional PowerToyValues::get_int_value(std::wstring_view property_name) { if (!has_property(m_json, property_name, json::JsonValueType::Number)) { return std::nullopt; } return static_cast(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value")); } std::optional PowerToyValues::get_string_value(std::wstring_view property_name) { if (!has_property(m_json, property_name, json::JsonValueType::String)) { return std::nullopt; } return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedString(L"value").c_str(); } std::optional PowerToyValues::get_json(std::wstring_view property_name) { if (!has_property(m_json, property_name, json::JsonValueType::Object)) { return std::nullopt; } return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value"); } std::wstring PowerToyValues::serialize() { set_version(); return m_json.Stringify().c_str(); } void PowerToyValues::save_to_settings_file() { set_version(); PTSettingsHelper::save_module_settings(_name, m_json); } void PowerToyValues::set_version() { m_json.SetNamedValue(L"version", json::value(m_version)); } }