Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f5ae373a1 | ||
|
|
b978361180 | ||
|
|
93b8055085 | ||
|
|
70ee338fc3 |
No files matched your search
+1
-1
@@ -1,5 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(KSwitcher VERSION 0.6.77 LANGUAGES CXX RC)
|
||||
project(KSwitcher VERSION 0.6.78 LANGUAGES CXX RC)
|
||||
if(NOT WIN32)
|
||||
message(FATAL_ERROR "KSwitcher uses native Windows APIs")
|
||||
endif()
|
||||
|
||||
@@ -65,6 +65,10 @@ Far Manager є зразком для оформлення файлового м
|
||||
|
||||
## Панелі
|
||||
|
||||
- Застосовані налаштування Files одразу підхоплюють інші відкриті вікна.
|
||||
Apply зберігає поля, змінені в поточній чернетці. Якщо два вікна одночасно
|
||||
редагували набір стилів файлів, відкрий Options заново, щоб побачити свіжі правила.
|
||||
|
||||
- Типовий колір тексту для ZIP-архівів — світлий коралово-рожевий.
|
||||
|
||||
- Меню Change drive показує літеру, тип, загальний обсяг і вільне місце. Відкриття меню запускає нове LAN-виявлення. Секція KSwitcher LAN показує збережені пари, зокрема офлайн. Після кожного відкриття меню асинхронно запитує диски й показує їх під назвою відповідного ПК. Поки триває запит, видно стан завантаження. Якщо запит не вдався, видно помилку. Повторне відкриття запускає новий запит. Кожна панель має власний диск і шлях, а в заголовку віддаленої панелі перед шляхом показано назву ПК.
|
||||
|
||||
Binary file not shown.
@@ -1,5 +1,17 @@
|
||||
# Latest Windows release
|
||||
|
||||
## v0.6.78 — 2026-11-14
|
||||
|
||||
The Windows package includes KSwitcher Files, a two-panel file manager with
|
||||
local and paired LAN drives, folder shortcuts, an embedded PowerShell terminal,
|
||||
and searchable command history. Applied Files settings update other open
|
||||
instances immediately.
|
||||
|
||||
**Українською.** До пакета для Windows входить KSwitcher Files, двопанельний
|
||||
файловий менеджер із локальними дисками й дисками спарених ПК, ярликами папок,
|
||||
вбудованим PowerShell та пошуком в історії команд. Застосовані налаштування
|
||||
Files одразу підхоплюють інші відкриті вікна.
|
||||
|
||||
## v0.6.77 — 2026-11-13
|
||||
|
||||
The screenshot editor remembers the local pencil smoothing default across
|
||||
|
||||
@@ -1 +1 @@
|
||||
51d95639527590b36453a5ef485532a7d2135950222fa197eb431a5309f1a45c KSwitcher-win-x64.zip
|
||||
e51829479fa7fa372c0d87a5065716af56d5f0e62b2d9562040f7288e1600ce7 KSwitcher-win-x64.zip
|
||||
+70
-25
@@ -1,86 +1,131 @@
|
||||
{
|
||||
"version": "0.6.77",
|
||||
"schema": 1,
|
||||
"version": "0.6.78",
|
||||
"files": [
|
||||
{
|
||||
"size": 2340864,
|
||||
"path": "KSwitcher.exe",
|
||||
"size": 2249216,
|
||||
"sha256": "f1c79d337d746efcda03946cc833b7b5588ef4e739f1dff7d3afa15d0465469f"
|
||||
"sha256": "1e67e8e15eada80c902764f14a12a0bd370080709a94d454cc3c565dd3de1136"
|
||||
},
|
||||
{
|
||||
"size": 2341376,
|
||||
"path": "KSwitcher.Config.exe",
|
||||
"size": 2251776,
|
||||
"sha256": "016edc389007e0d15ee365fff7115fc91a820b46080cb39a3fb362f3b463bae7"
|
||||
"sha256": "64f83dcc31d785d17832380371379a6f7f30ed52eff79b7fcd29b95b94a7d5b3"
|
||||
},
|
||||
{
|
||||
"size": 3319296,
|
||||
"path": "KSwitcher.Screenshot.exe",
|
||||
"size": 3247616,
|
||||
"sha256": "c8ef070ad01acc410802c62e0df6a96cb299fe036fe8e99f0cf6a398b7324ec6"
|
||||
"sha256": "d9593c6ff103070f1f72b93c0f350ba4782d9df814090565f48bd0aa34125059"
|
||||
},
|
||||
{
|
||||
"size": 1815552,
|
||||
"path": "KSwitcher.Files.exe",
|
||||
"sha256": "22f897cfdc3207350e3edb63f33747d71a0f9d60c7a8d3771f642ee589ed6ce1"
|
||||
},
|
||||
{
|
||||
"size": 194912,
|
||||
"path": "WebView2Loader.dll",
|
||||
"sha256": "d3fce90bdeecb08596e377dea6a316354dd8949e32ff09b89d51be00c14e21b6"
|
||||
},
|
||||
{
|
||||
"size": 1103,
|
||||
"path": "terminal/addon-fit-LICENSE.txt",
|
||||
"sha256": "e256f01188af527e4d06d21d06fbf785ae9c50d4b328bf03cbe0ba7f0aa4228f"
|
||||
},
|
||||
{
|
||||
"size": 1521,
|
||||
"path": "terminal/addon-fit.js",
|
||||
"sha256": "ba3ea256ce0620a0992a197d6c9baea64823fc93d8da07a9e366ca9943c18527"
|
||||
},
|
||||
{
|
||||
"size": 527,
|
||||
"path": "terminal/index.html",
|
||||
"sha256": "084d97a727b778fb10d31adcd557ee7840a38377ed60e0ef0f3ece93b349b1ef"
|
||||
},
|
||||
{
|
||||
"size": 3174,
|
||||
"path": "terminal/terminal.js",
|
||||
"sha256": "142624d166314c4539dd14f922c17dca3d2bc7203f84aff2df03a196602c4b09"
|
||||
},
|
||||
{
|
||||
"size": 1261,
|
||||
"path": "terminal/xterm-LICENSE.txt",
|
||||
"sha256": "b569f629d00f2626a8100df2a1798210535621e42164dfd426a6fe5aac7b0ccd"
|
||||
},
|
||||
{
|
||||
"size": 7112,
|
||||
"path": "terminal/xterm.css",
|
||||
"sha256": "854a7c0fb70e8b1a083c16797ab827299fb18744f5ad34f227b48337e33293c6"
|
||||
},
|
||||
{
|
||||
"size": 488663,
|
||||
"path": "terminal/xterm.js",
|
||||
"sha256": "14903579ff54664cd72f8e8699e6961a6272c21863ec1c3b118cdc8af5d4a972"
|
||||
},
|
||||
{
|
||||
"path": "LICENSE",
|
||||
"size": 4401,
|
||||
"path": "LICENSE",
|
||||
"sha256": "d3c81140cce01c26bf6cbf52aa40e0825e1fa35b9a91d1387170a65d2597082c"
|
||||
},
|
||||
{
|
||||
"path": "json-LICENSE.txt",
|
||||
"size": 1075,
|
||||
"path": "json-LICENSE.txt",
|
||||
"sha256": "c0d068392ea65358b798b8c165103560f06e9e3b38c4ab4e2d8810a7b931af86"
|
||||
},
|
||||
{
|
||||
"path": "README.md",
|
||||
"size": 93885,
|
||||
"path": "README.md",
|
||||
"sha256": "df6d40d0eb66ad7da8db1cffe6bd211de70dfee474cc228e041c821b3940718b"
|
||||
},
|
||||
{
|
||||
"path": "LAN-PREVIEW.md",
|
||||
"size": 11418,
|
||||
"path": "LAN-PREVIEW.md",
|
||||
"sha256": "2c13d3ed4761e679c352fb1ade24a1ec3060ad2862376ede801cdee5fcc3bada"
|
||||
},
|
||||
{
|
||||
"path": "dictionaries/en.txt",
|
||||
"size": 682867,
|
||||
"path": "dictionaries/en.txt",
|
||||
"sha256": "5f267c141c3d6837870e1c098f86b89a113ba300343119432644ead88f720c21"
|
||||
},
|
||||
{
|
||||
"path": "dictionaries/LICENSE-CC-BY-SA-4.0.txt",
|
||||
"size": 20138,
|
||||
"path": "dictionaries/LICENSE-CC-BY-SA-4.0.txt",
|
||||
"sha256": "28a9529c7d0bb4dc51f4bf5c116a3d16ef247a052f7591466768ddf563fd1cf5"
|
||||
},
|
||||
{
|
||||
"size": 2265,
|
||||
"path": "dictionaries/README.md",
|
||||
"size": 2230,
|
||||
"sha256": "2df17fe4e17d527c67ab57269b07dce59a49c1fb128c429a1408decbb47109ec"
|
||||
"sha256": "3017bf44d3be9d9dfab21bd6778aa52b7947e61acf9ce2bc86b41d6e949ac311"
|
||||
},
|
||||
{
|
||||
"path": "dictionaries/ru.txt",
|
||||
"size": 1060364,
|
||||
"path": "dictionaries/ru.txt",
|
||||
"sha256": "9ef922c7699569304a428f6aba0fd13a21341c0d0cb9561f37ef83c41577a28b"
|
||||
},
|
||||
{
|
||||
"size": 1280,
|
||||
"path": "dictionaries/sources.json",
|
||||
"size": 1279,
|
||||
"sha256": "d6e11a3aaba22a8a7eaba19f778d8a5bd66653ff306810e85a1b0e7fff3a6b86"
|
||||
"sha256": "98e5b3fe7304e37705c9e5ff48b0b399ccb16e806736d21f09921b99e5f2a408"
|
||||
},
|
||||
{
|
||||
"size": 940799,
|
||||
"path": "dictionaries/uk.txt",
|
||||
"size": 898248,
|
||||
"sha256": "caeb097749d4afc84b68ad96b3d7dfb6a6569561cd32ccce0bee94a13b43ba86"
|
||||
"sha256": "d30e990d6ec2983c04f3644a3c61c6c668e8c542323f5931916fdd55b916eebf"
|
||||
},
|
||||
{
|
||||
"path": "tools/README.txt",
|
||||
"size": 993,
|
||||
"path": "tools/README.txt",
|
||||
"sha256": "a34b5161a8315af037e1ec71d816bfc688f7c364141d4ee2347cf0515ef0c82a"
|
||||
},
|
||||
{
|
||||
"path": "tools/StayHere.exe",
|
||||
"size": 134656,
|
||||
"path": "tools/StayHere.exe",
|
||||
"sha256": "6ef5cf64708d62b7fc63c3c793cc99188a513433ff4774cae01dc014f6664376"
|
||||
},
|
||||
{
|
||||
"path": "tools/StayHere-README.md",
|
||||
"size": 2796,
|
||||
"path": "tools/StayHere-README.md",
|
||||
"sha256": "ba214e2aca7405e698b3ab21ceb1f41ce088edd996b3e30e4a9d58ff496f9413"
|
||||
}
|
||||
],
|
||||
"schema": 1
|
||||
]
|
||||
}
|
||||
+3
-3
@@ -9,8 +9,8 @@ IDC_SCREENSHOT_PENCIL CURSOR "icons/lucide/pencil.cur"
|
||||
1 RT_MANIFEST "app.manifest"
|
||||
201 RCDATA "update.ps1"
|
||||
1 VERSIONINFO
|
||||
FILEVERSION 0,6,77,0
|
||||
PRODUCTVERSION 0,6,77,0
|
||||
FILEVERSION 0,6,78,0
|
||||
PRODUCTVERSION 0,6,78,0
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_APP
|
||||
BEGIN
|
||||
@@ -20,7 +20,7 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "FileDescription", "KSwitcher — native keyboard and clipboard utility"
|
||||
VALUE "ProductName", "KSwitcher"
|
||||
VALUE "FileVersion", "0.6.77"
|
||||
VALUE "FileVersion", "0.6.78"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -29,11 +29,15 @@ void setOptionHistoryKeys(HWND dialog,const std::array<WORD,2> &keys)
|
||||
SendDlgItemMessageW(dialog,323,HKM_SETHOTKEY,keys[1],0);
|
||||
}
|
||||
|
||||
void loadCommandHistory()
|
||||
void loadCommandHistoryKeys()
|
||||
{
|
||||
const std::array<WORD,2> keys{static_cast<WORD>(preference(L"PreviousCommandKey",defaultHistoryKeys[0])),
|
||||
static_cast<WORD>(preference(L"CommandHistoryKey",defaultHistoryKeys[1]))};
|
||||
if(validHistoryKeys(keys)) commandHistoryKeys=keys;
|
||||
commandHistoryKeys=validHistoryKeys(keys)?keys:defaultHistoryKeys;
|
||||
}
|
||||
|
||||
void loadCommandHistory()
|
||||
{
|
||||
|
||||
DWORD bytes{};
|
||||
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"CommandHistory",RRF_RT_REG_BINARY,nullptr,nullptr,&bytes)
|
||||
|
||||
@@ -139,6 +139,7 @@ INT_PTR CALLBACK folderShortcutEditDialog(HWND dialog,UINT message,WPARAM wp,LPA
|
||||
return TRUE;
|
||||
}
|
||||
folderShortcuts=std::move(updated);
|
||||
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
|
||||
finishFilesDialog(dialog,IDOK);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -362,6 +363,7 @@ INT_PTR CALLBACK quickFolderDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
|
||||
else
|
||||
{
|
||||
folderShortcuts=std::move(updated);
|
||||
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
|
||||
layoutQuickFolders(dialog,*view,static_cast<int>(target));
|
||||
}
|
||||
return TRUE;
|
||||
@@ -383,6 +385,7 @@ INT_PTR CALLBACK quickFolderDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
|
||||
return TRUE;
|
||||
}
|
||||
folderShortcuts=std::move(updated);
|
||||
notifyFilesPreferences(GetAncestor(dialog,GA_ROOTOWNER));
|
||||
if(folderShortcuts[view->digit].empty()) finishFilesDialog(dialog,IDCANCEL);
|
||||
else layoutQuickFolders(dialog,*view,static_cast<int>(row));
|
||||
return TRUE;
|
||||
|
||||
+50
-23
@@ -364,6 +364,13 @@ DWORD preference(const wchar_t *name, DWORD fallback)
|
||||
== ERROR_SUCCESS ? value : fallback;
|
||||
}
|
||||
|
||||
const UINT filesPreferencesChanged=RegisterWindowMessageW(L"KSwitcher.Files.PreferencesChanged");
|
||||
|
||||
void notifyFilesPreferences(HWND source)
|
||||
{
|
||||
SendNotifyMessageW(HWND_BROADCAST,filesPreferencesChanged,reinterpret_cast<WPARAM>(source),0);
|
||||
}
|
||||
|
||||
void savePreference(const wchar_t *name, DWORD value)
|
||||
{
|
||||
RegSetKeyValueW(HKEY_CURRENT_USER,schemeKey,name,REG_DWORD,&value,sizeof(value));
|
||||
@@ -393,6 +400,7 @@ void setMode(int index, bool wide)
|
||||
{
|
||||
panels[index].wide=wide;
|
||||
savePreference(index ? L"RightWide" : L"LeftWide",wide);
|
||||
notifyFilesPreferences(GetParent(panels[index].list));
|
||||
layout(GetParent(panels[index].list));
|
||||
InvalidateRect(panels[index].list,nullptr,TRUE);
|
||||
showFileDetails(panels[active]);
|
||||
@@ -3144,6 +3152,35 @@ LRESULT CALLBACK panelKeys(HWND window, UINT message, WPARAM wp, LPARAM lp, UINT
|
||||
|
||||
#include "files_folder_shortcuts.inl"
|
||||
#include "files_command_history_dialog.inl"
|
||||
bool loadFilesPreferences(HWND window)
|
||||
{
|
||||
LOGFONTW font{};
|
||||
DWORD bytes=sizeof(font);
|
||||
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",RRF_RT_REG_BINARY,nullptr,&font,&bytes)
|
||||
!=ERROR_SUCCESS || bytes!=sizeof(font))
|
||||
{
|
||||
font=defaultFilesFont();
|
||||
}
|
||||
font.lfFaceName[LF_FACESIZE-1]=0;
|
||||
if(!applyFont(window,font,static_cast<int>(std::clamp(preference(L"FontPoints",defaultFontPoints),80UL,240UL)))) return false;
|
||||
loadColors();
|
||||
dialogFramePadding={
|
||||
std::min(preference(dialogFrameOuterKey,defaultDialogFramePadding.outer),maxDialogFramePadding),
|
||||
std::min(preference(dialogFrameInnerKey,defaultDialogFramePadding.inner),maxDialogFramePadding),
|
||||
std::min(preference(dialogRowTextKey,defaultDialogFramePadding.rowText),maxDialogRowTextPadding)};
|
||||
loadFileStyles();
|
||||
loadFolderShortcuts();
|
||||
panels[0].wide=preference(L"LeftWide",defaultWide)!=0;
|
||||
panels[1].wide=preference(L"RightWide",defaultWide)!=0;
|
||||
sizeWidth=static_cast<int>(std::clamp(preference(L"SizeWidth",defaultSizeWidth),6UL,16UL));
|
||||
alignExtensions=preference(L"AlignExtensions",defaultAlignExtensions)!=0;
|
||||
showDetails=preference(L"ShowDetails",defaultShowDetails)!=0;
|
||||
alignFolders=preference(L"AlignFolders",defaultAlignFolders)!=0;
|
||||
statusFields=preference(L"StatusFields",defaultStatusFields)&15;
|
||||
loadCommandHistoryKeys();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "files_options.inl"
|
||||
|
||||
void openMenu(HWND window, int index)
|
||||
@@ -3261,6 +3298,18 @@ bool handleFilesMenuKey(HWND window,UINT message,WPARAM key,LPARAM flags,bool mo
|
||||
|
||||
LRESULT CALLBACK filesWindow(HWND window, UINT message, WPARAM wp, LPARAM lp)
|
||||
{
|
||||
if(message==filesPreferencesChanged)
|
||||
{
|
||||
if(reinterpret_cast<HWND>(wp)!=window)
|
||||
{
|
||||
loadFilesPreferences(window);
|
||||
layout(window);
|
||||
layoutOpenCommandHistory();
|
||||
showFileDetails(panels[active]);
|
||||
RedrawWindow(window,nullptr,nullptr,RDW_INVALIDATE|RDW_ALLCHILDREN);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch (message)
|
||||
{
|
||||
case WM_ACTIVATEAPP:
|
||||
@@ -3297,29 +3346,7 @@ LRESULT CALLBACK filesWindow(HWND window, UINT message, WPARAM wp, LPARAM lp)
|
||||
case WM_CREATE:
|
||||
{
|
||||
auto instance = GetModuleHandleW(nullptr);
|
||||
LOGFONTW font{};
|
||||
DWORD bytes=sizeof(font);
|
||||
if(RegGetValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",RRF_RT_REG_BINARY,nullptr,&font,&bytes)
|
||||
!=ERROR_SUCCESS || bytes!=sizeof(font))
|
||||
{
|
||||
font=defaultFilesFont();
|
||||
}
|
||||
font.lfFaceName[LF_FACESIZE-1]=0;
|
||||
if(!applyFont(window,font,static_cast<int>(std::clamp(preference(L"FontPoints",defaultFontPoints),80UL,240UL)))) return -1;
|
||||
loadColors();
|
||||
dialogFramePadding={
|
||||
std::min(preference(dialogFrameOuterKey,defaultDialogFramePadding.outer),maxDialogFramePadding),
|
||||
std::min(preference(dialogFrameInnerKey,defaultDialogFramePadding.inner),maxDialogFramePadding),
|
||||
std::min(preference(dialogRowTextKey,defaultDialogFramePadding.rowText),maxDialogRowTextPadding)};
|
||||
loadFileStyles();
|
||||
loadFolderShortcuts();
|
||||
panels[0].wide=preference(L"LeftWide",defaultWide)!=0;
|
||||
panels[1].wide=preference(L"RightWide",defaultWide)!=0;
|
||||
sizeWidth=static_cast<int>(std::clamp(preference(L"SizeWidth",defaultSizeWidth),6UL,16UL));
|
||||
alignExtensions=preference(L"AlignExtensions",defaultAlignExtensions)!=0;
|
||||
showDetails=preference(L"ShowDetails",defaultShowDetails)!=0;
|
||||
alignFolders=preference(L"AlignFolders",defaultAlignFolders)!=0;
|
||||
statusFields=preference(L"StatusFields",defaultStatusFields)&15;
|
||||
if(!loadFilesPreferences(window)) return -1;
|
||||
menuBar=CreateWindowW(L"BUTTON",L"",WS_CHILD|WS_CLIPSIBLINGS|BS_OWNERDRAW,
|
||||
0,0,0,0,window,reinterpret_cast<HMENU>(120),instance,nullptr);
|
||||
const wchar_t *menus[]{L"Left",L"Files",L"Commands",L"Options",L"Right"};
|
||||
|
||||
+100
-45
@@ -52,8 +52,22 @@ void resetPanelProperty(HWND dialog,const PanelProperty &property)
|
||||
else CheckDlgButton(dialog,property.control,property.defaultValue);
|
||||
}
|
||||
|
||||
struct OptionsBaseline
|
||||
{
|
||||
LOGFONTW font=displayFont;
|
||||
int points=fontPoints;
|
||||
DialogFramePadding padding=dialogFramePadding;
|
||||
std::array<COLORREF,ColorCount> palette=colors;
|
||||
std::vector<FileStyle> styles=fileStyles;
|
||||
std::array<WORD,2> keys=commandHistoryKeys;
|
||||
DWORD width=static_cast<DWORD>(sizeWidth), fields=statusFields;
|
||||
bool extensions=alignExtensions, folders=alignFolders, details=showDetails;
|
||||
std::array<bool,2> wide{panels[0].wide,panels[1].wide};
|
||||
};
|
||||
|
||||
struct OptionsDraft
|
||||
{
|
||||
OptionsBaseline baseline;
|
||||
LOGFONTW font=displayFont;
|
||||
int points=fontPoints;
|
||||
DialogFramePadding framePadding=dialogFramePadding;
|
||||
@@ -81,15 +95,28 @@ struct OptionsDraft
|
||||
|
||||
bool optionsFontChanged(const OptionsDraft &draft)
|
||||
{
|
||||
auto pending=draft.font, applied=displayFont;
|
||||
auto pending=draft.font, applied=draft.baseline.font;
|
||||
// Height follows the selected point size and DPI. applyFont always uses natural width.
|
||||
pending.lfHeight=applied.lfHeight=0;
|
||||
pending.lfWidth=applied.lfWidth=0;
|
||||
return draft.points!=fontPoints ||
|
||||
return draft.points!=draft.baseline.points ||
|
||||
memcmp(&pending,&applied,offsetof(LOGFONTW,lfFaceName))!=0 ||
|
||||
_wcsicmp(pending.lfFaceName,applied.lfFaceName)!=0;
|
||||
}
|
||||
|
||||
struct OptionsWriteLock
|
||||
{
|
||||
HANDLE mutex=CreateMutexW(nullptr,FALSE,L"Local\\KSwitcher.Files.OptionsWrite");
|
||||
DWORD result=mutex?WaitForSingleObject(mutex,2000):WAIT_FAILED;
|
||||
|
||||
bool acquired() const { return result==WAIT_OBJECT_0 || result==WAIT_ABANDONED; }
|
||||
~OptionsWriteLock()
|
||||
{
|
||||
if(acquired()) ReleaseMutex(mutex);
|
||||
if(mutex) CloseHandle(mutex);
|
||||
}
|
||||
};
|
||||
|
||||
void updateOptionsApply(HWND dialog,const OptionsDraft &draft)
|
||||
{
|
||||
BOOL valid{};
|
||||
@@ -97,12 +124,13 @@ void updateOptionsApply(HWND dialog,const OptionsDraft &draft)
|
||||
const auto checked=[&](int id){return IsDlgButtonChecked(dialog,id)==BST_CHECKED;};
|
||||
DWORD fields=0;
|
||||
for(int i=0;i<4;++i) if(checked(205+i)) fields|=1u<<i;
|
||||
const bool dirty=!valid || width!=static_cast<UINT>(sizeWidth) ||
|
||||
checked(273)!=panels[0].wide || checked(274)!=panels[1].wide ||
|
||||
checked(202)!=alignExtensions || checked(204)!=alignFolders || checked(203)!=showDetails ||
|
||||
fields!=statusFields || draft.palette!=colors || draft.styles!=fileStyles ||
|
||||
draft.framePadding!=dialogFramePadding || optionsFontChanged(draft) ||
|
||||
optionHistoryKeys(dialog)!=commandHistoryKeys;
|
||||
const auto &base=draft.baseline;
|
||||
const bool dirty=!valid || width!=base.width ||
|
||||
checked(273)!=base.wide[0] || checked(274)!=base.wide[1] ||
|
||||
checked(202)!=base.extensions || checked(204)!=base.folders || checked(203)!=base.details ||
|
||||
fields!=base.fields || draft.palette!=base.palette || draft.styles!=base.styles ||
|
||||
draft.framePadding!=base.padding || optionsFontChanged(draft) ||
|
||||
optionHistoryKeys(dialog)!=base.keys;
|
||||
EnableWindow(GetDlgItem(dialog,optionsApply),dirty);
|
||||
InvalidateRect(GetDlgItem(dialog,fileStylePreview),nullptr,FALSE);
|
||||
}
|
||||
@@ -521,14 +549,31 @@ INT_PTR CALLBACK optionsDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
|
||||
SendDlgItemMessageW(dialog,201,EM_SETSEL,0,-1);
|
||||
return TRUE;
|
||||
}
|
||||
const auto keys=optionHistoryKeys(dialog);
|
||||
const auto owner=GetWindow(dialog,GW_OWNER);
|
||||
const OptionsWriteLock writeLock;
|
||||
if(!writeLock.acquired())
|
||||
{
|
||||
setStatus(L"Another window is saving Files settings. Try Apply again.");
|
||||
return TRUE;
|
||||
}
|
||||
const auto &base=draft->baseline;
|
||||
auto keys=optionHistoryKeys(dialog);
|
||||
loadCommandHistoryKeys();
|
||||
for(size_t i=0;i<keys.size();++i)
|
||||
if(keys[i]==base.keys[i]) keys[i]=commandHistoryKeys[i];
|
||||
if(!validHistoryKeys(keys))
|
||||
{
|
||||
MessageBoxW(dialog,L"Choose distinct shortcuts using Ctrl or Alt that are free in Files.",L"Command history",MB_OK|MB_ICONWARNING);
|
||||
return TRUE;
|
||||
}
|
||||
const auto owner=GetWindow(dialog,GW_OWNER);
|
||||
const bool stylesChanged=draft->styles!=fileStyles;
|
||||
const bool stylesChanged=draft->styles!=base.styles;
|
||||
loadFileStyles();
|
||||
if(stylesChanged && fileStyles!=base.styles && fileStyles!=draft->styles)
|
||||
{
|
||||
MessageBoxW(dialog,L"File type styles changed in another window. Reopen Options before editing them again.",
|
||||
L"KSwitcher Files Options",MB_OK|MB_ICONWARNING);
|
||||
return TRUE;
|
||||
}
|
||||
if(stylesChanged && !saveFileStyles(draft->styles))
|
||||
{
|
||||
MessageBoxW(dialog,L"Could not save the file type styles.",L"KSwitcher Files Options",MB_OK|MB_ICONWARNING);
|
||||
@@ -541,47 +586,57 @@ INT_PTR CALLBACK optionsDialog(HWND dialog,UINT message,WPARAM wp,LPARAM lp)
|
||||
MessageBoxW(dialog,L"Could not apply the selected font.",optionsTitles[Appearance],MB_OK|MB_ICONWARNING);
|
||||
return TRUE;
|
||||
}
|
||||
commandHistoryKeys=keys;
|
||||
savePreference(L"PreviousCommandKey",keys[0]);
|
||||
savePreference(L"CommandHistoryKey",keys[1]);
|
||||
if(stylesChanged) fileStyles=draft->styles;
|
||||
sizeWidth=static_cast<int>(width);
|
||||
alignExtensions=IsDlgButtonChecked(dialog,202)==BST_CHECKED;
|
||||
showDetails=IsDlgButtonChecked(dialog,203)==BST_CHECKED;
|
||||
alignFolders=IsDlgButtonChecked(dialog,204)==BST_CHECKED;
|
||||
statusFields=0;
|
||||
for(int i=0;i<4;++i)
|
||||
if(IsDlgButtonChecked(dialog,205+i)==BST_CHECKED) statusFields|=1u<<i;
|
||||
savePreference(L"SizeWidth",sizeWidth);
|
||||
savePreference(L"AlignExtensions",alignExtensions);
|
||||
savePreference(L"ShowDetails",showDetails);
|
||||
savePreference(L"AlignFolders",alignFolders);
|
||||
savePreference(L"StatusFields",statusFields);
|
||||
for(int i=0;i<ColorCount;++i)
|
||||
if(colors[i]!=draft->palette[i])
|
||||
{
|
||||
colors[i]=draft->palette[i];
|
||||
savePreference(std::to_wstring(i).c_str(),colors[i]);
|
||||
}
|
||||
refreshColors();
|
||||
if(draft->framePadding!=dialogFramePadding)
|
||||
const auto saveChanged=[](const wchar_t *name,DWORD value,DWORD initial)
|
||||
{
|
||||
dialogFramePadding=draft->framePadding;
|
||||
savePreference(dialogFrameOuterKey,dialogFramePadding.outer);
|
||||
savePreference(dialogFrameInnerKey,dialogFramePadding.inner);
|
||||
savePreference(dialogRowTextKey,dialogFramePadding.rowText);
|
||||
if(value!=initial) savePreference(name,value);
|
||||
};
|
||||
const auto checked=[&](int id){return IsDlgButtonChecked(dialog,id)==BST_CHECKED;};
|
||||
const auto inputKeys=optionHistoryKeys(dialog);
|
||||
saveChanged(L"PreviousCommandKey",inputKeys[0],base.keys[0]);
|
||||
saveChanged(L"CommandHistoryKey",inputKeys[1],base.keys[1]);
|
||||
saveChanged(L"SizeWidth",width,base.width);
|
||||
saveChanged(L"AlignExtensions",checked(202),base.extensions);
|
||||
saveChanged(L"AlignFolders",checked(204),base.folders);
|
||||
saveChanged(L"ShowDetails",checked(203),base.details);
|
||||
DWORD fields=preference(L"StatusFields",defaultStatusFields)&15;
|
||||
const auto initialFields=fields;
|
||||
for(int i=0;i<4;++i)
|
||||
{
|
||||
const DWORD bit=1u<<i;
|
||||
if(checked(205+i)!=((base.fields&bit)!=0)) fields=checked(205+i)?fields|bit:fields&~bit;
|
||||
}
|
||||
saveChanged(L"StatusFields",fields,initialFields);
|
||||
for(int i=0;i<ColorCount;++i)
|
||||
saveChanged(std::to_wstring(i).c_str(),draft->palette[i],base.palette[i]);
|
||||
saveChanged(dialogFrameOuterKey,draft->framePadding.outer,base.padding.outer);
|
||||
saveChanged(dialogFrameInnerKey,draft->framePadding.inner,base.padding.inner);
|
||||
saveChanged(dialogRowTextKey,draft->framePadding.rowText,base.padding.rowText);
|
||||
if(fontChanged)
|
||||
{
|
||||
savePreference(L"FontPoints",fontPoints);
|
||||
RegSetKeyValueW(HKEY_CURRENT_USER,schemeKey,L"DisplayFont",REG_BINARY,&displayFont,sizeof(displayFont));
|
||||
draft->font=displayFont;
|
||||
}
|
||||
for(int i=0;i<2;++i)
|
||||
{
|
||||
const bool wide=IsDlgButtonChecked(dialog,273+i)==BST_CHECKED;
|
||||
if(panels[i].wide!=wide) setMode(i,wide);
|
||||
}
|
||||
saveChanged(L"LeftWide",checked(273),base.wide[0]);
|
||||
saveChanged(L"RightWide",checked(274),base.wide[1]);
|
||||
loadFilesPreferences(owner);
|
||||
notifyFilesPreferences(owner);
|
||||
draft->baseline=OptionsBaseline{};
|
||||
draft->font=displayFont;
|
||||
draft->points=fontPoints;
|
||||
draft->styles=fileStyles;
|
||||
draft->palette=colors;
|
||||
draft->framePadding=dialogFramePadding;
|
||||
SetDlgItemInt(dialog,201,sizeWidth,FALSE);
|
||||
CheckDlgButton(dialog,202,alignExtensions);
|
||||
CheckDlgButton(dialog,203,showDetails);
|
||||
CheckDlgButton(dialog,204,alignFolders);
|
||||
CheckDlgButton(dialog,273,panels[0].wide);
|
||||
CheckDlgButton(dialog,274,panels[1].wide);
|
||||
for(int i=0;i<4;++i) CheckDlgButton(dialog,205+i,(statusFields>>i)&1u);
|
||||
setOptionHistoryKeys(dialog,commandHistoryKeys);
|
||||
if(draft->page==PanelColors && draft->section==fileStyleSection)
|
||||
updateFileStyleEditor(dialog,*draft,true);
|
||||
showOptionsPage(dialog,*draft,draft->page,draft->section);
|
||||
layout(owner);
|
||||
showFileDetails(panels[active]);
|
||||
RedrawWindow(owner,nullptr,nullptr,RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN|RDW_UPDATENOW);
|
||||
|
||||
+3
-1
@@ -1514,7 +1514,9 @@ Settings collectSettings(HWND w, SettingsView *v)
|
||||
s.undo = value(w, 213);
|
||||
s.clipboard = value(w, 214);
|
||||
s.screenshot = value(w, 215);
|
||||
s.filesHotkey = value(w, 216);
|
||||
auto filesHotkey = value(w, 216);
|
||||
if (s.filesHotkey || !filesHotkey.empty())
|
||||
s.filesHotkey = std::move(filesHotkey);
|
||||
s.maxItems = integer(w, 240);
|
||||
s.maxMiB = integer(w, 241);
|
||||
s.maxImageMiB = integer(w, 242);
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#include "platform.h"
|
||||
namespace ks
|
||||
{
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.77";
|
||||
inline constexpr wchar_t AppVersion[] = L"0.6.78";
|
||||
inline constexpr UINT UpdateMessage = WM_APP + 7;
|
||||
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
|
||||
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;
|
||||
|
||||
Reference in new issue
Block a user