mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
common: refactor common library pt2 (#8588)
- remove common lib - split settings, remove common-md - move ipc interop/kb_layout to interop - rename core -> settings, settings -> old_settings - os-detect header-only; interop -> PowerToysInterop - split notifications, move single-use headers where they're used - winstore lib - rename com utils - rename Updating and Telemetry projects - rename core -> settings-ui and remove examples folder - rename settings-ui folder + consisent common/version include
This commit is contained in:
54
src/common/SettingsAPI/SetttingsAPI.vcxproj
Normal file
54
src/common/SettingsAPI/SetttingsAPI.vcxproj
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{6955446D-23F7-4023-9BB3-8657F904AF99}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>SetttingsAPI</RootNamespace>
|
||||
<ProjectName>SetttingsAPI</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="settings_helpers.h" />
|
||||
<ClInclude Include="settings_objects.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="settings_helpers.cpp" />
|
||||
<ClCompile Include="settings_objects.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
1
src/common/SettingsAPI/pch.cpp
Normal file
1
src/common/SettingsAPI/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
11
src/common/SettingsAPI/pch.h
Normal file
11
src/common/SettingsAPI/pch.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <winrt/base.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <Windows.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
80
src/common/SettingsAPI/settings_helpers.cpp
Normal file
80
src/common/SettingsAPI/settings_helpers.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "pch.h"
|
||||
#include "settings_helpers.h"
|
||||
|
||||
namespace PTSettingsHelper
|
||||
{
|
||||
constexpr inline const wchar_t* settings_filename = L"\\settings.json";
|
||||
constexpr inline const wchar_t* log_settings_filename = L"log_settings.json";
|
||||
|
||||
std::wstring get_root_save_folder_location()
|
||||
{
|
||||
PWSTR local_app_path;
|
||||
winrt::check_hresult(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &local_app_path));
|
||||
std::wstring result{ local_app_path };
|
||||
CoTaskMemFree(local_app_path);
|
||||
|
||||
result += L"\\Microsoft\\PowerToys";
|
||||
std::filesystem::path save_path(result);
|
||||
if (!std::filesystem::exists(save_path))
|
||||
{
|
||||
std::filesystem::create_directories(save_path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring get_module_save_folder_location(std::wstring_view powertoy_key)
|
||||
{
|
||||
std::wstring result = get_root_save_folder_location();
|
||||
result += L"\\";
|
||||
result += powertoy_key;
|
||||
std::filesystem::path save_path(result);
|
||||
if (!std::filesystem::exists(save_path))
|
||||
{
|
||||
std::filesystem::create_directories(save_path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring get_module_save_file_location(std::wstring_view powertoy_key)
|
||||
{
|
||||
return get_module_save_folder_location(powertoy_key) + settings_filename;
|
||||
}
|
||||
|
||||
std::wstring get_powertoys_general_save_file_location()
|
||||
{
|
||||
return get_root_save_folder_location() + settings_filename;
|
||||
}
|
||||
|
||||
void save_module_settings(std::wstring_view powertoy_key, json::JsonObject& settings)
|
||||
{
|
||||
const std::wstring save_file_location = get_module_save_file_location(powertoy_key);
|
||||
json::to_file(save_file_location, settings);
|
||||
}
|
||||
|
||||
json::JsonObject load_module_settings(std::wstring_view powertoy_key)
|
||||
{
|
||||
const std::wstring save_file_location = get_module_save_file_location(powertoy_key);
|
||||
auto saved_settings = json::from_file(save_file_location);
|
||||
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};
|
||||
}
|
||||
|
||||
void save_general_settings(const json::JsonObject& settings)
|
||||
{
|
||||
const std::wstring save_file_location = get_powertoys_general_save_file_location();
|
||||
json::to_file(save_file_location, settings);
|
||||
}
|
||||
|
||||
json::JsonObject load_general_settings()
|
||||
{
|
||||
const std::wstring save_file_location = get_powertoys_general_save_file_location();
|
||||
auto saved_settings = json::from_file(save_file_location);
|
||||
return saved_settings.has_value() ? std::move(*saved_settings) : json::JsonObject{};
|
||||
}
|
||||
|
||||
std::wstring get_log_settings_file_location()
|
||||
{
|
||||
std::filesystem::path result(PTSettingsHelper::get_root_save_folder_location());
|
||||
result = result.append(log_settings_filename);
|
||||
return result.wstring();
|
||||
}
|
||||
}
|
||||
17
src/common/SettingsAPI/settings_helpers.h
Normal file
17
src/common/SettingsAPI/settings_helpers.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <Shlobj.h>
|
||||
|
||||
#include "../utils/json.h"
|
||||
|
||||
namespace PTSettingsHelper
|
||||
{
|
||||
std::wstring get_module_save_folder_location(std::wstring_view powertoy_name);
|
||||
std::wstring get_root_save_folder_location();
|
||||
|
||||
void save_module_settings(std::wstring_view powertoy_name, json::JsonObject& settings);
|
||||
json::JsonObject load_module_settings(std::wstring_view powertoy_name);
|
||||
void save_general_settings(const json::JsonObject& settings);
|
||||
json::JsonObject load_general_settings();
|
||||
std::wstring get_log_settings_file_location();
|
||||
}
|
||||
373
src/common/SettingsAPI/settings_objects.cpp
Normal file
373
src/common/SettingsAPI/settings_objects.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
#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_toggle overloads.
|
||||
void Settings::add_bool_toggle(std::wstring_view name, UINT description_resource_id, bool value)
|
||||
{
|
||||
add_bool_toggle(name, get_resource(description_resource_id), value);
|
||||
}
|
||||
|
||||
void Settings::add_bool_toggle(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);
|
||||
}
|
||||
|
||||
void Settings::add_header_szLarge(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"header_large"));
|
||||
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_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<std::pair<std::wstring, UINT>>& keys_and_text_ids)
|
||||
{
|
||||
std::vector<std::pair<std::wstring, std::wstring>> 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<std::pair<std::wstring, std::wstring>>& 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<std::pair<std::wstring, UINT>>& keys_and_text_ids)
|
||||
{
|
||||
std::vector<std::pair<std::wstring, std::wstring>> 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<std::pair<std::wstring, std::wstring>>& 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<wchar_t*>(&res_ptr), 0);
|
||||
if (resource_length != 0)
|
||||
{
|
||||
return { *reinterpret_cast<wchar_t**>(&res_ptr), resource_length };
|
||||
}
|
||||
}
|
||||
|
||||
return L"RESOURCE ID NOT FOUND: " + std::to_wstring(resource_id);
|
||||
}
|
||||
|
||||
PowerToyValues::PowerToyValues(std::wstring_view powertoy_name, std::wstring_view powertoy_key)
|
||||
{
|
||||
_key = powertoy_key;
|
||||
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, std::wstring_view powertoy_key)
|
||||
{
|
||||
PowerToyValues result = PowerToyValues();
|
||||
json::JsonObject jsonObject = json::JsonValue::Parse(json).GetObjectW();
|
||||
if (!jsonObject.HasKey(L"name"))
|
||||
{
|
||||
throw winrt::hresult_error(E_NOT_SET, L"name field not set");
|
||||
}
|
||||
|
||||
result.m_json = json::JsonValue::Parse(json).GetObjectW();
|
||||
result._key = powertoy_key;
|
||||
return result;
|
||||
}
|
||||
|
||||
PowerToyValues PowerToyValues::load_from_settings_file(std::wstring_view powertoy_key)
|
||||
{
|
||||
PowerToyValues result = PowerToyValues();
|
||||
result.m_json = PTSettingsHelper::load_module_settings(powertoy_key);
|
||||
result._key = powertoy_key;
|
||||
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<bool> 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<int> 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<int>(m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedNumber(L"value"));
|
||||
}
|
||||
|
||||
std::optional<std::wstring> 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<json::JsonObject> 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");
|
||||
}
|
||||
|
||||
json::JsonObject PowerToyValues::get_raw_json()
|
||||
{
|
||||
return m_json;
|
||||
}
|
||||
|
||||
std::wstring PowerToyValues::serialize()
|
||||
{
|
||||
set_version();
|
||||
return m_json.Stringify().c_str();
|
||||
}
|
||||
|
||||
void PowerToyValues::save_to_settings_file()
|
||||
{
|
||||
set_version();
|
||||
PTSettingsHelper::save_module_settings(_key, m_json);
|
||||
}
|
||||
|
||||
void PowerToyValues::set_version()
|
||||
{
|
||||
m_json.SetNamedValue(L"version", json::value(m_version));
|
||||
}
|
||||
}
|
||||
223
src/common/SettingsAPI/settings_objects.h
Normal file
223
src/common/SettingsAPI/settings_objects.h
Normal file
@@ -0,0 +1,223 @@
|
||||
#pragma once
|
||||
|
||||
#include "../utils/json.h"
|
||||
|
||||
namespace PowerToysSettings
|
||||
{
|
||||
class HotkeyObject;
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings(
|
||||
const HINSTANCE hinstance, // Module handle of the PowerToy DLL 'IMAGE_DOS_HEADER __ImageBase'
|
||||
std::wstring_view powertoy_name);
|
||||
|
||||
// Add additional general information to the PowerToy settings.
|
||||
void set_description(UINT resource_id);
|
||||
void set_description(std::wstring_view description);
|
||||
|
||||
void set_icon_key(std::wstring_view icon_key);
|
||||
void set_overview_link(std::wstring_view overview_link);
|
||||
void set_video_link(std::wstring_view video_link);
|
||||
|
||||
// Add properties to the PowerToy settings.
|
||||
void add_bool_toggle(std::wstring_view name, UINT description_resource_id, bool value);
|
||||
void add_bool_toggle(std::wstring_view name, std::wstring_view description, bool value);
|
||||
|
||||
void add_int_spinner(std::wstring_view name, UINT description_resource_id, int value, int min, int max, int step);
|
||||
void add_int_spinner(std::wstring_view name, std::wstring_view description, int value, int min, int max, int step);
|
||||
|
||||
void add_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
|
||||
void add_string(std::wstring_view name, std::wstring_view description, std::wstring_view value);
|
||||
|
||||
void add_multiline_string(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
|
||||
void add_multiline_string(std::wstring_view name, std::wstring_view description, std::wstring_view value);
|
||||
|
||||
void add_color_picker(std::wstring_view name, UINT description_resource_id, std::wstring_view value);
|
||||
void add_color_picker(std::wstring_view name, std::wstring_view description, std::wstring_view value);
|
||||
|
||||
void add_hotkey(std::wstring_view name, UINT description_resource_id, const HotkeyObject& hotkey);
|
||||
void add_hotkey(std::wstring_view name, std::wstring_view description, const HotkeyObject& hotkey);
|
||||
|
||||
void add_choice_group(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
|
||||
void add_choice_group(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
|
||||
|
||||
void add_dropdown(std::wstring_view name, UINT description_resource_id, std::wstring_view value, const std::vector<std::pair<std::wstring, UINT>>& keys_and_text_ids);
|
||||
void add_dropdown(std::wstring_view name, std::wstring_view description, std::wstring_view value, const std::vector<std::pair<std::wstring, std::wstring>>& keys_and_texts);
|
||||
|
||||
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, UINT ext_description_resource_id);
|
||||
void add_custom_action(std::wstring_view name, UINT description_resource_id, UINT button_text_resource_id, std::wstring_view value);
|
||||
void add_custom_action(std::wstring_view name, std::wstring_view description, std::wstring_view button_text, std::wstring_view value);
|
||||
|
||||
void add_header_szLarge(std::wstring_view name, std::wstring_view description, std::wstring_view value);
|
||||
// Serialize the internal json to a string.
|
||||
std::wstring serialize();
|
||||
// Serialize the internal json to the input buffer.
|
||||
bool serialize_to_buffer(wchar_t* buffer, int* buffer_size);
|
||||
|
||||
private:
|
||||
json::JsonObject m_json;
|
||||
int m_curr_priority = 0; // For keeping order when adding elements.
|
||||
HINSTANCE m_instance;
|
||||
|
||||
std::wstring get_resource(UINT resource_id);
|
||||
};
|
||||
|
||||
class PowerToyValues
|
||||
{
|
||||
public:
|
||||
PowerToyValues(std::wstring_view powertoy_name, std::wstring_view powertoy_key);
|
||||
static PowerToyValues from_json_string(std::wstring_view json, std::wstring_view powertoy_key);
|
||||
static PowerToyValues load_from_settings_file(std::wstring_view powertoy_key);
|
||||
|
||||
template<typename T>
|
||||
inline void add_property(std::wstring_view name, T value)
|
||||
{
|
||||
json::JsonObject prop_value;
|
||||
prop_value.SetNamedValue(L"value", json::value(value));
|
||||
m_json.GetNamedObject(L"properties").SetNamedValue(name, prop_value);
|
||||
}
|
||||
|
||||
std::optional<bool> get_bool_value(std::wstring_view property_name);
|
||||
std::optional<int> get_int_value(std::wstring_view property_name);
|
||||
std::optional<std::wstring> get_string_value(std::wstring_view property_name);
|
||||
std::optional<json::JsonObject> get_json(std::wstring_view property_name);
|
||||
json::JsonObject get_raw_json();
|
||||
|
||||
std::wstring serialize();
|
||||
void save_to_settings_file();
|
||||
|
||||
private:
|
||||
const std::wstring m_version = L"1.0";
|
||||
void set_version();
|
||||
json::JsonObject m_json;
|
||||
std::wstring _key;
|
||||
PowerToyValues() {}
|
||||
};
|
||||
|
||||
class CustomActionObject
|
||||
{
|
||||
public:
|
||||
static CustomActionObject from_json_string(std::wstring_view json)
|
||||
{
|
||||
return CustomActionObject(json::JsonValue::Parse(json).GetObjectW());
|
||||
}
|
||||
|
||||
std::wstring get_name() { return m_json.GetNamedString(L"action_name").c_str(); }
|
||||
std::wstring get_value() { return m_json.GetNamedString(L"value").c_str(); }
|
||||
|
||||
protected:
|
||||
CustomActionObject(json::JsonObject action_json) :
|
||||
m_json(std::move(action_json)){};
|
||||
json::JsonObject m_json;
|
||||
};
|
||||
|
||||
class HotkeyObject
|
||||
{
|
||||
public:
|
||||
static HotkeyObject from_json(json::JsonObject json)
|
||||
{
|
||||
return HotkeyObject(std::move(json));
|
||||
}
|
||||
static HotkeyObject from_json_string(std::wstring_view json)
|
||||
{
|
||||
return HotkeyObject(json::JsonValue::Parse(json).GetObjectW());
|
||||
}
|
||||
static HotkeyObject from_settings(bool win_pressed, bool ctrl_pressed, bool alt_pressed, bool shift_pressed, UINT vk_code)
|
||||
{
|
||||
json::JsonObject json;
|
||||
json.SetNamedValue(L"win", json::value(win_pressed));
|
||||
json.SetNamedValue(L"ctrl", json::value(ctrl_pressed));
|
||||
json.SetNamedValue(L"alt", json::value(alt_pressed));
|
||||
json.SetNamedValue(L"shift", json::value(shift_pressed));
|
||||
json.SetNamedValue(L"code", json::value(vk_code));
|
||||
json.SetNamedValue(L"key", json::value(key_from_code(vk_code)));
|
||||
return std::move(json);
|
||||
}
|
||||
const json::JsonObject& get_json() const { return m_json; }
|
||||
|
||||
std::wstring get_key() const { return m_json.GetNamedString(L"key").c_str(); }
|
||||
UINT get_code() const { return static_cast<UINT>(m_json.GetNamedNumber(L"code")); }
|
||||
bool win_pressed() const { return m_json.GetNamedBoolean(L"win"); }
|
||||
bool ctrl_pressed() const { return m_json.GetNamedBoolean(L"ctrl"); }
|
||||
bool alt_pressed() const { return m_json.GetNamedBoolean(L"alt"); }
|
||||
bool shift_pressed() const { return m_json.GetNamedBoolean(L"shift"); }
|
||||
UINT get_modifiers_repeat() const
|
||||
{
|
||||
return (win_pressed() ? MOD_WIN : 0) |
|
||||
(ctrl_pressed() ? MOD_CONTROL : 0) |
|
||||
(alt_pressed() ? MOD_ALT : 0) |
|
||||
(shift_pressed() ? MOD_SHIFT : 0);
|
||||
}
|
||||
UINT get_modifiers() const
|
||||
{
|
||||
return get_modifiers_repeat() | MOD_NOREPEAT;
|
||||
}
|
||||
|
||||
protected:
|
||||
static std::wstring key_from_code(UINT key_code)
|
||||
{
|
||||
auto layout = GetKeyboardLayout(0);
|
||||
auto scan_code = MapVirtualKeyExW(key_code, MAPVK_VK_TO_VSC_EX, layout);
|
||||
// Determinate if vk is an extended key. Unfortunately MAPVK_VK_TO_VSC_EX
|
||||
// does not return correct values.
|
||||
static std::vector<UINT> extended_keys = {
|
||||
VK_APPS,
|
||||
VK_CANCEL,
|
||||
VK_SNAPSHOT,
|
||||
VK_DIVIDE,
|
||||
VK_NUMLOCK,
|
||||
VK_LWIN,
|
||||
VK_RWIN,
|
||||
VK_RMENU,
|
||||
VK_RCONTROL,
|
||||
VK_RSHIFT,
|
||||
VK_RETURN,
|
||||
VK_INSERT,
|
||||
VK_DELETE,
|
||||
VK_PRIOR,
|
||||
VK_NEXT,
|
||||
VK_HOME,
|
||||
VK_END,
|
||||
VK_UP,
|
||||
VK_DOWN,
|
||||
VK_LEFT,
|
||||
VK_RIGHT,
|
||||
};
|
||||
if (find(begin(extended_keys), end(extended_keys), key_code) != end(extended_keys))
|
||||
{
|
||||
scan_code |= 0x100;
|
||||
}
|
||||
std::array<BYTE, 256> key_states{}; // Zero-initialize
|
||||
std::array<wchar_t, 256> output;
|
||||
auto output_bytes = ToUnicodeEx(key_code, scan_code, key_states.data(), output.data(), (int)output.size() - 1, 0, layout);
|
||||
if (output_bytes <= 0)
|
||||
{
|
||||
// If ToUnicodeEx fails (e.g. for F1-F12 keys) use GetKeyNameTextW
|
||||
output_bytes = GetKeyNameTextW(scan_code << 16, output.data(), static_cast<int>(output.size()));
|
||||
}
|
||||
if (output_bytes > 0)
|
||||
{
|
||||
output[output_bytes] = 0;
|
||||
if (output_bytes == 1 && output[0] >= 'a' && output[0] <= 'z')
|
||||
{
|
||||
// Make Latin letters keys capital, as it looks better
|
||||
output[0] = toupper(output[0]);
|
||||
}
|
||||
return output.data();
|
||||
}
|
||||
return L"(Key " + std::to_wstring(key_code) + L")";
|
||||
}
|
||||
HotkeyObject(json::JsonObject hotkey_json) :
|
||||
m_json(std::move(hotkey_json))
|
||||
{
|
||||
if (get_key() == L"~" && get_modifiers_repeat() == MOD_WIN)
|
||||
{
|
||||
m_json.SetNamedValue(L"key", json::value(key_from_code(get_code())));
|
||||
}
|
||||
};
|
||||
json::JsonObject m_json;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user