From 2a7fc0034cb410b5cabfbc37156e77710d9a8da7 Mon Sep 17 00:00:00 2001 From: ge0rdi Date: Sat, 10 Dec 2022 14:07:03 +0100 Subject: [PATCH] ModernSettings: Remove duplicates Windows started to add newer version of settings to settings description file. These have the same description as older settings, but use different parameters. Unfortunately old settings are still present. This causes our modern settings folder to contain duplicates. And also we tend to use older setting definitions that no longer work properly. Thus we will de-duplicate parsed settings and try to keep newer ones (that should work better). New settings tend to have numeric suffix, so we will keep those with biggest suffix. Fixes #1031 --- .../StartMenuHelper/ModernSettings.cpp | 46 +++++++++++++++---- .../StartMenuHelper/ModernSettings.h | 1 + 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/Src/StartMenu/StartMenuHelper/ModernSettings.cpp b/Src/StartMenu/StartMenuHelper/ModernSettings.cpp index 257c772..88f5a98 100644 --- a/Src/StartMenu/StartMenuHelper/ModernSettings.cpp +++ b/Src/StartMenu/StartMenuHelper/ModernSettings.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -316,9 +317,9 @@ static std::vector ParseSetting(CComPtr& parent) return writer.buffer(); } -static std::vector ParseModernSettings() +static std::vector> ParseModernSettings() { - AttributeWriter writer; + std::vector> retval; CComPtr doc; if (SUCCEEDED(doc.CoCreateInstance(L"Msxml2.FreeThreadedDOMDocument"))) @@ -335,16 +336,13 @@ static std::vector ParseModernSettings() CComPtr root; if (doc->selectSingleNode(CComBSTR(L"PCSettings"), &root) == S_OK) { - FileHdr hdr{}; - writer.addBlob(Id::Header, &hdr, sizeof(hdr)); - CComPtr node; root->get_firstChild(&node); while (node) { auto buffer = ParseSetting(node); if (!buffer.empty()) - writer.addBlob(Id::Blob, buffer.data(), buffer.size()); + retval.push_back(std::move(buffer)); CComPtr next; if (FAILED(node->get_nextSibling(&next))) @@ -355,6 +353,19 @@ static std::vector ParseModernSettings() } } + return retval; +} + +static std::vector SerializeModernSettings(const std::vector>& settings) +{ + AttributeWriter writer; + + FileHdr hdr{}; + writer.addBlob(Id::Header, &hdr, sizeof(hdr)); + + for (const auto& setting : settings) + writer.addBlob(Id::Blob, setting.data(), setting.size()); + return writer.buffer(); } @@ -480,11 +491,30 @@ std::shared_ptr GetModernSettings() s_settings.reset(); // re-parse settings - auto buffer = ParseModernSettings(); - if (!buffer.empty()) + auto settings = ParseModernSettings(); + if (!settings.empty()) { + // sort by setting name (in reverse order) + // this way we will have newer settings (like SomeSetting-2) before older ones + std::stable_sort(settings.begin(), settings.end(), [](const auto& a, const auto& b) { + return ModernSettings::Setting(a).fileName > ModernSettings::Setting(b).fileName; + }); + + // now sort by description (strings presented to the user) + // and keep relative order of items with the same description + std::stable_sort(settings.begin(), settings.end(), [](const auto& a, const auto& b) { + return ModernSettings::Setting(a).description < ModernSettings::Setting(b).description; + }); + + // remove duplicates + settings.erase(std::unique(settings.begin(), settings.end(), [](const auto& a, const auto& b) { + return ModernSettings::Setting(a).description == ModernSettings::Setting(b).description; + }), settings.end()); + // store to file { + auto buffer = SerializeModernSettings(settings); + File f(path.c_str(), GENERIC_WRITE, 0, CREATE_ALWAYS); if (f) { diff --git a/Src/StartMenu/StartMenuHelper/ModernSettings.h b/Src/StartMenu/StartMenuHelper/ModernSettings.h index 08f8732..16fa9c3 100644 --- a/Src/StartMenu/StartMenuHelper/ModernSettings.h +++ b/Src/StartMenu/StartMenuHelper/ModernSettings.h @@ -121,6 +121,7 @@ public: Setting() = default; Setting(const Blob& blob); + Setting(const std::vector& blob) : Setting(Blob{ blob.data(), blob.size() }) {} explicit operator bool() const {