From 26f471496af2a42967ed322e9b52a93fba553e14 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 15 Sep 2019 18:36:20 +0300 Subject: PluginUpdater: - fixes #2057 (PluginUpdater: add search box); - missing components dialog moved to UI classes; - version bump --- plugins/PluginUpdater/src/DlgListNew.cpp | 479 ++++++++++++++++--------------- 1 file changed, 241 insertions(+), 238 deletions(-) (limited to 'plugins/PluginUpdater/src/DlgListNew.cpp') diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp index 0088c4e983..fc256092df 100644 --- a/plugins/PluginUpdater/src/DlgListNew.cpp +++ b/plugins/PluginUpdater/src/DlgListNew.cpp @@ -22,79 +22,10 @@ Boston, MA 02111-1307, USA. static HWND hwndDialog; static HANDLE hListThread; -static void SelectAll(HWND hDlg, bool bEnable) -{ - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - for (int i = 0; i < todo.getCount(); i++) - ListView_SetCheckState(hwndList, i, todo[i].bEnabled = bEnable); -} - -static void ApplyDownloads(void *param) -{ - Thread_SetName("PluginUpdater: ApplyDownloads"); - - HWND hDlg = (HWND)param; - - //////////////////////////////////////////////////////////////////////////////////////// - // if we need to escalate priviledges, launch a atub - - if (!PrepareEscalation()) { - PostMessage(hDlg, WM_CLOSE, 0, 0); - return; - } - - //////////////////////////////////////////////////////////////////////////////////////// - // ok, let's unpack all zips - - AutoHandle pipe(hPipe); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - //create needed folders after escalating priviledges. Folders creates when we actually install updates - wchar_t tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_snwprintf(tszFileBack, L"%s\\Backups", g_tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_snwprintf(tszFileTemp, L"%s\\Temp", g_tszRoot); - SafeCreateDirectory(tszFileTemp); - - VARSW tszMirandaPath(L"%miranda_path%"); - - HNETLIBCONN nlc = nullptr; - for (int i = 0; i < todo.getCount(); ++i) { - auto &p = todo[i]; - ListView_EnsureVisible(hwndList, i, FALSE); - if (p.bEnabled) { - // download update - ListView_SetItemText(hwndList, i, 1, TranslateT("Downloading...")); - - if (DownloadFile(&p.File, nlc)) { - ListView_SetItemText(hwndList, i, 1, TranslateT("Succeeded.")); - if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, false)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - db_unset(0, DB_MODULE_NEW_FILES, _T2A(p.tszOldName)); - } - else ListView_SetItemText(hwndList, i, 1, TranslateT("Failed!")); - } - else ListView_SetItemText(hwndList, i, 1, TranslateT("Skipped.")); - } - Netlib_CloseHandle(nlc); - - ShowPopup(TranslateT("Plugin Updater"), TranslateT("Download complete"), POPUP_TYPE_INFO); - - int rc = MessageBox(hDlg, TranslateT("Download complete. Do you want to go to plugins option page?"), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION); - if (rc == IDYES) - CallFunctionAsync(OpenPluginOptions, nullptr); - - PostMessage(hDlg, WM_CLOSE, 0, 0); -} +static void ApplyDownloads(void *param); ///////////////////////////////////////////////////////////////////////////////////////// -static WNDPROC oldWndProc = nullptr; - static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (msg == WM_LBUTTONDOWN) { @@ -120,20 +51,7 @@ static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LP } } - return CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); -} - -static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc) -{ - switch (urc->wId) { - case IDC_SELNONE: - case IDOK: - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - - case IDC_UPDATETEXT: - return RD_ANCHORX_CENTRE; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam); } int ImageList_AddIconFromIconLib(HIMAGELIST hIml, int i) @@ -144,196 +62,281 @@ int ImageList_AddIconFromIconLib(HIMAGELIST hIml, int i) return res; } -INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +class CMissingPLuginsDlg : public CDlgBase { - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - switch (message) { - case WM_INITDIALOG: - TranslateDialogDefault(hDlg); - oldWndProc = (WNDPROC)SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)PluginListWndProc); - - Window_SetIcon_IcoLib(hDlg, iconList[2].hIcolib); - { - HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); - ImageList_AddIconFromIconLib(hIml, 1); - ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); - - if (IsWinVer7Plus()) { - wchar_t szPath[MAX_PATH]; - GetModuleFileNameW(nullptr, szPath, _countof(szPath)); - wchar_t *ext = wcsrchr(szPath, '.'); - if (ext != nullptr) - *ext = '\0'; - wcscat(szPath, L".test"); - HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (hFile == INVALID_HANDLE_VALUE) - Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); - else { - CloseHandle(hFile); - DeleteFile(szPath); - } + OBJLIST *todo; + CCtrlEdit m_filter; + CCtrlListView m_list; + CCtrlButton btnOk, btnNone; + + void FillList(const wchar_t *pwszFilter) + { + m_list.DeleteAllItems(); + + LVITEM lvi = { 0 }; + lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; + + bool enableOk = false; + for (auto &p : *todo) { + if (pwszFilter) { + wchar_t pathLwr[MAX_PATH]; + wcsncpy_s(pathLwr, p->tszNewName, _TRUNCATE); + wcslwr(pathLwr); + if (!wcsstr(pathLwr, pwszFilter)) + continue; } - ////////////////////////////////////////////////////////////////////////////////////// - LVCOLUMN lvc = { 0 }; - lvc.mask = LVCF_WIDTH | LVCF_TEXT; + int groupId = 4; + if (wcschr(p->tszOldName, L'\\') != nullptr) + groupId = (wcsstr(p->tszOldName, L"Plugins") != nullptr) ? 1 : ((wcsstr(p->tszOldName, L"Languages") != nullptr) ? 3 : 2); + + lvi.iItem = todo->indexOf(&p); + lvi.lParam = (LPARAM)p; + lvi.iGroupId = groupId; + lvi.iImage = ((groupId == 1) ? 0 : -1); + lvi.pszText = p->tszOldName; + m_list.InsertItem(&lvi); - lvc.pszText = TranslateT("Component Name"); - lvc.cx = 220; // width of column in pixels - ListView_InsertColumn(hwndList, 0, &lvc); + if (p->bEnabled) { + enableOk = true; + m_list.SetCheckState(lvi.iItem, 1); + } + } - lvc.pszText = TranslateT("State"); - lvc.cx = 100; // width of column in pixels - ListView_InsertColumn(hwndList, 1, &lvc); + btnOk.Enable(enableOk); + } - ////////////////////////////////////////////////////////////////////////////////////// - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID; + void SelectAll(bool bEnable) + { + for (int i = 0; i < todo->getCount(); i++) + m_list.SetCheckState(i, (*todo)[i].bEnabled = bEnable); + } - lvg.pszHeader = TranslateT("Plugins"); - lvg.iGroupId = 1; - ListView_InsertGroup(hwndList, 0, &lvg); +public: + CMissingPLuginsDlg(OBJLIST *param) : + CDlgBase(g_plugin, IDD_MISSINGPLUGINS), + todo(param), + btnOk(this, IDOK), + btnNone(this, IDC_SELNONE), + m_list(this, IDC_LIST_UPDATES), + m_filter(this, IDC_SEARCH) + { + m_autoClose = CLOSE_ON_CANCEL; + SetParent(GetDesktopWindow()); + SetMinSize(370, 300); + + btnOk.OnClick = Callback(this, &CMissingPLuginsDlg::onClick_Ok); + btnNone.OnClick = Callback(this, &CMissingPLuginsDlg::onClick_None); + + m_filter.OnChange = Callback(this, &CMissingPLuginsDlg::onChange_Filter); + m_list.OnItemChanged = Callback(this, &CMissingPLuginsDlg::onItemChanged); + } - lvg.pszHeader = TranslateT("Icons"); - lvg.iGroupId = 2; - ListView_InsertGroup(hwndList, 0, &lvg); + bool OnInitDialog() override + { + hwndDialog = m_hwnd; + mir_subclassWindow(m_list.GetHwnd(), PluginListWndProc); + + Window_SetIcon_IcoLib(m_hwnd, iconList[2].hIcolib); + + HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); + ImageList_AddIconFromIconLib(hIml, 1); + m_list.SetImageList(hIml, LVSIL_SMALL); + + if (IsWinVer7Plus()) { + wchar_t szPath[MAX_PATH]; + GetModuleFileNameW(nullptr, szPath, _countof(szPath)); + wchar_t *ext = wcsrchr(szPath, '.'); + if (ext != nullptr) + *ext = '\0'; + wcscat(szPath, L".test"); + HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) + Button_SetElevationRequiredState(GetDlgItem(m_hwnd, IDOK), !IsProcessElevated()); + else { + CloseHandle(hFile); + DeleteFile(szPath); + } + } - lvg.pszHeader = TranslateT("Languages"); - lvg.iGroupId = 3; - ListView_InsertGroup(hwndList, 0, &lvg); + ////////////////////////////////////////////////////////////////////////////////////// + LVCOLUMN lvc = { 0 }; + lvc.mask = LVCF_WIDTH | LVCF_TEXT; - lvg.pszHeader = TranslateT("Other"); - lvg.iGroupId = 4; - ListView_InsertGroup(hwndList, 0, &lvg); + lvc.pszText = TranslateT("Component Name"); + lvc.cx = 220; // width of column in pixels + m_list.InsertColumn(0, &lvc); - ListView_EnableGroupView(hwndList, TRUE); + lvc.pszText = TranslateT("State"); + lvc.cx = 100; // width of column in pixels + m_list.InsertColumn(1, &lvc); - ////////////////////////////////////////////////////////////////////////////////////// - SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); - ListView_DeleteAllItems(hwndList); + ////////////////////////////////////////////////////////////////////////////////////// + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID; + + lvg.pszHeader = TranslateT("Plugins"); + lvg.iGroupId = 1; + m_list.InsertGroup(0, &lvg); + + lvg.pszHeader = TranslateT("Icons"); + lvg.iGroupId = 2; + m_list.InsertGroup(0, &lvg); + + lvg.pszHeader = TranslateT("Languages"); + lvg.iGroupId = 3; + m_list.InsertGroup(0, &lvg); + + lvg.pszHeader = TranslateT("Other"); + lvg.iGroupId = 4; + m_list.InsertGroup(0, &lvg); + + m_list.EnableGroupView(true); + + ////////////////////////////////////////////////////////////////////////////////////// + m_list.SendMsg(LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); + + FillList(nullptr); + + // do this after filling list - enables 'ITEMCHANGED' below + Utils_RestoreWindowPosition(m_hwnd, 0, MODULENAME, "ListWindow"); + return true; + } + + void OnDestroy() override + { + Utils_SaveWindowPosition(m_hwnd, NULL, MODULENAME, "ListWindow"); + Window_FreeIcon_IcoLib(m_hwnd); + hwndDialog = nullptr; + delete (OBJLIST *)GetWindowLongPtr(m_hwnd, GWLP_USERDATA); + } + + int Resizer(UTILRESIZECONTROL *urc) override + { + switch (urc->wId) { + case IDC_SELNONE: + case IDOK: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + + case IDC_SEARCH: + return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; + + case IDC_UPDATETEXT: + return RD_ANCHORX_CENTRE; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + } + + void onItemChanged(CCtrlListView::TEventInfo *ev) + { + NMLISTVIEW *nmlv = ev->nmlv; + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { + LVITEM lvI = { 0 }; + lvI.iItem = nmlv->iItem; + lvI.iSubItem = 0; + lvI.mask = LVIF_PARAM; + m_list.GetItem(&lvI); + + FILEINFO *p = (FILEINFO *)lvI.lParam; + p->bEnabled = m_list.GetCheckState(nmlv->iItem); - ////////////////////////////////////////////////////////////////////////////////////// bool enableOk = false; - OBJLIST &todo = *(OBJLIST *)lParam; - for (auto &p : todo) { - LVITEM lvi = { 0 }; - lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; - - int groupId = 4; - if (wcschr(p->tszOldName, L'\\') != nullptr) - groupId = (wcsstr(p->tszOldName, L"Plugins") != nullptr) ? 1 : ((wcsstr(p->tszOldName, L"Languages") != nullptr) ? 3 : 2); - - lvi.iItem = todo.indexOf(&p); - lvi.lParam = (LPARAM)p; - lvi.iGroupId = groupId; - lvi.iImage = ((groupId == 1) ? 0 : -1); - lvi.pszText = p->tszOldName; - ListView_InsertItem(hwndList, &lvi); - - if (p->bEnabled) { + for (auto &it : *todo) { + if (it->bEnabled) { enableOk = true; - ListView_SetCheckState(hwndList, lvi.iItem, 1); + break; } } - if (enableOk) - EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + + btnOk.Enable(enableOk); } + } - // do this after filling list - enables 'ITEMCHANGED' below - SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); - Utils_RestoreWindowPosition(hDlg, 0, MODULENAME, "ListWindow"); - return TRUE; - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->hwndFrom == hwndList) { - switch (((LPNMHDR)lParam)->code) { - case LVN_ITEMCHANGED: - if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { - LVITEM lvI = { 0 }; - lvI.iItem = nmlv->iItem; - lvI.iSubItem = 0; - lvI.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvI); - - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - FILEINFO *p = (FILEINFO*)lvI.lParam; - p->bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); - - bool enableOk = false; - for (auto &it : todo) { - if (it->bEnabled) { - enableOk = true; - break; - } - } - EnableWindow(GetDlgItem(hDlg, IDOK), enableOk ? TRUE : FALSE); - } - } - break; - } + void onClick_Ok(CCtrlButton *) + { + btnOk.Disable(); + btnNone.Disable(); + mir_forkthread(ApplyDownloads, this); + } + + void onClick_None(CCtrlButton *) + { + SelectAll(false); + } + + void onChange_Filter(CCtrlEdit *) + { + wchar_t wszText[100]; + m_filter.GetText(wszText, _countof(wszText)); + if (wszText[0] == 0) + FillList(nullptr); + else { + wcslwr(wszText); + FillList(wszText); } - break; + } - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED) { - switch (LOWORD(wParam)) { - case IDOK: - EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); - EnableWindow(GetDlgItem(hDlg, IDC_SELNONE), FALSE); + void Unpack() + { + AutoHandle pipe(hPipe); - mir_forkthread(ApplyDownloads, hDlg); - return TRUE; + // create needed folders after escalating priviledges. Folders creates when we actually install updates + wchar_t tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - case IDC_SELNONE: - SelectAll(hDlg, false); - break; + mir_snwprintf(tszFileBack, L"%s\\Backups", g_tszRoot); + SafeCreateDirectory(tszFileBack); - case IDCANCEL: - DestroyWindow(hDlg); - return TRUE; - } - } - break; + mir_snwprintf(tszFileTemp, L"%s\\Temp", g_tszRoot); + SafeCreateDirectory(tszFileTemp); - case WM_SIZE: // make the dlg resizeable - if (!IsIconic(hDlg)) - Utils_ResizeDialog(hDlg, g_plugin.getInst(), MAKEINTRESOURCEA(IDD_LIST), ListDlg_Resize); - break; + VARSW tszMirandaPath(L"%miranda_path%"); - case WM_GETMINMAXINFO: - { - LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; + HNETLIBCONN nlc = nullptr; + for (int i = 0; i < todo->getCount(); ++i) { + auto &p = (*todo)[i]; + m_list.EnsureVisible(i, FALSE); + if (p.bEnabled) { + // download update + m_list.SetItemText(i, 1, TranslateT("Downloading...")); - // The minimum width in points - mmi->ptMinTrackSize.x = 370; - // The minimum height in points - mmi->ptMinTrackSize.y = 300; + if (DownloadFile(&p.File, nlc)) { + m_list.SetItemText(i, 1, TranslateT("Succeeded.")); + if (unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack, false)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + db_unset(0, DB_MODULE_NEW_FILES, _T2A(p.tszOldName)); + } + else m_list.SetItemText(i, 1, TranslateT("Failed!")); + } + else m_list.SetItemText(i, 1, TranslateT("Skipped.")); } - break; + Netlib_CloseHandle(nlc); - case WM_CLOSE: - DestroyWindow(hDlg); - break; + ShowPopup(TranslateT("Plugin Updater"), TranslateT("Download complete"), POPUP_TYPE_INFO); - case WM_DESTROY: - Utils_SaveWindowPosition(hDlg, NULL, MODULENAME, "ListWindow"); - Window_FreeIcon_IcoLib(hDlg); - hwndDialog = nullptr; - delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); - break; + int rc = MessageBox(m_hwnd, TranslateT("Download complete. Do you want to go to plugins option page?"), TranslateT("Plugin Updater"), MB_YESNO | MB_ICONQUESTION); + if (rc == IDYES) + CallFunctionAsync(OpenPluginOptions, nullptr); + + Close(); } +}; - return FALSE; +static void ApplyDownloads(void *param) +{ + Thread_SetName("PluginUpdater: ApplyDownloads"); + auto *pDlg = (CMissingPLuginsDlg *)param; + + // if we need to escalate priviledges, launch a atub + if (PrepareEscalation()) + pDlg->Unpack(); + + pDlg->Close(); } static void __stdcall LaunchListDialog(void *param) { - hwndDialog = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param); + (new CMissingPLuginsDlg((OBJLIST *)param))->Show(); } static FILEINFO* ServerEntryToFileInfo(const ServListEntry &hash, const wchar_t* tszBaseUrl, const wchar_t* tszPath) -- cgit v1.2.3