feat: 支持打开配置文件位置

This commit is contained in:
刘旭 2022-08-18 14:29:15 +08:00
commit 6ddea9765c
15 changed files with 95 additions and 77 deletions

View file

@ -419,6 +419,9 @@
<Page Include="AboutPage.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="Button.xaml">
<SubType>Designer</SubType>
</Page>
<Page Include="ScalingProfilePage.xaml">
<SubType>Designer</SubType>
</Page>

View file

@ -192,6 +192,9 @@
<Page Include="ShortcutDialog.xaml">
<Filter>Controls</Filter>
</Page>
<Page Include="Button.xaml">
<Filter>Styles</Filter>
</Page>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">

View file

@ -147,6 +147,7 @@
<ResourceDictionary.MergedDictionaries>
<muxc:XamlControlsResources ControlsResourcesVersion="Version2" />
<ResourceDictionary Source="ms-appx:///Button.xaml" />
<ResourceDictionary Source="ms-appx:///ToggleSwitch.xaml" />
<ResourceDictionary Source="ms-appx:///KeyVisual.xaml" />
</ResourceDictionary.MergedDictionaries>

View file

@ -16,34 +16,6 @@ using namespace Magpie::Runtime;
namespace winrt::Magpie::App {
static hstring GetWorkingDir(bool isPortableMode) {
if (isPortableMode) {
wchar_t curDir[MAX_PATH];
if (!GetCurrentDirectory(MAX_PATH, curDir)) {
return L"";
}
std::wstring result = curDir;
if (result.back() != L'\\') {
result += L'\\';
}
return result.c_str();
} else {
wchar_t localAppDataDir[MAX_PATH];
HRESULT hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, localAppDataDir);
if (FAILED(hr)) {
return L"";
}
return StrUtils::ConcatW(
localAppDataDir,
localAppDataDir[StrUtils::StrLen(localAppDataDir) - 1] == L'\\' ? L"Magpie\\" : L"\\Magpie\\",
MAGPIE_VERSION_W,
L"\\"
).c_str();
}
}
static bool LoadBoolSettingItem(
const rapidjson::GenericObject<false, rapidjson::Value>& obj,
const char* nodeName,
@ -356,12 +328,11 @@ bool AppSettings::Initialize() {
Logger& logger = Logger::Get();
// 若程序所在目录存在配置文件则为便携模式
_isPortableMode = Win32Utils::FileExists(CommonSharedConstants::CONFIG_PATH_W);
_workingDir = GetWorkingDir(_isPortableMode);
_isPortableMode = Win32Utils::FileExists(
StrUtils::ConcatW(CommonSharedConstants::CONFIG_DIR, CommonSharedConstants::CONFIG_NAME).c_str());
_UpdateConfigPath();
std::wstring configPath = StrUtils::ConcatW(_workingDir, CommonSharedConstants::CONFIG_PATH_W);
if (!Win32Utils::FileExists(configPath.c_str())) {
if (!Win32Utils::FileExists(_configPath.c_str())) {
logger.Info("不存在配置文件");
// 只有不存在配置文件时才生成默认缩放模式
_SetDefaultScaleModes();
@ -369,7 +340,7 @@ bool AppSettings::Initialize() {
}
std::string configText;
if (!Win32Utils::ReadTextFile(configPath.c_str(), configText)) {
if (!Win32Utils::ReadTextFile(_configPath.c_str(), configText)) {
logger.Error("读取配置文件失败");
return false;
}
@ -384,8 +355,7 @@ bool AppSettings::Initialize() {
}
bool AppSettings::Save() {
std::wstring configDir = StrUtils::ConcatW(_workingDir, L"config");
if (!Win32Utils::CreateDir(configDir)) {
if (!Win32Utils::CreateDir(_configDir)) {
Logger::Get().Error("创建配置文件夹失败");
return false;
}
@ -474,7 +444,7 @@ bool AppSettings::Save() {
writer.EndObject();
if (!Win32Utils::WriteTextFile(StrUtils::ConcatW(_workingDir, CommonSharedConstants::CONFIG_PATH_W).c_str(), json.GetString())) {
if (!Win32Utils::WriteTextFile(_configPath.c_str(), json.GetString())) {
Logger::Get().Error("保存配置失败");
return false;
}
@ -490,18 +460,13 @@ void AppSettings::IsPortableMode(bool value) {
if (!value) {
// 关闭便携模式需删除本地配置文件
// 不关心是否成功
DeleteFile(StrUtils::ConcatW(_workingDir, CommonSharedConstants::CONFIG_PATH_W).c_str());
DeleteFile(StrUtils::ConcatW(_configDir, CommonSharedConstants::CONFIG_NAME).c_str());
}
Logger::Get().Info(value ? "已开启便携模式" : "已关闭便携模式");
_isPortableMode = value;
_workingDir = GetWorkingDir(value);
// 确保 WorkingDir 存在
if (!Win32Utils::CreateDir(_workingDir.c_str(), true)) {
Logger::Get().Error(StrUtils::Concat("创建文件夹", StrUtils::UTF16ToUTF8(_workingDir), "失败"));
}
_UpdateConfigPath();
}
void AppSettings::Theme(uint32_t value) {
@ -772,4 +737,37 @@ void AppSettings::_SetDefaultScaleModes() {
}
}
void AppSettings::_UpdateConfigPath() noexcept {
if (_isPortableMode) {
wchar_t curDir[MAX_PATH];
GetCurrentDirectory(MAX_PATH, curDir);
_configDir = curDir;
if (_configDir.back() != L'\\') {
_configDir.push_back(L'\\');
}
_configDir += CommonSharedConstants::CONFIG_DIR;
} else {
wchar_t localAppDataDir[MAX_PATH];
HRESULT hr = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, localAppDataDir);
if (SUCCEEDED(hr)) {
_configDir = StrUtils::ConcatW(
localAppDataDir,
localAppDataDir[StrUtils::StrLen(localAppDataDir) - 1] == L'\\' ? L"Magpie\\" : L"\\Magpie\\",
MAGPIE_VERSION_W,
L"\\",
CommonSharedConstants::CONFIG_DIR
);
} else {
Logger::Get().ComError("SHGetFolderPath 失败", hr);
_configDir = CommonSharedConstants::CONFIG_DIR;
}
}
_configPath = _configDir + CommonSharedConstants::CONFIG_NAME;
// 确保 ConfigDir 存在
Win32Utils::CreateDir(_configDir.c_str(), true);
}
}

View file

@ -19,8 +19,8 @@ public:
bool Save();
hstring WorkingDir() const noexcept {
return _workingDir;
const std::wstring& ConfigDir() const noexcept {
return _configDir;
}
bool IsPortableMode() const noexcept {
@ -213,8 +213,11 @@ private:
void _SetDefaultHotkeys();
void _SetDefaultScaleModes();
void _UpdateConfigPath() noexcept;
bool _isPortableMode = false;
hstring _workingDir;
std::wstring _configDir;
std::wstring _configPath;
// 0: 浅色
// 1: 深色

View file

@ -60,11 +60,16 @@
<ToggleSwitch IsOn="{x:Bind ViewModel.IsShowTrayIcon, Mode=TwoWay}" />
</local:SettingItem.ActionContent>
</local:SettingItem>
<local:SettingItem Title="便携模式"
Description="更改用户数据的保存位置">
<local:SettingItem Title="便携模式">
<local:SettingItem.Icon>
<FontIcon Glyph="&#xE88E;" />
</local:SettingItem.Icon>
<local:SettingItem.Description>
<StackPanel Orientation="Vertical" Spacing="2">
<TextBlock Text="更改配置文件的保存位置" />
<HyperlinkButton Content="打开配置文件位置" Click="{x:Bind ViewModel.OpenConfigLocation}" />
</StackPanel>
</local:SettingItem.Description>
<local:SettingItem.ActionContent>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsPortableMode, Mode=TwoWay}" />
</local:SettingItem.ActionContent>

View file

@ -82,6 +82,10 @@ void SettingsViewModel::IsPortableMode(bool value) noexcept {
_propertyChangedEvent(*this, PropertyChangedEventArgs(L"IsPortableMode"));
}
void SettingsViewModel::OpenConfigLocation() const noexcept {
ShellExecute(NULL, L"explore", AppSettings::Get().ConfigDir().c_str(), nullptr, nullptr, SW_SHOWNORMAL);
}
bool SettingsViewModel::IsShowTrayIcon() const noexcept {
return AppSettings::Get().IsShowTrayIcon();
}

View file

@ -27,6 +27,8 @@ struct SettingsViewModel : SettingsViewModelT<SettingsViewModel> {
bool IsPortableMode() const noexcept;
void IsPortableMode(bool value) noexcept;
void OpenConfigLocation() const noexcept;
bool IsShowTrayIcon() const noexcept;
void IsShowTrayIcon(bool value) noexcept;

View file

@ -10,6 +10,7 @@ namespace Magpie.App
Boolean IsMinimizeAtStartup;
Boolean IsMinimizeAtStartupEnabled { get; };
Boolean IsPortableMode;
void OpenConfigLocation();
Boolean IsShowTrayIcon;
Boolean IsSimulateExclusiveFullscreen;
Boolean IsBreakpointMode;

View file

@ -1,9 +1,7 @@
<!-- Copied from: https://github.com/microsoft/PowerToys/blob/35bfb0f83e5fc08cc04398e7aa98d77774412d3f/src/settings-ui/Settings.UI/Styles/Button.xaml#L96 -->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- This style overrides the default style so that all ToggleSwitches are right aligned, with the label on the left -->
<Style TargetType="ToggleSwitch">
@ -19,10 +17,10 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">
<Grid contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Background="{TemplateBinding Background}"
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
@ -60,10 +58,9 @@
Grid.RowSpan="3"
Grid.ColumnSpan="3"
Margin="0,5"
contract7NotPresent:CornerRadius="{StaticResource ControlCornerRadius}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Background="{ThemeResource ToggleSwitchContainerBackground}"
Control.IsTemplateFocusTarget="True" />
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}" />
<ContentPresenter x:Name="OffContentPresenter"
Grid.RowSpan="3"
Grid.Column="0"
@ -119,8 +116,8 @@
Height="12"
Margin="0,0,1,0"
HorizontalAlignment="Center"
contract7Present:BackgroundSizing="OuterBorderEdge"
Background="{ThemeResource ToggleSwitchKnobFillOn}"
BackgroundSizing="OuterBorderEdge"
BorderBrush="{ThemeResource ToggleSwitchKnobStrokeOn}"
CornerRadius="7"
Opacity="0"

View file

@ -138,7 +138,6 @@ int XamlApp::Run() {
DispatchMessage(&msg);
}
_uwpApp.SaveSettings();
_uwpApp = nullptr;
_HideTrayIcon();
@ -277,6 +276,8 @@ void XamlApp::_Quit() noexcept {
if (_hwndMain) {
DestroyWindow(_hwndMain);
} else {
_uwpApp.SaveSettings();
}
PostQuitMessage(0);

View file

@ -149,7 +149,7 @@ static constexpr const int CACHE_COMPRESSION_LEVEL = 1;
static std::wstring GetCacheFileName(std::wstring_view effectName, std::wstring_view hash, UINT flags) {
// 缓存文件的命名:{效果名}_{标志位16进制}{哈希}
return fmt::format(L"{}{}_{:02x}_{}", CommonSharedConstants::CACHE_DIR_W, effectName, flags, hash);
return fmt::format(L"{}{}_{:02x}_{}", CommonSharedConstants::CACHE_DIR, effectName, flags, hash);
}
void EffectCacheManager::_AddToMemCache(const std::wstring& cacheFileName, const EffectDesc& desc) {
@ -260,8 +260,8 @@ void EffectCacheManager::Save(std::wstring_view effectName, std::wstring_view ha
}
}
if (!Win32Utils::DirExists(CommonSharedConstants::CACHE_DIR_W)) {
if (!CreateDirectory(CommonSharedConstants::CACHE_DIR_W, nullptr)) {
if (!Win32Utils::DirExists(CommonSharedConstants::CACHE_DIR)) {
if (!CreateDirectory(CommonSharedConstants::CACHE_DIR, nullptr)) {
Logger::Get().Win32Error("创建 cache 文件夹失败");
return;
}
@ -272,7 +272,7 @@ void EffectCacheManager::Save(std::wstring_view effectName, std::wstring_view ha
WIN32_FIND_DATA findData{};
HANDLE hFind = Win32Utils::SafeHandle(FindFirstFileEx(
StrUtils::ConcatW(CommonSharedConstants::CACHE_DIR_W, L"*").c_str(),
StrUtils::ConcatW(CommonSharedConstants::CACHE_DIR, L"*").c_str(),
FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH));
if (hFind) {
do {
@ -285,7 +285,7 @@ void EffectCacheManager::Save(std::wstring_view effectName, std::wstring_view ha
continue;
}
if (!DeleteFile(StrUtils::ConcatW(CommonSharedConstants::CACHE_DIR_W, findData.cFileName).c_str())) {
if (!DeleteFile(StrUtils::ConcatW(CommonSharedConstants::CACHE_DIR, findData.cFileName).c_str())) {
Logger::Get().Win32Error(StrUtils::Concat("删除缓存文件 ",
StrUtils::UTF16ToUTF8(findData.cFileName), " 失败"));
}

View file

@ -1470,8 +1470,8 @@ cbuffer __CB2 : register(b1) {
cbHlsl.append("};\n\n");
if (MagApp::Get().GetOptions().IsSaveEffectSources() && !Win32Utils::DirExists(CommonSharedConstants::SOURCES_DIR_W)) {
if (!CreateDirectory(CommonSharedConstants::SOURCES_DIR_W, nullptr)) {
if (MagApp::Get().GetOptions().IsSaveEffectSources() && !Win32Utils::DirExists(CommonSharedConstants::SOURCES_DIR)) {
if (!CreateDirectory(CommonSharedConstants::SOURCES_DIR, nullptr)) {
Logger::Get().Win32Error("创建 sources 文件夹失败");
}
}
@ -1487,8 +1487,8 @@ cbuffer __CB2 : register(b1) {
if (MagApp::Get().GetOptions().IsSaveEffectSources()) {
std::wstring fileName = desc.passes.size() == 1
? fmt::format(L"{}{}.hlsl", CommonSharedConstants::SOURCES_DIR_W, StrUtils::UTF8ToUTF16(desc.name))
: fmt::format(L"{}{}_Pass{}.hlsl", CommonSharedConstants::SOURCES_DIR_W, StrUtils::UTF8ToUTF16(desc.name), id + 1);
? fmt::format(L"{}{}.hlsl", CommonSharedConstants::SOURCES_DIR, StrUtils::UTF8ToUTF16(desc.name))
: fmt::format(L"{}{}_Pass{}.hlsl", CommonSharedConstants::SOURCES_DIR, StrUtils::UTF8ToUTF16(desc.name), id + 1);
if (!Win32Utils::WriteFile(fileName.c_str(), source.data(), source.size())) {
Logger::Get().Error(fmt::format("保存 Pass{} 源码失败", id + 1));
@ -1525,7 +1525,7 @@ UINT EffectCompiler::Compile(
desc.name = StrUtils::UTF16ToUTF8(effectName);
desc.flags = flags;
std::wstring fileName = StrUtils::ConcatW(CommonSharedConstants::EFFECTS_DIR_W, effectName, L".hlsl");
std::wstring fileName = StrUtils::ConcatW(CommonSharedConstants::EFFECTS_DIR, effectName, L".hlsl");
std::string source;
if (!Win32Utils::ReadTextFile(fileName.c_str(), source)) {

View file

@ -190,7 +190,7 @@ bool OverlayDrawer::Initialize() {
static std::vector<BYTE> fontData;
if (fontData.empty()) {
if (!Win32Utils::ReadFile(
StrUtils::ConcatW(CommonSharedConstants::ASSETS_DIR_W, L"NotoSansSC-Regular.otf").c_str(),
StrUtils::ConcatW(CommonSharedConstants::ASSETS_DIR, L"NotoSansSC-Regular.otf").c_str(),
fontData
)) {
Logger::Get().Error("读取字体文件失败");

View file

@ -11,12 +11,12 @@ struct CommonSharedConstants {
static constexpr const COLORREF DARK_TINT_COLOR = RGB(32, 32, 32);
static constexpr const char* LOG_PATH = "logs\\magpie.log";
static constexpr const char* CONFIG_PATH = "config\\config.json";
static constexpr const wchar_t* CONFIG_PATH_W = L"config\\config.json";
static constexpr const wchar_t* SOURCES_DIR_W = L"sources\\";
static constexpr const wchar_t* EFFECTS_DIR_W = L"effects\\";
static constexpr const wchar_t* ASSETS_DIR_W = L"assets\\";
static constexpr const wchar_t* CACHE_DIR_W = L"cache\\";
static constexpr const wchar_t* CONFIG_DIR = L"config\\";
static constexpr const wchar_t* CONFIG_NAME = L"config.json";
static constexpr const wchar_t* SOURCES_DIR = L"sources\\";
static constexpr const wchar_t* EFFECTS_DIR = L"effects\\";
static constexpr const wchar_t* ASSETS_DIR = L"assets\\";
static constexpr const wchar_t* CACHE_DIR = L"cache\\";
static constexpr const wchar_t* OPTION_MINIMIZE_TO_TRAY_AT_STARTUP = L"-t";