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 {