From aa6cb7d650fced948ec3c06c444e000d9e6c767f Mon Sep 17 00:00:00 2001 From: vldmr11080 <57061786+vldmr11080@users.noreply.github.com> Date: Wed, 15 Apr 2020 23:14:17 +0200 Subject: [PATCH] Migrate power rename MRU lists from registry to JSON (#2090) * Handle most recently used search/replace strings within settings. * Check for last modified time of json file and reload it if needed. * Handle changes in MRU search / replace lists size. * Improve handling of changes in MRU list size. * Don't check for last modified time in every getter method. Load only when starting application. * Add const identifier to getter methods. * Address PR comments: Add const to reg and json file paths and set them in constructor initializer. Check pushIdx validity. Move implementation to cpp of PowerRenameUI constructor. * Add error checking when getting values from registry. --- src/modules/powerrename/dll/dllmain.cpp | 5 +- src/modules/powerrename/lib/Settings.cpp | 520 ++++++++++--------- src/modules/powerrename/lib/Settings.h | 28 +- src/modules/powerrename/ui/PowerRenameUI.cpp | 9 +- src/modules/powerrename/ui/PowerRenameUI.h | 8 +- 5 files changed, 308 insertions(+), 262 deletions(-) diff --git a/src/modules/powerrename/dll/dllmain.cpp b/src/modules/powerrename/dll/dllmain.cpp index a952629ca1..2629137635 100644 --- a/src/modules/powerrename/dll/dllmain.cpp +++ b/src/modules/powerrename/dll/dllmain.cpp @@ -250,7 +250,7 @@ public: CSettingsInstance().SetMaxMRUSize(values.get_int_value(L"int_max_mru_size").value()); CSettingsInstance().SetShowIconOnMenu(values.get_bool_value(L"bool_show_icon_on_menu").value()); CSettingsInstance().SetExtendedContextMenuOnly(values.get_bool_value(L"bool_show_extended_menu").value()); - CSettingsInstance().SavePowerRenameData(); + CSettingsInstance().Save(); Trace::SettingsChanged(); } @@ -283,7 +283,6 @@ public: void init_settings() { - CSettingsInstance().LoadPowerRenameData(); m_enabled = CSettingsInstance().GetEnabled(); Trace::EnablePowerRename(m_enabled); } @@ -291,7 +290,7 @@ public: void save_settings() { CSettingsInstance().SetEnabled(m_enabled); - CSettingsInstance().SavePowerRenameData(); + CSettingsInstance().Save(); Trace::EnablePowerRename(m_enabled); } diff --git a/src/modules/powerrename/lib/Settings.cpp b/src/modules/powerrename/lib/Settings.cpp index 33d223cc7d..a7f20dde0c 100644 --- a/src/modules/powerrename/lib/Settings.cpp +++ b/src/modules/powerrename/lib/Settings.cpp @@ -5,14 +5,17 @@ #include #include +#include namespace { - const wchar_t c_powerRenameDataFilePath[] = L"power-rename-settings.json"; + const wchar_t c_powerRenameDataFilePath[] = L"\\power-rename-settings.json"; + const wchar_t c_searchMRUListFilePath[] = L"\\search-mru.json"; + const wchar_t c_replaceMRUListFilePath[] = L"\\replace-mru.json"; const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename"; - const wchar_t c_mruSearchRegPath[] = L"SearchMRU"; - const wchar_t c_mruReplaceRegPath[] = L"ReplaceMRU"; + const wchar_t c_mruSearchRegPath[] = L"\\SearchMRU"; + const wchar_t c_mruReplaceRegPath[] = L"\\ReplaceMRU"; const wchar_t c_enabled[] = L"Enabled"; const wchar_t c_showIconOnMenu[] = L"ShowIcon"; @@ -23,6 +26,8 @@ namespace const wchar_t c_searchText[] = L"SearchText"; const wchar_t c_replaceText[] = L"ReplaceText"; const wchar_t c_mruEnabled[] = L"MRUEnabled"; + const wchar_t c_mruList[] = L"MRUList"; + const wchar_t c_insertionIdx[] = L"InsertionIdx"; long GetRegNumber(const std::wstring& valueName, long defaultValue) { @@ -52,34 +57,218 @@ namespace SetRegNumber(valueName, value ? 1 : 0); } - std::wstring GetRegString(const std::wstring& valueName) { + std::wstring GetRegString(const std::wstring& valueName,const std::wstring& subPath) + { wchar_t value[CSettings::MAX_INPUT_STRING_LEN]; value[0] = L'\0'; DWORD type = REG_SZ; DWORD size = CSettings::MAX_INPUT_STRING_LEN * sizeof(wchar_t); - if (SUCCEEDED(HRESULT_FROM_WIN32(SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, value, &size) == ERROR_SUCCESS))) + std::wstring completePath = std::wstring(c_rootRegPath) + subPath; + if (SHGetValue(HKEY_CURRENT_USER, completePath.c_str(), valueName.c_str(), &type, value, &size) == ERROR_SUCCESS) { return std::wstring(value); } return std::wstring{}; } + + bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime) + { + WIN32_FILE_ATTRIBUTE_DATA attr{}; + if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr)) + { + *lpFileTime = attr.ftLastWriteTime; + return true; + } + return false; + } } -typedef int (CALLBACK* MRUCMPPROC)(LPCWSTR, LPCWSTR); +class MRUListHandler +{ +public: + MRUListHandler(int size, const std::wstring& filePath, const std::wstring& regPath) : + pushIdx(0), + nextIdx(1), + size(size), + jsonFilePath(PTSettingsHelper::get_module_save_folder_location(L"PowerRename") + filePath), + registryFilePath(regPath) + { + items.resize(size); + Load(); + } -typedef struct { - DWORD cbSize; - UINT uMax; - UINT fFlags; - HKEY hKey; - LPCTSTR lpszSubKey; - MRUCMPPROC lpfnCompare; -} MRUINFO; + void Push(const std::wstring& data); + bool Next(std::wstring& data); -typedef HANDLE (*CreateMRUListFn)(MRUINFO* pmi); -typedef int (*AddMRUStringFn)(HANDLE hMRU, LPCWSTR data); -typedef int (*EnumMRUListFn)(HANDLE hMRU, int nItem, void* lpData, UINT uLen); -typedef int (*FreeMRUListFn)(HANDLE hMRU); + void Reset(); + +private: + void Load(); + void Save(); + void MigrateFromRegistry(); + json::JsonArray Serialize(); + void ParseJson(); + + bool Exists(const std::wstring& data); + + std::vector items; + long pushIdx; + long nextIdx; + long size; + const std::wstring jsonFilePath; + const std::wstring registryFilePath; +}; + + +void MRUListHandler::Push(const std::wstring& data) +{ + if (Exists(data)) + { + // TODO: Already existing item should be put on top of MRU list. + return; + } + items[pushIdx] = data; + pushIdx = (pushIdx + 1) % size; + Save(); +} + +bool MRUListHandler::Next(std::wstring& data) +{ + if (nextIdx == size + 1) + { + Reset(); + return false; + } + // Go backwards to consume latest items first. + long idx = (pushIdx + size - nextIdx) % size; + if (items[idx].empty()) + { + Reset(); + return false; + } + data = items[idx]; + ++nextIdx; + return true; +} + +void MRUListHandler::Reset() +{ + nextIdx = 1; +} + +void MRUListHandler::Load() +{ + if (!std::filesystem::exists(jsonFilePath)) + { + MigrateFromRegistry(); + + Save(); + } + else + { + ParseJson(); + } +} + +void MRUListHandler::Save() +{ + json::JsonObject jsonData; + + jsonData.SetNamedValue(c_maxMRUSize, json::value(size)); + jsonData.SetNamedValue(c_insertionIdx, json::value(pushIdx)); + jsonData.SetNamedValue(c_mruList, Serialize()); + + json::to_file(jsonFilePath, jsonData); +} + +json::JsonArray MRUListHandler::Serialize() +{ + json::JsonArray searchMRU{}; + + std::wstring data{}; + for (const std::wstring& item : items) + { + searchMRU.Append(json::value(item)); + } + + return searchMRU; +} + +void MRUListHandler::MigrateFromRegistry() +{ + std::wstring searchListKeys = GetRegString(c_mruList, registryFilePath); + std::sort(std::begin(searchListKeys), std::end(searchListKeys)); + for (const wchar_t& key : searchListKeys) + { + Push(GetRegString(std::wstring(1, key), registryFilePath)); + } +} + +void MRUListHandler::ParseJson() +{ + auto json = json::from_file(jsonFilePath); + if (json) + { + const json::JsonObject& jsonObject = json.value(); + try + { + long oldSize{ size }; + if (json::has(jsonObject, c_maxMRUSize, json::JsonValueType::Number)) + { + oldSize = (long)jsonObject.GetNamedNumber(c_maxMRUSize); + } + long oldPushIdx{ 0 }; + if (json::has(jsonObject, c_insertionIdx, json::JsonValueType::Number)) + { + oldPushIdx = (long)jsonObject.GetNamedNumber(c_insertionIdx); + if (oldPushIdx < 0 || oldPushIdx >= oldSize) + { + oldPushIdx = 0; + } + } + if (json::has(jsonObject, c_mruList, json::JsonValueType::Array)) + { + auto jsonArray = jsonObject.GetNamedArray(c_mruList); + if (oldSize == size) + { + for (uint32_t i = 0; i < jsonArray.Size(); ++i) + { + items[i] = std::wstring(jsonArray.GetStringAt(i)); + } + pushIdx = oldPushIdx; + } + else + { + std::vector temp; + for (uint32_t i = 0; i < min(jsonArray.Size(), size); ++i) + { + int idx = (oldPushIdx + oldSize - (i + 1)) % oldSize; + temp.push_back(std::wstring(jsonArray.GetStringAt(idx))); + } + if (size > oldSize) + { + std::reverse(std::begin(temp), std::end(temp)); + pushIdx = (long)temp.size(); + temp.resize(size); + } + else + { + temp.resize(size); + std::reverse(std::begin(temp), std::end(temp)); + } + items = std::move(temp); + Save(); + } + } + } + catch (const winrt::hresult_error&) { } + } +} + +bool MRUListHandler::Exists(const std::wstring& data) +{ + return std::find(std::begin(items), std::end(items), data) != std::end(items); +} class CRenameMRU : public IEnumString, @@ -100,65 +289,33 @@ public: // IPowerRenameMRU IFACEMETHODIMP AddMRUString(_In_ PCWSTR entry); - static HRESULT CreateInstance(_In_ PCWSTR regPathMRU, _In_ ULONG maxMRUSize, _Outptr_ IUnknown** ppUnk); + static HRESULT CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _Outptr_ IUnknown** ppUnk); private: - CRenameMRU(); - ~CRenameMRU(); + CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath); - HRESULT _Initialize(_In_ PCWSTR regPathMRU, __in ULONG maxMRUSize); - HRESULT _CreateMRUList(_In_ MRUINFO* pmi); - int _AddMRUString(_In_ PCWSTR data); - int _EnumMRUList(_In_ int nItem, _Out_ void* lpData, _In_ UINT uLen); - void _FreeMRUList(); - - long m_refCount = 0; - HKEY m_hKey = NULL; - ULONG m_maxMRUSize = 0; - ULONG m_mruIndex = 0; - ULONG m_mruSize = 0; - HANDLE m_mruHandle = NULL; - HMODULE m_hComctl32Dll = NULL; - PWSTR m_regPath = nullptr; + std::unique_ptr mruList; + long refCount = 0; }; -CRenameMRU::CRenameMRU() : - m_refCount(1) -{} - -CRenameMRU::~CRenameMRU() +CRenameMRU::CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath) : + refCount(1) { - if (m_hKey) - { - RegCloseKey(m_hKey); - } - - _FreeMRUList(); - - if (m_hComctl32Dll) - { - FreeLibrary(m_hComctl32Dll); - } - - CoTaskMemFree(m_regPath); + mruList = std::make_unique(size, filePath, regPath); } -HRESULT CRenameMRU::CreateInstance(_In_ PCWSTR regPathMRU, _In_ ULONG maxMRUSize, _Outptr_ IUnknown** ppUnk) +HRESULT CRenameMRU::CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _Outptr_ IUnknown** ppUnk) { *ppUnk = nullptr; - HRESULT hr = (regPathMRU && maxMRUSize > 0) ? S_OK : E_FAIL; + long maxMRUSize = CSettingsInstance().GetMaxMRUSize(); + HRESULT hr = maxMRUSize > 0 ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { - CRenameMRU* renameMRU = new CRenameMRU(); + CRenameMRU* renameMRU = new CRenameMRU(maxMRUSize, filePath, regPath); hr = renameMRU ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hr)) { - hr = renameMRU->_Initialize(regPathMRU, maxMRUSize); - if (SUCCEEDED(hr)) - { - hr = renameMRU->QueryInterface(IID_PPV_ARGS(ppUnk)); - } - + renameMRU->QueryInterface(IID_PPV_ARGS(ppUnk)); renameMRU->Release(); } } @@ -166,21 +323,20 @@ HRESULT CRenameMRU::CreateInstance(_In_ PCWSTR regPathMRU, _In_ ULONG maxMRUSize return hr; } -// IUnknown IFACEMETHODIMP_(ULONG) CRenameMRU::AddRef() { - return InterlockedIncrement(&m_refCount); + return InterlockedIncrement(&refCount); } IFACEMETHODIMP_(ULONG) CRenameMRU::Release() { - long refCount = InterlockedDecrement(&m_refCount); + long cnt = InterlockedDecrement(&refCount); - if (refCount == 0) + if (cnt == 0) { delete this; } - return refCount; + return cnt; } IFACEMETHODIMP CRenameMRU::QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv) @@ -193,57 +349,8 @@ IFACEMETHODIMP CRenameMRU::QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv) return QISearch(this, qit, riid, ppv); } -HRESULT CRenameMRU::_Initialize(_In_ PCWSTR regPathMRU, __in ULONG maxMRUSize) -{ - m_maxMRUSize = maxMRUSize; - - wchar_t regPath[MAX_PATH] = { 0 }; - HRESULT hr = StringCchPrintf(regPath, ARRAYSIZE(regPath), L"%s\\%s", c_rootRegPath, regPathMRU); - if (SUCCEEDED(hr)) - { - hr = SHStrDup(regPathMRU, &m_regPath); - - if (SUCCEEDED(hr)) - { - MRUINFO mi = { - sizeof(MRUINFO), - maxMRUSize, - 0, - HKEY_CURRENT_USER, - regPath, - nullptr - }; - - hr = _CreateMRUList(&mi); - if (SUCCEEDED(hr)) - { - m_mruSize = _EnumMRUList(-1, NULL, 0); - } - else - { - hr = E_FAIL; - } - } - } - - return hr; -} - -// IEnumString -IFACEMETHODIMP CRenameMRU::Reset() -{ - m_mruIndex = 0; - return S_OK; -} - -#define MAX_ENTRY_STRING 1024 - IFACEMETHODIMP CRenameMRU::Next(__in ULONG celt, __out_ecount_part(celt, *pceltFetched) LPOLESTR* rgelt, __out_opt ULONG* pceltFetched) { - HRESULT hr = S_OK; - WCHAR mruEntry[MAX_ENTRY_STRING]; - mruEntry[0] = L'\0'; - if (pceltFetched) { *pceltFetched = 0; @@ -259,10 +366,10 @@ IFACEMETHODIMP CRenameMRU::Next(__in ULONG celt, __out_ecount_part(celt, *pceltF return S_FALSE; } - hr = S_FALSE; - if (m_mruIndex <= m_mruSize && _EnumMRUList(m_mruIndex++, (void*)mruEntry, ARRAYSIZE(mruEntry)) > 0) + HRESULT hr = S_FALSE; + if (std::wstring data{}; mruList->Next(data)) { - hr = SHStrDup(mruEntry, rgelt); + hr = SHStrDup(data.c_str(), rgelt); if (SUCCEEDED(hr) && pceltFetched != nullptr) { *pceltFetched = 1; @@ -272,137 +379,30 @@ IFACEMETHODIMP CRenameMRU::Next(__in ULONG celt, __out_ecount_part(celt, *pceltF return hr; } +IFACEMETHODIMP CRenameMRU::Reset() +{ + mruList->Reset(); + return S_OK; +} + IFACEMETHODIMP CRenameMRU::AddMRUString(_In_ PCWSTR entry) { - return (_AddMRUString(entry) < 0) ? E_FAIL : S_OK; -} - -HRESULT CRenameMRU::_CreateMRUList(_In_ MRUINFO* pmi) -{ - if (m_mruHandle != NULL) - { - _FreeMRUList(); - } - - if (m_hComctl32Dll == NULL) - { - m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (m_hComctl32Dll != nullptr) - { - CreateMRUListFn pfnCreateMRUList = reinterpret_cast(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(400))); - if (pfnCreateMRUList != nullptr) - { - m_mruHandle = pfnCreateMRUList(pmi); - } - } - - return (m_mruHandle != NULL) ? S_OK : E_FAIL; -} - -int CRenameMRU::_AddMRUString(_In_ PCWSTR data) -{ - int retVal = -1; - if (m_mruHandle != NULL) - { - if (m_hComctl32Dll == NULL) - { - m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (m_hComctl32Dll != nullptr) - { - AddMRUStringFn pfnAddMRUString = reinterpret_cast(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(401))); - if (pfnAddMRUString != nullptr) - { - retVal = pfnAddMRUString(m_mruHandle, data); - } - } - } - - return retVal; -} - -int CRenameMRU::_EnumMRUList(_In_ int nItem, _Out_ void* lpData, _In_ UINT uLen) -{ - int retVal = -1; - if (m_mruHandle != NULL) - { - if (m_hComctl32Dll == NULL) - { - m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (m_hComctl32Dll != nullptr) - { - EnumMRUListFn pfnEnumMRUList = reinterpret_cast(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(403))); - if (pfnEnumMRUList != nullptr) - { - retVal = pfnEnumMRUList(m_mruHandle, nItem, lpData, uLen); - } - } - } - - return retVal; -} - -void CRenameMRU::_FreeMRUList() -{ - if (m_mruHandle != NULL) - { - if (m_hComctl32Dll == NULL) - { - m_hComctl32Dll = LoadLibraryEx(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - } - - if (m_hComctl32Dll != nullptr) - { - FreeMRUListFn pfnFreeMRUList = reinterpret_cast(GetProcAddress(m_hComctl32Dll, (LPCSTR)MAKEINTRESOURCE(152))); - if (pfnFreeMRUList != nullptr) - { - pfnFreeMRUList(m_mruHandle); - } - - } - m_mruHandle = NULL; - } + mruList->Push(entry); + return S_OK; } CSettings::CSettings() { std::wstring result = PTSettingsHelper::get_module_save_folder_location(L"PowerRename"); - jsonFilePath = result + L"\\" + std::wstring(c_powerRenameDataFilePath); + jsonFilePath = result + std::wstring(c_powerRenameDataFilePath); + Load(); } -bool CSettings::GetEnabled() -{ - return GetRegBoolean(c_enabled, true); -} - -void CSettings::SetEnabled(bool enabled) -{ - SetRegBoolean(c_enabled, enabled); -} - -void CSettings::LoadPowerRenameData() -{ - if (!std::filesystem::exists(jsonFilePath)) - { - MigrateSettingsFromRegistry(); - - SavePowerRenameData(); - } - else - { - ParseJsonSettings(); - } -} - -void CSettings::SavePowerRenameData() const +void CSettings::Save() { json::JsonObject jsonData; + jsonData.SetNamedValue(c_enabled, json::value(settings.enabled)); jsonData.SetNamedValue(c_showIconOnMenu, json::value(settings.showIconOnMenu)); jsonData.SetNamedValue(c_extendedContextMenuOnly, json::value(settings.extendedContextMenuOnly)); jsonData.SetNamedValue(c_persistState, json::value(settings.persistState)); @@ -415,19 +415,47 @@ void CSettings::SavePowerRenameData() const json::to_file(jsonFilePath, jsonData); } -void CSettings::MigrateSettingsFromRegistry() +void CSettings::Load() { + if (!std::filesystem::exists(jsonFilePath)) + { + MigrateFromRegistry(); + + Save(); + } + else + { + ParseJson(); + } + GetSystemTimeAsFileTime(&lastLoadedTime); +} + +void CSettings::Reload() +{ + // Load json settings from data file if it is modified in the meantime. + FILETIME lastModifiedTime{}; + if (LastModifiedTime(jsonFilePath, &lastModifiedTime) && + CompareFileTime(&lastModifiedTime, &lastLoadedTime) == 1) + { + Load(); + } +} + + +void CSettings::MigrateFromRegistry() +{ + settings.enabled = GetRegBoolean(c_enabled, true); settings.showIconOnMenu = GetRegBoolean(c_showIconOnMenu, true); settings.extendedContextMenuOnly = GetRegBoolean(c_extendedContextMenuOnly, false); // Disabled by default. settings.persistState = GetRegBoolean(c_persistState, true); settings.MRUEnabled = GetRegBoolean(c_mruEnabled, true); settings.maxMRUSize = GetRegNumber(c_maxMRUSize, 10); settings.flags = GetRegNumber(c_flags, 0); - settings.searchText = GetRegString(c_searchText); - settings.replaceText = GetRegString(c_replaceText); + settings.searchText = GetRegString(c_searchText, L""); + settings.replaceText = GetRegString(c_replaceText, L""); } -void CSettings::ParseJsonSettings() +void CSettings::ParseJson() { auto json = json::from_file(jsonFilePath); if (json) @@ -435,6 +463,10 @@ void CSettings::ParseJsonSettings() const json::JsonObject& jsonSettings = json.value(); try { + if (json::has(jsonSettings, c_enabled, json::JsonValueType::Boolean)) + { + settings.enabled = jsonSettings.GetNamedBoolean(c_enabled); + } if (json::has(jsonSettings, c_showIconOnMenu, json::JsonValueType::Boolean)) { settings.showIconOnMenu = jsonSettings.GetNamedBoolean(c_showIconOnMenu); @@ -480,10 +512,10 @@ CSettings& CSettingsInstance() HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk) { - return CRenameMRU::CreateInstance(c_mruSearchRegPath, CSettingsInstance().GetMaxMRUSize(), ppUnk); + return CRenameMRU::CreateInstance(c_searchMRUListFilePath, c_mruSearchRegPath, ppUnk); } HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk) { - return CRenameMRU::CreateInstance(c_mruReplaceRegPath, CSettingsInstance().GetMaxMRUSize(), ppUnk); + return CRenameMRU::CreateInstance(c_replaceMRUListFilePath, c_mruReplaceRegPath, ppUnk); } diff --git a/src/modules/powerrename/lib/Settings.h b/src/modules/powerrename/lib/Settings.h index b7e5fa83bf..e82c5c0b65 100644 --- a/src/modules/powerrename/lib/Settings.h +++ b/src/modules/powerrename/lib/Settings.h @@ -2,8 +2,6 @@ #include "json.h" -#include - class CSettings { public: @@ -11,9 +9,17 @@ public: CSettings(); - bool GetEnabled(); + inline bool GetEnabled() + { + Reload(); + return settings.enabled; + } - void SetEnabled(bool enabled); + inline void SetEnabled(bool enabled) + { + settings.enabled = enabled; + Save(); + } inline bool GetShowIconOnMenu() const { @@ -73,6 +79,7 @@ public: inline void SetFlags(long flags) { settings.flags = flags; + Save(); } inline const std::wstring& GetSearchText() const @@ -83,6 +90,7 @@ public: inline void SetSearchText(const std::wstring& text) { settings.searchText = text; + Save(); } inline const std::wstring& GetReplaceText() const @@ -93,14 +101,16 @@ public: inline void SetReplaceText(const std::wstring& text) { settings.replaceText = text; + Save(); } - void LoadPowerRenameData(); - void SavePowerRenameData() const; + void Save(); + void Load(); private: struct Settings { + bool enabled{ true }; bool showIconOnMenu{ true }; bool extendedContextMenuOnly{ false }; // Disabled by default. bool persistState{ true }; @@ -111,11 +121,13 @@ private: std::wstring replaceText{}; }; - void MigrateSettingsFromRegistry(); - void ParseJsonSettings(); + void Reload(); + void MigrateFromRegistry(); + void ParseJson(); Settings settings; std::wstring jsonFilePath; + FILETIME lastLoadedTime; }; CSettings& CSettingsInstance(); diff --git a/src/modules/powerrename/ui/PowerRenameUI.cpp b/src/modules/powerrename/ui/PowerRenameUI.cpp index e43cc9f148..c4bd0b5eaa 100644 --- a/src/modules/powerrename/ui/PowerRenameUI.cpp +++ b/src/modules/powerrename/ui/PowerRenameUI.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -80,6 +79,14 @@ inline int RECT_HEIGHT(RECT& r) return r.bottom - r.top; } +CPowerRenameUI::CPowerRenameUI() : + m_refCount(1) +{ + CSettingsInstance().Load(); + (void)OleInitialize(nullptr); + ModuleAddRef(); +} + // IUnknown IFACEMETHODIMP CPowerRenameUI::QueryInterface(__in REFIID riid, __deref_out void** ppv) { diff --git a/src/modules/powerrename/ui/PowerRenameUI.h b/src/modules/powerrename/ui/PowerRenameUI.h index ec9ef7a091..df46fc6a0a 100644 --- a/src/modules/powerrename/ui/PowerRenameUI.h +++ b/src/modules/powerrename/ui/PowerRenameUI.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include void ModuleAddRef(); @@ -37,12 +38,7 @@ class CPowerRenameUI : public IPowerRenameManagerEvents { public: - CPowerRenameUI() : - m_refCount(1) - { - (void)OleInitialize(nullptr); - ModuleAddRef(); - } + CPowerRenameUI(); // IUnknown IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void** ppv);