Update Settings Page.

This commit is contained in:
Bruce
2025-11-29 18:19:08 +08:00
parent 87efdc39df
commit cf50b09bf0
111 changed files with 7115 additions and 322 deletions

348
settings/vemani.h Normal file
View File

@@ -0,0 +1,348 @@
#pragma once
#include <Windows.h>
#include <pugiconfig.hpp>
#include <pugixml.hpp>
#include <string>
#include <fstream>
#include <sstream>
#include <codecvt>
#include <locale>
#include <cstdio>
#include "strcmp.h"
#include "dynarr.h"
#include "themeinfo.h"
#include "nstring.h"
#include "filepath.h"
class vemanifest
{
public:
enum class TextColor { dark = 0x000000, light = 0xFFFFFF };
vemanifest (): available (false) {}
vemanifest (LPCSTR filename): available (false) { create (filename); }
vemanifest (const std::string &filename): available (false) { create (filename); }
vemanifest (LPCWSTR filename): available (false) { create (filename); }
vemanifest (const std::wstring &filename): available (false) { create (filename); }
vemanifest (std::ifstream &stream): available (false) { create (stream); }
vemanifest (std::fstream &stream): available (false) { create (stream); }
vemanifest (FILE *file): available (false) { create (file); }
~vemanifest () { destroy (); }
bool create (LPCSTR filename)
{
destroy ();
pugi::xml_parse_result result = doc.load_file (filename);
available = result; return available;
}
bool create (const std::string &filename) { return create (filename.c_str ()); }
bool create (LPCWSTR filename)
{
destroy ();
std::wstring ws (filename);
std::string s = to_utf8 (ws);
pugi::xml_parse_result result = doc.load_file (s.c_str ());
available = result; return available;
}
bool create (const std::wstring &filename) { return create (filename.c_str ()); }
bool create (std::ifstream &stream)
{
destroy ();
std::stringstream buffer; buffer << stream.rdbuf ();
std::string content = buffer.str ();
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
bool create (std::fstream &stream)
{
destroy ();
std::stringstream buffer; buffer << stream.rdbuf ();
std::string content = buffer.str ();
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
bool create (FILE *file)
{
destroy ();
if (!file) { return false; }
fseek (file, 0, SEEK_END);
long length = ftell (file);
fseek (file, 0, SEEK_SET);
std::string content (length, '\0');
fread (&content [0], 1, length, file);
pugi::xml_parse_result result = doc.load_string (content.c_str ());
available = result; return available;
}
void destroy () { if (!available) return; doc.reset (); available = false; }
bool valid () const { return available; }
std::string display_name (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("DisplayName").as_string () : "";
}
std::wstring display_name (const std::wstring &id = L"App") const { return pugi::as_wide (this->display_name (pugi::as_utf8 (id))); }
std::string logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string logo = visual.attribute ("Logo").as_string ();
return !logo.empty () ? logo : visual.attribute ("Square150x150Logo").as_string ();
}
std::wstring logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->logo (pugi::as_utf8 (id))); }
std::string small_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string smallLogo = visual.attribute ("SmallLogo").as_string ();
return !smallLogo.empty () ? smallLogo : visual.attribute ("Square70x70Logo").as_string ();
}
std::wstring small_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->small_logo (pugi::as_utf8 (id))); }
TextColor foreground_text (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return TextColor::dark;
std::string fg = visual.attribute ("ForegroundText").as_string ();
return (fg == "light") ? TextColor::light : TextColor::dark;
}
TextColor foreground_text (const std::wstring &id = L"App") const { return (this->foreground_text (pugi::as_utf8 (id))); }
std::string lnk_32x32_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("Lnk32x32Logo").as_string () : "";
}
std::wstring lnk_32x32_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->lnk_32x32_logo (pugi::as_utf8 (id))); }
std::string item_display_logo (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
std::string itemLogo = visual.attribute ("ItemDisplayLogo").as_string ();
if (!itemLogo.empty ()) return itemLogo;
itemLogo = visual.attribute ("Lnk32x32Logo").as_string ();
return !itemLogo.empty () ? itemLogo : visual.attribute ("Square44x44Logo").as_string ();
}
std::wstring item_display_logo (const std::wstring &id = L"App") const { return pugi::as_wide (this->item_display_logo (pugi::as_utf8 (id))); }
bool show_name_on_tile (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? (std::string (visual.attribute ("ShowNameOnSquare150x150Logo").as_string ()) == "on") : false;
}
bool show_name_on_tile (const std::wstring &id = L"App") const { return (this->show_name_on_tile (pugi::as_utf8 (id))); }
std::string background_color (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
return visual ? visual.attribute ("BackgroundColor").as_string () : "";
}
std::wstring background_color (const std::wstring &id = L"App") const { return pugi::as_wide (this->background_color (pugi::as_utf8 (id))); }
std::string splash_screen_image (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
return splash ? splash.attribute ("Image").as_string () : "";
}
std::wstring splash_screen_image (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_image (pugi::as_utf8 (id))); }
std::string splash_screen_backgroundcolor (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
std::string bg = splash ? splash.attribute ("BackgroundColor").as_string () : "";
return !bg.empty () ? bg : visual.attribute ("BackgroundColor").as_string ();
}
std::wstring splash_screen_backgroundcolor (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_backgroundcolor (pugi::as_utf8 (id))); }
std::string splash_screen_backgroundcolor_darkmode (const std::string &id = "App") const
{
pugi::xml_node visual = visual_element_node (id);
if (!visual) return "";
pugi::xml_node splash = visual.child ("SplashScreen");
std::string bg = splash ? splash.attribute ("DarkModeBackgroundColor").as_string () : "";
return !bg.empty () ? bg : visual.attribute ("DarkModeBackgroundColor").as_string ();
}
std::wstring splash_screen_backgroundcolor_darkmode (const std::wstring &id = L"App") const { return pugi::as_wide (this->splash_screen_backgroundcolor_darkmode (pugi::as_utf8 (id))); }
bool is_appid_exists (const std::string &id) const
{
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id)) return true;
}
return pugi::xml_node ();
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id)) return true;
}
return false;
}
bool is_appid_exists (const std::wstring &id) const { return this->is_appid_exists (pugi::as_utf8 (id)); }
size_t app_ids (std::vector <std::string> &output) const
{
if (!&output) return 0;
output.clear ();
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, std::string (lp));
}
}
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr)
{
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, std::string (lp));
}
}
}
if (!output.size ()) push_unique (output, std::string ("App"));
return output.size ();
}
size_t app_ids (std::vector <std::wstring> &output) const
{
if (!&output) return 0;
output.clear ();
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, pugi::as_wide (lp));
}
}
}
else if (rootName == "Application")
{
pugi::xml_attribute attr = root.attribute ("Id");
if (attr)
{
if (attr)
{
LPCSTR lp = attr.value ();
if (lp) push_unique (output, pugi::as_wide (lp));
}
}
}
if (!output.size ()) push_unique (output, std::wstring (L"App"));
return output.size ();
}
private:
pugi::xml_document doc;
bool available;
// 根据 id 查找 VisualElements 节点:若根节点为 <Applications>,遍历所有 <Application> 查找其 <VisualElements> 节点中属性 Id 等于 id若根节点为 <Application>,直接返回其 <VisualElements>
pugi::xml_node visual_element_node (const std::string &id) const
{
pugi::xml_node root = doc.document_element ();
std::string rootName = root.name ();
if (rootName == "Applications")
{
for (pugi::xml_node app : root.children ("Application"))
{
pugi::xml_attribute attr = app.attribute ("Id");
if (attr && LabelEqual (std::string (attr.value ()), id))
{
pugi::xml_node visual = app.child ("VisualElements");
if (visual) return visual;
}
}
return pugi::xml_node ();
}
else if (rootName == "Application") return root.child ("VisualElements");
return pugi::xml_node ();
}
std::string to_utf8 (const std::wstring &wstr) const
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.to_bytes (wstr);
}
};
class resxmldoc
{
private:
std::wstring filepath;
pugi::xml_document doc;
bool available = false;
std::string to_utf8 (const std::wstring &wstr) const
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.to_bytes (wstr);
}
public:
resxmldoc (const std::wstring &xmlpath) { create (xmlpath); }
void destroy () { if (!available) return; doc.reset (); available = false; }
~resxmldoc () { destroy (); }
bool create (const std::wstring &xmlpath)
{
destroy ();
std::wstring ws (filepath = xmlpath);
std::string s = to_utf8 (ws);
pugi::xml_parse_result result = doc.load_file (s.c_str ());
available = result; return available;
}
std::string get (const std::string &id) const
{
auto root = doc.first_child ();
auto nodes = root.children ();
for (auto it : nodes)
{
if (IsNormalizeStringEquals (std::string (it.attribute ("id").as_string ()), id))
{
auto scales = it.children ();
std::map <int, std::string> s_v;
for (auto it_s : scales)
{
std::string dpi = it_s.attribute ("dpi").as_string ();
if (IsNormalizeStringEquals (dpi.c_str (), "default")) { s_v [0] = it_s.text ().get (); }
else
{
try { s_v [it_s.attribute ("dpi").as_int ()] = it_s.text ().get (); }
catch (...) {}
}
}
std::vector <std::pair <int, std::string>> existfilepath;
{
std::vector <std::pair <int, std::string>> vec (s_v.begin (), s_v.end ());
std::sort (vec.begin (), vec.end (), [] (auto &a, auto &b) { return a.second < b.second; });
for (auto &it_ss : vec)
{
it_ss.second = pugi::as_utf8 (CombinePath (GetFileDirectoryW (filepath), pugi::as_wide (it_ss.second)));
if (IsFileExists (pugi::as_wide (it_ss.second))) existfilepath.push_back (it_ss);
}
}
int dpipercent = GetDPI ();
for (auto &it_path : existfilepath)
{
if (it_path.first >= dpipercent) return it_path.second;
}
if (!existfilepath.empty ()) return existfilepath.at (0).second;
return "";
break;
}
}
return "";
}
std::wstring get (const std::wstring &id) const { return pugi::as_wide (get (WStringToString (id))); }
std::wstring operator [] (const std::wstring &id) const { return get (id); }
std::wstring operator [] (const std::wstring &id) { return get (id); }
std::string operator [] (const std::string &id) const { return get (id); }
std::string operator [] (const std::string &id) { return get (id); }
};