diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index ca22a43dd..9708f358e 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -103,6 +103,8 @@ static LPCTSTR const kElimDup = TEXT("ElimDup"); static LPCTSTR const kNtSecur = TEXT("Security"); static LPCTSTR const kMemLimit = TEXT("MemLimit"); +static LPCTSTR const kFMCopyHistoryValueName = TEXT("CopyHistory"); + void CInfo::Save() const { CS_LOCK @@ -122,11 +124,13 @@ void CInfo::Save() const Key_Set_BoolPair(key, kShowPassword, ShowPassword); Key_Set_BoolPair(key, kOpnTrgFold, OpnTrgFold); - key.RecurseDeleteKey(kPathHistory); - if (WantPathHistory()) - key.SetValue_Strings(kPathHistory, Paths); - else - key.SetValue_Strings(kPathHistory, Empty); + // Store path history in shared FM key (cross-dialog: Extract GUI + FM context menu) + key.Close(); + if (key.Create(HKEY_CURRENT_USER, GetKeyPath(TEXT("FM"))) == ERROR_SUCCESS) + { + key.SetValue_Strings(kFMCopyHistoryValueName, Paths); + key.Close(); + } } void Save_ShowPassword(bool showPassword) @@ -137,6 +141,14 @@ void Save_ShowPassword(bool showPassword) key.SetValue(kShowPassword, showPassword); } +void Save_OpnTrgFold(bool open) +{ + CS_LOCK + CKey key; + CreateMainKey(key, kKeyName); + key.SetValue(kOpnTrgFold, open); +} + void Save_LimitGB(UInt32 limit_GB) { CS_LOCK @@ -158,29 +170,37 @@ void CInfo::Load() CS_LOCK CKey key; - if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) - return; - - key.GetValue_Strings(kPathHistory, Paths); - UInt32 v; - if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) + + // Resilient against missing Extraction key; load paths from shared FM key + if (OpenMainKey(key, kKeyName) == ERROR_SUCCESS) { - PathMode = (NPathMode::EEnum)v; - PathMode_Force = true; + UInt32 v; + if (key.GetValue_UInt32_IfOk(kExtractMode, v) == ERROR_SUCCESS && v <= NPathMode::kAbsPaths) + { + PathMode = (NPathMode::EEnum)v; + PathMode_Force = true; + } + if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) + { + OverwriteMode = (NOverwriteMode::EEnum)v; + OverwriteMode_Force = true; + } + + Key_Get_BoolPair_true(key, kSplitDest, SplitDest); + + Key_Get_BoolPair(key, kElimDup, ElimDup); + // Key_Get_BoolPair(key, kAltStreams, AltStreams); + Key_Get_BoolPair(key, kNtSecur, NtSecurity); + Key_Get_BoolPair(key, kShowPassword, ShowPassword); + Key_Get_BoolPair(key, kOpnTrgFold, OpnTrgFold); + key.Close(); } - if (key.GetValue_UInt32_IfOk(kOverwriteMode, v) == ERROR_SUCCESS && v <= NOverwriteMode::kRenameExisting) + + if (key.Open(HKEY_CURRENT_USER, GetKeyPath(TEXT("FM")), KEY_READ) == ERROR_SUCCESS) { - OverwriteMode = (NOverwriteMode::EEnum)v; - OverwriteMode_Force = true; + key.GetValue_Strings(kFMCopyHistoryValueName, Paths); + key.Close(); } - - Key_Get_BoolPair_true(key, kSplitDest, SplitDest); - - Key_Get_BoolPair(key, kElimDup, ElimDup); - // Key_Get_BoolPair(key, kAltStreams, AltStreams); - Key_Get_BoolPair(key, kNtSecur, NtSecurity); - Key_Get_BoolPair(key, kShowPassword, ShowPassword); - Key_Get_BoolPair(key, kOpnTrgFold, OpnTrgFold); } bool Read_ShowPassword() @@ -194,6 +214,17 @@ bool Read_ShowPassword() return showPassword; } +bool Read_OpnTrgFold() +{ + CS_LOCK + CKey key; + bool open = false; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return open; + key.GetValue_bool_IfOk(kOpnTrgFold, open); + return open; +} + UInt32 Read_LimitGB() { CS_LOCK @@ -607,7 +638,7 @@ void CContextMenuInfo::Load() Cascaded.Val = true; Cascaded.Def = false; - MenuIcons.Val = false; + MenuIcons.Val = true; MenuIcons.Def = false; ElimDup.Val = true; @@ -634,7 +665,7 @@ void CContextMenuInfo::Load() Key_Get_BoolPair_true(key, kCascadedMenu, Cascaded); Key_Get_BoolPair_true(key, kElimDup, ElimDup); - Key_Get_BoolPair(key, kMenuIcons, MenuIcons); + Key_Get_BoolPair_true(key, kMenuIcons, MenuIcons); Key_Get_UInt32(key, kWriteZoneId, WriteZone); diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index bbeb75a1f..2d24400cf 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -46,6 +46,9 @@ namespace NExtract void Save_ShowPassword(bool showPassword); bool Read_ShowPassword(); + void Save_OpnTrgFold(bool open); + bool Read_OpnTrgFold(); + void Save_LimitGB(UInt32 limit_GB); UInt32 Read_LimitGB(); } diff --git a/CPP/7zip/UI/Explorer/ContextMenu.cpp b/CPP/7zip/UI/Explorer/ContextMenu.cpp index 3dd19850c..115ecaf4c 100644 --- a/CPP/7zip/UI/Explorer/ContextMenu.cpp +++ b/CPP/7zip/UI/Explorer/ContextMenu.cpp @@ -648,14 +648,10 @@ Z7_COMWF_B CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, _elimDup = ci.ElimDup; _writeZone = ci.WriteZone; - HBITMAP bitmap = NULL; - if (ci.MenuIcons.Val) - { - ODS("### 45") - if (!_bitmap) - _bitmap = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_MENU_LOGO)); - bitmap = _bitmap; - } + ODS("### 45") + if (!_bitmap) + _bitmap = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_MENU_LOGO)); + HBITMAP bitmap = _bitmap; UINT subIndex = indexMenu; diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp index d93b94cb8..599bbe459 100644 --- a/CPP/7zip/UI/FileManager/App.cpp +++ b/CPP/7zip/UI/FileManager/App.cpp @@ -43,6 +43,30 @@ extern HINSTANCE g_hInstance; #define kTempDirPrefix FTEXT("7zE") +// Walk up, delete found archive. +static void DeleteSourceArchive_WalkUp(CPanel &srcPanel, UString srcFilePath) +{ + while (!srcFilePath.IsEmpty()) + { + if (srcFilePath.Back() == L'\\') + srcFilePath.DeleteBack(); + const DWORD dwAttr = GetFileAttributesW(srcFilePath); // NOSONAR cpp:S6004 — FM build is pre-C++17, init-statement not available + + if (dwAttr != INVALID_FILE_ATTRIBUTES) + { + if (dwAttr & FILE_ATTRIBUTE_ARCHIVE) + NDir::DeleteFileIfArchive(us2fs(srcFilePath)); + return; + } + + const int n = srcFilePath.ReverseFind(L'\\'); + if (n == -1) + return; + srcPanel.OpenParentFolder(); + srcFilePath.ReleaseBuf_SetEnd(n); + } +} + void CPanelCallbackImp::OnTab() { if (g_App.NumPanels != 1) @@ -591,7 +615,7 @@ UString CPanel::GetItemsInfoString(const CRecordVector &indices) info.Add_LF(); info += _currentFolderPrefix; - + for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++) { info.Add_LF(); @@ -612,7 +636,6 @@ UString CPanel::GetItemsInfoString(const CRecordVector &indices) bool IsCorrectFsName(const UString &name); - /* Returns true, if path is path that can be used as path for File System functions */ @@ -647,6 +670,9 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex) CRecordVector indices; UString destPath; + bool openOutputFolder = false; + bool deleteSourceFile = false; + bool close7Zip = false; bool useDestPanel = false; { @@ -685,10 +711,15 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex) LangString(move ? IDS_MOVE : IDS_COPY, copyDialog.Title); LangString(move ? IDS_MOVE_TO : IDS_COPY_TO, copyDialog.Static); copyDialog.Info = srcPanel.GetItemsInfoString(indices); + copyDialog.CurrentFolderPrefix = srcPanel._currentFolderPrefix; if (copyDialog.Create(srcPanel.GetParent()) != IDOK) return; + openOutputFolder = copyDialog.OpenOutputFolder; + deleteSourceFile = copyDialog.DeleteSourceFile; + close7Zip = copyDialog.Close7Zip; + destPath = copyDialog.Value; } @@ -820,6 +851,8 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex) SaveCopyHistory(copyFolders); } + ProgressDialog_SetError(false); + bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder(); bool useTemp = useSrcPanel && useDestPanel; @@ -916,6 +949,24 @@ void CApp::OnCopy(bool move, bool copyToSame, unsigned srcPanelIndex) disableNotify1.Restore(); disableNotify2.Restore(); srcPanel.SetFocusToList(); + + if (!ProgressDialog_HadError() && result == S_OK) + { + if (openOutputFolder && NFind::DoesDirExist_FollowLink(us2fs(destPath))) + { + StartApplicationDontWait(destPath, destPath, _window); + } + if (deleteSourceFile) + { + UString srcFilePath(srcPanel._currentFolderPrefix); + srcPanel.OpenParentFolder(); + DeleteSourceArchive_WalkUp(srcPanel, srcFilePath); + } + if (close7Zip) + { + PostMessage(_window, WM_CLOSE, 0, 0); + } + } } void CApp::OnSetSameFolder(unsigned srcPanelIndex) diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp index b12d8e814..e85b55845 100644 --- a/CPP/7zip/UI/FileManager/BrowseDialog.cpp +++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp @@ -1,7 +1,9 @@ // BrowseDialog.cpp - + #include "StdAfx.h" +#include + #include "../../../Common/MyWindows.h" #include "../../../Common/IntToString.h" @@ -566,6 +568,79 @@ wchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s) return s; } + +// ". B" with 2 decimals, or " B". +void FreeSpace_ConvertSizeToString(UInt64 v, wchar_t *s); +void FreeSpace_ConvertSizeToString(UInt64 v, wchar_t *s) +{ + unsigned shift = 0; + wchar_t unit = 0; + if (v >= ((UInt64)1 << 50)) { shift = 50; unit = 'P'; } + else if (v >= ((UInt64)1 << 40)) { shift = 40; unit = 'T'; } + else if (v >= ((UInt64)1 << 30)) { shift = 30; unit = 'G'; } + else if (v >= ((UInt64)1 << 20)) { shift = 20; unit = 'M'; } + else if (v >= ((UInt64)1 << 10)) { shift = 10; unit = 'K'; } + + if (unit == 0) + { + s = ConvertUInt64ToString(v, s); + *s++ = ' '; + *s++ = 'B'; + *s = 0; + return; + } + + const UInt64 whole = v >> shift; + UInt64 frac = ((v & (((UInt64)1 << shift) - 1)) * 100 + + ((UInt64)1 << (shift - 1))) >> shift; + if (frac >= 100) + frac = 99; + + s = ConvertUInt64ToString(whole, s); + *s++ = '.'; + *s++ = (wchar_t)('0' + (unsigned)(frac / 10)); + *s++ = (wchar_t)('0' + (unsigned)(frac % 10)); + *s++ = ' '; + *s++ = unit; + *s++ = 'B'; + *s = 0; +} + + +// Trims path, then formats free/total. +void FormatPathFreeSpace(UString &strPath, UString &strText); +void FormatPathFreeSpace(UString &strPath, UString &strText) +{ + strText.Empty(); + strPath.Trim(); + for (;;) + { + const DWORD attr = GetFileAttributesW(strPath); // NOSONAR cpp:S6004 — FM build is pre-C++17, init-statement not available + if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY)) + break; + const int n = strPath.ReverseFind(L'\\'); + if (n == -1) + return; + strPath.ReleaseBuf_SetEnd(n); + } + + ULARGE_INTEGER freeBytes; + ULARGE_INTEGER totalBytes; + ULARGE_INTEGER totalFree; + if (!GetDiskFreeSpaceExW(strPath, &freeBytes, &totalBytes, &totalFree)) + return; + + std::array szFree; + std::array szTotal; + FreeSpace_ConvertSizeToString(totalFree.QuadPart, szFree.data()); + FreeSpace_ConvertSizeToString(totalBytes.QuadPart, szTotal.data()); + strText = szFree.data(); + strText += L" Free (Total: "; + strText += szTotal.data(); + strText += L")"; +} + + // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) diff --git a/CPP/7zip/UI/FileManager/CopyDialog.cpp b/CPP/7zip/UI/FileManager/CopyDialog.cpp index 9bc01d064..f3ab9905f 100644 --- a/CPP/7zip/UI/FileManager/CopyDialog.cpp +++ b/CPP/7zip/UI/FileManager/CopyDialog.cpp @@ -2,16 +2,61 @@ #include "StdAfx.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Control/Static.h" +#include "../Common/ZipRegistry.h" + #include "BrowseDialog.h" #include "CopyDialog.h" +#include "FormatUtils.h" + +#include "Panel.h" +#include "ViewSettings.h" + #include "LangUtils.h" +extern void FormatPathFreeSpace(UString &strPath, UString &strText); + using namespace NWindows; +static bool IsFileExistentAndNotDir(const wchar_t * lpszFile) +{ + DWORD dwAttr = GetFileAttributesW(lpszFile); + return (dwAttr != INVALID_FILE_ATTRIBUTES) + && ((dwAttr & FILE_ATTRIBUTE_ARCHIVE) != 0) + && ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == 0); +} + +// Walk up, extract archive basename. +static void FindRealFileName_WalkUp(UString &pathPrefix, UString &realName) +{ + while (!pathPrefix.IsEmpty()) + { + if (pathPrefix.Back() == L'\\') + pathPrefix.DeleteBack(); + + if (IsFileExistentAndNotDir(pathPrefix)) + { + const int slash = pathPrefix.ReverseFind(L'\\'); + const int dot = pathPrefix.ReverseFind(L'.'); + const int start = (slash != -1) ? slash + 1 : 0; + const int end = (dot == -1 || dot <= start) ? pathPrefix.Len() : dot; + realName = pathPrefix.Mid(start, end - start); + return; + } + + const int slash = pathPrefix.ReverseFind(L'\\'); + if (slash == -1) + return; + pathPrefix.ReleaseBuf_SetEnd(slash); + } +} + bool CCopyDialog::OnInit() { #ifdef Z7_LANG @@ -20,6 +65,9 @@ bool CCopyDialog::OnInit() _path.Attach(GetItem(IDC_COPY)); SetText(Title); + _freeSpace.Attach(GetItem(IDC_FREE_SPACE)); + _freeSpace.SetText(L""); + NControl::CStatic staticContol; staticContol.Attach(GetItem(IDT_COPY)); staticContol.SetText(Static); @@ -30,8 +78,32 @@ bool CCopyDialog::OnInit() FOR_VECTOR (i, Strings) _path.AddString(Strings[i]); _path.SetText(Value); + ShowPathFreeSpace(Value); + + OpenOutputFolder = NExtract::Read_OpnTrgFold(); + Close7Zip = Read_Close7Zip(); + + CheckButton(IDC_CHECK_OPEN_OUTPUT_FOLDER, OpenOutputFolder); + CheckButton(IDC_CHECK_CLOSE_7ZIP, Close7Zip); + SetItemText(IDT_COPY_INFO, Info); NormalizeSize(true); + + Set_MinTrackSize_FromCurrent(4, 5, 4, 5); + + ///////////////////////////////////////////////////////// + + RealFileName.Empty(); + if (NFile::NFind::DoesDirExist_FollowLink(us2fs(CurrentFolderPrefix))) + { + EnableItem(IDC_COPY_ADD_FILE_NAME, false); + EnableItem(IDC_CHECK_DELETE_SOURCE_FILE, false); + } + else + { + FindRealFileName_WalkUp(CurrentFolderPrefix, RealFileName); + } + return CModalDialog::OnInit(); } @@ -45,28 +117,41 @@ bool CCopyDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) const int y = ySize - my - by; const int x = xSize - mx - bx1; - InvalidateRect(NULL); - { RECT r; + + GetClientRectOfItem(IDC_COPY_ADD_FILE_NAME, r); + int bxAddFileName = r.right - r.left; + int byAddFileName = r.bottom - r.top; + MoveItem(IDC_COPY_ADD_FILE_NAME, xSize - mx - bxAddFileName, r.top, bxAddFileName, byAddFileName, false); + + GetClientRectOfItem(IDC_COPY_OPEN_PATH, r); + int bxOpen = r.right - r.left; + int byOpen = r.bottom - r.top; + MoveItem(IDC_COPY_OPEN_PATH, xSize - mx - bxOpen - mx/2 - bxAddFileName, r.top, bxOpen, byOpen, false); + GetClientRectOfItem(IDB_COPY_SET_PATH, r); - const int bx = RECT_SIZE_X(r); - MoveItem(IDB_COPY_SET_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r)); - ChangeSubWindowSizeX(_path, xSize - mx - mx - bx - mx); + int bxSet = RECT_SIZE_X(r); + int bySet = RECT_SIZE_Y(r); + MoveItem(IDB_COPY_SET_PATH, xSize - mx - bxSet - bxOpen - mx - bxAddFileName, r.top, bxSet, bySet, false); + ChangeSubWindowSizeX(_path, xSize - mx - mx - bxSet - bxOpen - mx - mx/2 - bxAddFileName); } { RECT r; GetClientRectOfItem(IDT_COPY_INFO, r); - NControl::CStatic staticContol; - staticContol.Attach(GetItem(IDT_COPY_INFO)); const int yPos = r.top; - staticContol.Move(mx, yPos, xSize - mx * 2, y - 2 - yPos); + const int xc = xSize - mx * 2; + MoveItem(IDT_COPY_INFO, mx, yPos, xc, y - 2 - yPos, false); + + GetClientRectOfItem(IDC_AFTER_EXTRACT, r); + MoveItem(IDC_AFTER_EXTRACT, mx, r.top, xc, r.bottom - r.top, false); } - MoveItem(IDCANCEL, x, y, bx1, by); - MoveItem(IDOK, x - mx - bx2, y, bx2, by); + MoveItem(IDCANCEL, x, y, bx1, by, false); + MoveItem(IDOK, x - mx - bx2, y, bx2, by, false); + InvalidateRect(NULL); return false; } @@ -77,6 +162,21 @@ bool CCopyDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) case IDB_COPY_SET_PATH: OnButtonSetPath(); return true; + case IDC_COPY_OPEN_PATH: + OnButtonOpenPath(); + return true; + case IDC_COPY_ADD_FILE_NAME: + OnButtonAddFileName(); + return true; + case IDC_CHECK_OPEN_OUTPUT_FOLDER: + OpenOutputFolder = IsButtonCheckedBool(IDC_CHECK_OPEN_OUTPUT_FOLDER); + return true; + case IDC_CHECK_DELETE_SOURCE_FILE: + DeleteSourceFile = IsButtonCheckedBool(IDC_CHECK_DELETE_SOURCE_FILE); + return true; + case IDC_CHECK_CLOSE_7ZIP: + Close7Zip = IsButtonCheckedBool(IDC_CHECK_CLOSE_7ZIP); + return true; } return CModalDialog::OnButtonClicked(buttonID, buttonHWND); } @@ -94,10 +194,98 @@ void CCopyDialog::OnButtonSetPath() NFile::NName::NormalizeDirPathPrefix(resultPath); _path.SetCurSel(-1); _path.SetText(resultPath); + ShowPathFreeSpace(resultPath); } void CCopyDialog::OnOK() { + NExtract::Save_OpnTrgFold(OpenOutputFolder); + Save_Close7Zip(Close7Zip); + _path.GetText(Value); CModalDialog::OnOK(); } + +void CCopyDialog::OnButtonOpenPath() +{ + UString currentPath; + _path.GetText(currentPath); + + if (NFile::NFind::DoesDirExist_FollowLink(us2fs(currentPath))) + { + StartApplicationDontWait(currentPath, currentPath, *this); + } + else + { + const UString msg = MyFormatNew( + L"Folder \"{0}\" is not available yet.\n\n" + L"Note: the program will create the folder automatically when extracting.", + currentPath); + MessageBoxW(*this, msg, L"7-Zip", MB_ICONEXCLAMATION); + } +} + +void CCopyDialog::OnButtonAddFileName() +{ + UString currentPath; + _path.GetText(currentPath); + + currentPath.Trim(); + if (currentPath.Back() == '\\') + { + currentPath.DeleteBack(); + } + + UString strLastDir; + int n = currentPath.ReverseFind(L'\\'); + if (n != -1) + { + strLastDir = currentPath.Ptr(n+1); + } + else + { + strLastDir = currentPath; + } + if (strLastDir != RealFileName) + { + currentPath += L'\\'; + currentPath += RealFileName; + + _path.SetText(currentPath); + } + _path.SetFocus(); +} + +void CCopyDialog::ShowPathFreeSpace(UString & strPath) +{ + UString strText; + FormatPathFreeSpace(strPath, strText); + _freeSpace.SetText(strText); +} + +bool CCopyDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam) +{ + if (itemID == IDC_COPY) + { + if (code == CBN_EDITCHANGE) + { + UString strPath; + _path.GetText(strPath); + + ShowPathFreeSpace(strPath); + return true; + } + else if (code == CBN_SELCHANGE) + { + int nSel = _path.GetCurSel(); + if (nSel != CB_ERR) + { + UString strPath; + _path.GetLBText(nSel, strPath); + ShowPathFreeSpace(strPath); + } + return true; + } + } + return CModalDialog::OnCommand(code, itemID, lParam); +} diff --git a/CPP/7zip/UI/FileManager/CopyDialog.h b/CPP/7zip/UI/FileManager/CopyDialog.h index 378242085..844953506 100644 --- a/CPP/7zip/UI/FileManager/CopyDialog.h +++ b/CPP/7zip/UI/FileManager/CopyDialog.h @@ -5,6 +5,7 @@ #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Dialog.h" +#include "../../../Windows/Control/Static.h" #include "CopyDialogRes.h" @@ -13,18 +14,34 @@ const int kCopyDialog_NumInfoLines = 11; class CCopyDialog: public NWindows::NControl::CModalDialog { NWindows::NControl::CComboBox _path; + NWindows::NControl::CStatic _freeSpace; virtual void OnOK() Z7_override; virtual bool OnInit() Z7_override; virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; void OnButtonSetPath(); + void OnButtonOpenPath(); + void OnButtonAddFileName(); + bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam) Z7_override; + + void ShowPathFreeSpace(UString & strPath); + public: + CCopyDialog() = default; + UString Title; UString Static; UString Value; UString Info; UStringVector Strings; + bool OpenOutputFolder = false; + bool DeleteSourceFile = false; + bool Close7Zip = false; + + UString CurrentFolderPrefix; + UString RealFileName; + INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_COPY, parentWindow); } }; diff --git a/CPP/7zip/UI/FileManager/CopyDialog.rc b/CPP/7zip/UI/FileManager/CopyDialog.rc index 73d3ea80d..f0026085b 100644 --- a/CPP/7zip/UI/FileManager/CopyDialog.rc +++ b/CPP/7zip/UI/FileManager/CopyDialog.rc @@ -1,18 +1,54 @@ #include "CopyDialogRes.h" #include "../../GuiCommon.rc" -#define xc 320 -#define yc 144 +#define xc 340 +#define yc 190 -#define y 40 +#define y 78 + +#define OPEN_XS 28 +#define FILENAME_XS 40 +#define SPACE_XS 4 + +#define FILENAME_X (xs - m - FILENAME_XS) +#define OPEN_X (FILENAME_X - OPEN_XS - SPACE_XS) +#define DOTS_X (OPEN_X - bxsDots - SPACE_XS) +#define PATH_Y (m + 12) +#define PATH_XS (DOTS_X - m - SPACE_XS) + +#define FREE_SPACE_Y (PATH_Y + 15) + +#define AFTER_EXTRACTION_Y (FREE_SPACE_Y + 12) + +#define OPTION_SPACE 10 + +#define OPEN_OUTPUT_FOLDER_X (m + 6) +#define OPEN_OUTPUT_FOLDER_XS 80 +#define OPEN_OUTPUT_FOLDER_Y (AFTER_EXTRACTION_Y + 12) + +#define DELETE_SOURCE_X (OPEN_OUTPUT_FOLDER_X + OPEN_OUTPUT_FOLDER_XS + OPTION_SPACE) +#define DELETE_SOURCE_XS 88 + +#define CLOSE_7ZIP_X (DELETE_SOURCE_X + DELETE_SOURCE_XS + OPTION_SPACE) +#define CLOSE_7ZIP_XS 54 + +#define INFO_Y (AFTER_EXTRACTION_Y + 27 + 4) +#define INFO_YS (by - m - 12 - 15 - 12 - 27 - 4 - 1) IDD_COPY DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Copy" { - LTEXT "", IDT_COPY, m, m, xc, 8 - COMBOBOX IDC_COPY, m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT - PUSHBUTTON "...", IDB_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP - LTEXT "", IDT_COPY_INFO, m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP + LTEXT "", IDT_COPY, m, m, xc, 9 + COMBOBOX IDC_COPY, m, PATH_Y, PATH_XS, 160, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_COPY_SET_PATH, DOTS_X, PATH_Y - 1, bxsDots, bys - 1, WS_GROUP + PUSHBUTTON "&Open", IDC_COPY_OPEN_PATH, OPEN_X, PATH_Y - 1, OPEN_XS, bys - 1, WS_GROUP + PUSHBUTTON "&Filename", IDC_COPY_ADD_FILE_NAME, FILENAME_X, PATH_Y - 1, FILENAME_XS, bys - 1, WS_GROUP + LTEXT "", IDC_FREE_SPACE, m, FREE_SPACE_Y, xc, 9 + GROUPBOX "After extraction completes successfully", IDC_AFTER_EXTRACT, m, AFTER_EXTRACTION_Y, xc, 27 + CONTROL "O&pen output folder", IDC_CHECK_OPEN_OUTPUT_FOLDER, MY_CHECKBOX, OPEN_OUTPUT_FOLDER_X, OPEN_OUTPUT_FOLDER_Y, OPEN_OUTPUT_FOLDER_XS, 10 + CONTROL "&Delete source archive", IDC_CHECK_DELETE_SOURCE_FILE, MY_CHECKBOX, DELETE_SOURCE_X, OPEN_OUTPUT_FOLDER_Y, DELETE_SOURCE_XS, 10 + CONTROL "&Close 7-Zip", IDC_CHECK_CLOSE_7ZIP, MY_CHECKBOX, CLOSE_7ZIP_X, OPEN_OUTPUT_FOLDER_Y, CLOSE_7ZIP_XS, 10 + LTEXT "", IDT_COPY_INFO, m, INFO_Y, xc, INFO_YS, SS_NOPREFIX | SS_LEFTNOWORDWRAP OK_CANCEL } diff --git a/CPP/7zip/UI/FileManager/CopyDialogRes.h b/CPP/7zip/UI/FileManager/CopyDialogRes.h index 85f5a39a4..a52327d60 100644 --- a/CPP/7zip/UI/FileManager/CopyDialogRes.h +++ b/CPP/7zip/UI/FileManager/CopyDialogRes.h @@ -5,4 +5,13 @@ #define IDB_COPY_SET_PATH 102 #define IDT_COPY_INFO 103 +// Win32 resource IDs — must remain #define for rc.exe (cpp:S5028 N/A). +#define IDC_CHECK_OPEN_OUTPUT_FOLDER 104 // NOSONAR +#define IDC_COPY_OPEN_PATH 105 // NOSONAR +#define IDC_FREE_SPACE 106 // NOSONAR +#define IDC_COPY_ADD_FILE_NAME 107 // NOSONAR +#define IDC_CHECK_DELETE_SOURCE_FILE 108 // NOSONAR +#define IDC_CHECK_CLOSE_7ZIP 109 // NOSONAR +#define IDC_AFTER_EXTRACT 110 // NOSONAR + #define IDS_SET_FOLDER 6007 diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp index 6767e4c0c..748e4d45a 100644 --- a/CPP/7zip/UI/FileManager/ListViewDialog.cpp +++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp @@ -126,6 +126,8 @@ bool CListViewDialog::OnInit() _listView.SetColumnWidthAuto(1); StringsWereChanged = false; + Set_MinTrackSize_FromCurrent(3, 4, 3, 4); + NormalizeSize(); return CModalDialog::OnInit(); } @@ -146,15 +148,14 @@ bool CListViewDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) rect.top = y - my; InvalidateRect(&rect); */ - InvalidateRect(NULL); - - MoveItem(IDCANCEL, x, y, bx1, by); - MoveItem(IDOK, x - mx - bx2, y, bx2, by); + MoveItem(IDCANCEL, x, y, bx1, by, false); + MoveItem(IDOK, x - mx - bx2, y, bx2, by, false); /* if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE) mx = 0; */ - _listView.Move(mx, my, xSize - mx * 2, y - my * 2); + _listView.Move(mx, my, xSize - mx * 2, y - my * 2, false); + InvalidateRect(NULL); return false; } @@ -319,3 +320,4 @@ void CListViewDialog::OnOK() FocusedItemIndex = _listView.GetFocusedItem(); CModalDialog::OnOK(); } + diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp index 57e56bcf7..06a01f707 100644 --- a/CPP/7zip/UI/FileManager/MessagesDialog.cpp +++ b/CPP/7zip/UI/FileManager/MessagesDialog.cpp @@ -55,6 +55,9 @@ bool CMessagesDialog::OnInit() _messageList.SetColumnWidthAuto(0); _messageList.SetColumnWidthAuto(1); + + Set_MinTrackSize_FromCurrent(3, 4, 3, 4); + NormalizeSize(); return CModalDialog::OnInit(); } @@ -68,9 +71,10 @@ bool CMessagesDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) int y = ySize - my - by; int x = xSize - mx - bx; - InvalidateRect(NULL); - MoveItem(IDOK, x, y, bx, by); - _messageList.Move(mx, my, xSize - mx * 2, y - my * 2); + MoveItem(IDOK, x, y, bx, by, false); + _messageList.Move(mx, my, xSize - mx * 2, y - my * 2, false); + InvalidateRect(NULL); return false; } + diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.h b/CPP/7zip/UI/FileManager/MessagesDialog.h index 40b0379bf..62297a369 100644 --- a/CPP/7zip/UI/FileManager/MessagesDialog.h +++ b/CPP/7zip/UI/FileManager/MessagesDialog.h @@ -18,7 +18,7 @@ class CMessagesDialog: public NWindows::NControl::CModalDialog virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override; public: const UStringVector *Messages; - + INT_PTR Create(HWND parent = NULL) { return CModalDialog::Create(IDD_MESSAGES, parent); } }; diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h index b2432597f..43dbfd0ac 100644 --- a/CPP/7zip/UI/FileManager/Panel.h +++ b/CPP/7zip/UI/FileManager/Panel.h @@ -210,6 +210,7 @@ enum MyMessages }; UString GetFolderPath(IFolderFolder *folder); +void StartApplicationDontWait(const UString &dir, const UString &path, HWND window); class CPanel; diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index c452d41c1..3fa9aa8f0 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -493,7 +493,10 @@ void CApp::Combine() AddInfoFileName(info, L"..."); AddInfoFileName(info, fs2us(combiner.Names.Back())); } - + + bool openOutputFolder = false; + bool deleteSourceFile = false; + bool close7Zip = false; { CCopyDialog copyDialog; copyDialog.Value = path; @@ -502,9 +505,13 @@ void CApp::Combine() copyDialog.Title += srcPanel.GetItemRelPath(index); LangString(IDS_COMBINE_TO, copyDialog.Static); copyDialog.Info = info; + copyDialog.CurrentFolderPrefix = srcPanel.GetItemFullPath(index); if (copyDialog.Create(srcPanel.GetParent()) != IDOK) return; path = copyDialog.Value; + openOutputFolder = copyDialog.OpenOutputFolder; + deleteSourceFile = copyDialog.DeleteSourceFile; + close7Zip = copyDialog.Close7Zip; } NName::NormalizeDirPathPrefix(path); @@ -552,6 +559,20 @@ void CApp::Combine() if (combiner.Create(title, _window) != 0) return; + + if (openOutputFolder && NFind::DoesDirExist_FollowLink(us2fs(path))) + { + StartApplicationDontWait(path, path, _window); + } + if (deleteSourceFile) + { + for (i = 0; i < combiner.Names.Size(); i++) + NDir::DeleteFileIfArchive(us2fs(srcPath) + combiner.Names[i]); + } + if (close7Zip) + { + PostMessage(_window, WM_CLOSE, 0, 0); + } } RefreshTitleAlways(); diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp index a070a0a37..842b343de 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp @@ -13,18 +13,60 @@ #include "../../../Windows/ErrorMsg.h" #include "../GUI/ExtractRes.h" +#include "resourceGui.h" #include "LangUtils.h" #include "DialogSize.h" #include "ProgressDialog2.h" #include "ProgressDialog2Res.h" +#include "ProgressDialog2IconRes.h" using namespace NWindows; extern HINSTANCE g_hInstance; extern bool g_DisableUserQuestions; +namespace { + bool& ProcessErrorRef() + { + static bool s_error = false; + return s_error; + } +} + +void ProgressDialog_SetError(bool error) { ProcessErrorRef() = error; } +bool ProgressDialog_HadError() { return ProcessErrorRef(); } + +static const UINT WM_TRAY_ICON_NOTIFY = WM_APP + 10; +static const UINT ID_SYSTRAY_ICON = 100; + +static BOOL SetSysTray(HWND dlg, + DWORD message, + UINT id, + UINT flags, + UINT callbackMessage, + HICON icon, + const wchar_t *tip) +{ + NOTIFYICONDATAW data; + ZeroMemory(&data, sizeof(NOTIFYICONDATAW)); + + data.cbSize = sizeof(NOTIFYICONDATAW); + data.hWnd = dlg; + data.uID = id; + data.uFlags = flags; + data.uCallbackMessage = callbackMessage; + data.hIcon = icon; + + if (tip != nullptr && *tip != 0) + { + ::lstrcpynW(data.szTip, tip, static_cast(std::size(data.szTip))); + } + + return Shell_NotifyIconW(message, &data); +} + static const UINT_PTR kTimerID = 3; static const UINT kCloseMessage = WM_APP + 1; @@ -270,7 +312,6 @@ CProgressDialog::CProgressDialog(): IconID(-1), MainWindow(NULL) { - if (_dialogCreatedEvent.Create() != S_OK) throw 1334987; if (_createDialogEvent.Create() != S_OK) @@ -389,6 +430,7 @@ bool CProgressDialog::OnInit() LangString(IDS_PROGRESS_FOREGROUND, _foreground_String); LangString(IDS_CONTINUE, _continue_String); LangString(IDS_PROGRESS_PAUSED, _paused_String); + LangString(IDS_CANCEL, cancelString); SetText(_title); SetPauseText(); @@ -428,6 +470,8 @@ bool CProgressDialog::OnInit() SetTaskbarProgressState(); + Set_MinTrackSize_FromCurrent(2, 3, 3, 4); + return CModalDialog::OnInit(); } @@ -476,7 +520,13 @@ bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) int yPos = ySize - my - _buttonSizeY; ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2); - ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2); + { + RECT rect; + GetClientRectOfItem(IDC_PROGRESS_PERCENT, rect); + int percent_width = rect.right - rect.left; + MoveItem(IDC_PROGRESS_PERCENT, xSize - mx - percent_width, rect.top, percent_width, rect.bottom - rect.top); + ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - (mx * 2) - percent_width); + } ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2); int bSizeX = _buttonSizeX; @@ -841,9 +891,18 @@ void CProgressDialog::UpdateStatInfo(bool showAll) { _prevPercentValue = percent; needSetTitle = true; + + std::array szPercent; + wchar_t *p = ConvertUInt64ToString(percent, szPercent.data()); + *p++ = L'%'; + *p = 0; + SetItemText(IDC_PROGRESS_PERCENT, szPercent.data()); + + if (_background && _sysTray.Icons[0] != nullptr) + _sysTray.UpdateIcon(_window, _prevPercentValue, false, true); } } - + { wchar_t s[64]; @@ -1051,6 +1110,9 @@ bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { + case WM_TRAY_ICON_NOTIFY: + return OnTrayNotification(lParam); + case kCloseMessage: { if (_timer) @@ -1067,6 +1129,25 @@ bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) _externalCloseMessageWasReceived = true; break; } + if (_background) + { + SetSysTray(_window, NIM_DELETE, ID_SYSTRAY_ICON, 0, 0, nullptr, nullptr); + if (MainWindow != nullptr) + ShowWindow(MainWindow, SW_SHOW); + } + if (_sysTray.Icons[0] != nullptr) + { + for (auto &icon : _sysTray.Icons) + { + DestroyIcon(icon); + icon = nullptr; + } + } + if (_sysTray.Menu != nullptr) + { + ::DestroyMenu(_sysTray.Menu); + _sysTray.Menu = nullptr; + } return OnExternalCloseMessage(); } /* @@ -1123,8 +1204,12 @@ void CProgressDialog::SetTitleText() void CProgressDialog::SetPauseText() { - SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String); + LPCWSTR pszText = Sync.Get_Paused() ? _continue_String : _pause_String; + SetItemText(IDB_PAUSE, pszText); SetTitleText(); + + if (_sysTray.Menu != nullptr) + ModifyMenuW(_sysTray.Menu, IDB_PAUSE, MF_BYCOMMAND, IDB_PAUSE, pszText); } void CProgressDialog::OnPauseButton() @@ -1152,6 +1237,26 @@ void CProgressDialog::OnPriorityButton() _background = !_background; #ifndef UNDER_CE SetPriorityClass(GetCurrentProcess(), _background ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); + if (!_background) // foreground + { + if (_sysTray.Icons[0] != nullptr) + { + if (MainWindow != nullptr) + ShowWindow(MainWindow, SW_SHOW); + Show(SW_SHOW); + SetSysTray(_window, NIM_DELETE, ID_SYSTRAY_ICON, 0, 0, nullptr, nullptr); + } + } + else + { + if (_sysTray.LoadIcons(g_hInstance, IDI_SYSTRAY_0)) + { + if (MainWindow != nullptr) + ShowWindow(MainWindow, SW_HIDE); + Show(SW_HIDE); + _sysTray.UpdateIcon(_window, _prevPercentValue, true, true); + } + } #endif SetPriorityText(); } @@ -1215,6 +1320,8 @@ void CProgressDialog::UpdateMessagesDialog() } if (!messages.IsEmpty()) { + ProgressDialog_SetError(true); + FOR_VECTOR (i, messages) AddMessage(messages[i]); // SetColumnWidthAuto() can be slow for big number of files. @@ -1396,6 +1503,85 @@ void CProgressDialog::CopyToClipboard() } +bool CSysTray::LoadIcons(HINSTANCE hInst, int firstResId) +{ + if (Icons[0] != nullptr) return true; + + int id = firstResId; + for (auto &icon : Icons) + { + icon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); + id++; + } + + return Icons[0] != nullptr; +} + +void CSysTray::UpdateIcon(HWND dlg, UInt64 percentValue, bool addIcon, bool updateTip) +{ + const auto newIconId = static_cast((percentValue / kPercentPerIcon) % kNumIcons); + const bool updateIcon = newIconId > IconArrayId; + + if (updateIcon || updateTip || addIcon) + { + std::array tip; + wchar_t *p = ConvertUInt64ToString(percentValue, tip.data()); + *p++ = L'%'; + *p = 0; + + UINT flags = NIF_TIP; + if (updateIcon) + flags |= NIF_ICON; + + if (!SetSysTray(dlg, NIM_MODIFY, ID_SYSTRAY_ICON, flags, 0, Icons[newIconId], tip.data())) + { + SetSysTray(dlg, NIM_DELETE, ID_SYSTRAY_ICON, 0, 0, nullptr, nullptr); + SetSysTray(dlg, NIM_ADD, ID_SYSTRAY_ICON, NIF_ICON | NIF_MESSAGE | NIF_TIP, WM_TRAY_ICON_NOTIFY, + Icons[newIconId], tip.data()); + } + + IconArrayId = newIconId; + } +} + +bool CSysTray::BuildPopupMenu(LPCWSTR foregroundText, LPCWSTR pauseOrContinueText, LPCWSTR cancelText) +{ + if (Menu != nullptr) return true; + + Menu = CreatePopupMenu(); + AppendMenuW(Menu, MF_STRING, IDB_PROGRESS_BACKGROUND, foregroundText); + AppendMenuW(Menu, MF_STRING, IDB_PAUSE, pauseOrContinueText); + AppendMenuW(Menu, MF_STRING, IDCANCEL, cancelText); + return Menu != nullptr; +} + +bool CProgressDialog::OnTrayNotification(LPARAM lParam) +{ + switch (lParam) + { + case WM_RBUTTONUP: + if (_sysTray.BuildPopupMenu(_foreground_String, + Sync.Get_Paused() ? _continue_String : _pause_String, + cancelString)) + { + POINT point; + ::GetCursorPos(&point); + ::TrackPopupMenu(_sysTray.Menu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, point.x, point.y, 0, _window, nullptr); + // BUGFIX: see "PRB: Menus for Notification Icons Don't Work Correctly" + ::PostMessage(_window, WM_NULL, 0, 0); + } + break; + + case WM_LBUTTONUP: + OnPriorityButton(); + break; + + default: + break; + } + return false; +} + static THREAD_FUNC_DECL MyThreadFunction(void *param) { CProgressThreadVirt *p = (CProgressThreadVirt *)param; diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h index 60a5ca62a..527d6e895 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h @@ -3,6 +3,8 @@ #ifndef ZIP7_INC_PROGRESS_DIALOG_2_H #define ZIP7_INC_PROGRESS_DIALOG_2_H +#include + #include "../../../Common/MyCom.h" #include "../../../Windows/ErrorMsg.h" @@ -103,6 +105,26 @@ class CProgressSync }; +void ProgressDialog_SetError(bool error); +bool ProgressDialog_HadError(); + + +struct CSysTray +{ + static const int kNumIcons = 15; + static const int kPercentPerIcon = 7; + + std::array Icons{}; + int IconArrayId = -1; + HMENU Menu = nullptr; + + CSysTray() = default; + bool LoadIcons(HINSTANCE hInst, int firstResId); + void UpdateIcon(HWND dlg, UInt64 percentValue, bool addIcon, bool updateTip); + bool BuildPopupMenu(LPCWSTR foregroundText, LPCWSTR pauseOrContinueText, LPCWSTR cancelText); +}; + + class CProgressDialog: public NWindows::NControl::CModalDialog { bool _isDir; @@ -135,6 +157,7 @@ class CProgressDialog: public NWindows::NControl::CModalDialog UString _pause_String; UString _continue_String; UString _paused_String; + UString cancelString; int _buttonSizeX; int _buttonSizeY; @@ -143,6 +166,8 @@ class CProgressDialog: public NWindows::NControl::CModalDialog UString _title; + CSysTray _sysTray; + class CU64ToI32Converter { unsigned _numShiftBits; @@ -230,6 +255,7 @@ class CProgressDialog: public NWindows::NControl::CModalDialog void OnPriorityButton(); bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override; + bool OnTrayNotification(LPARAM lParam); void SetTitleText(); void ShowSize(unsigned id, UInt64 val, UInt64 &prev); @@ -265,7 +291,6 @@ class CProgressDialog: public NWindows::NControl::CModalDialog INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL); - /* how it works: 1) the working thread calls ProcessWasFinished() that sends kCloseMessage message to CProgressDialog (GUI) thread diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc index 4d0e0c7bf..f17a5dd73 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc @@ -1,6 +1,8 @@ #include "ProgressDialog2Res.h" #include "../../GuiCommon.rc" +#include "ProgressDialog2Icon.rc" + #undef DIALOG_ID #define DIALOG_ID IDD_PROGRESS #define xc 360 @@ -37,4 +39,5 @@ STRINGTABLE DISCARDABLE IDS_CONTINUE "&Continue" IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?" IDS_CLOSE "&Close" + IDS_CANCEL "&Cancel" } diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Icon.rc b/CPP/7zip/UI/FileManager/ProgressDialog2Icon.rc new file mode 100644 index 000000000..257220b1e --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2Icon.rc @@ -0,0 +1,19 @@ +#include "ProgressDialog2IconRes.h" + +IDI_SYSTRAY_0 ICON "../../UI/FileManager/trayico/tray00.ico" +IDI_SYSTRAY_1 ICON "../../UI/FileManager/trayico/tray01.ico" +IDI_SYSTRAY_2 ICON "../../UI/FileManager/trayico/tray02.ico" +IDI_SYSTRAY_3 ICON "../../UI/FileManager/trayico/tray03.ico" +IDI_SYSTRAY_4 ICON "../../UI/FileManager/trayico/tray04.ico" +IDI_SYSTRAY_5 ICON "../../UI/FileManager/trayico/tray05.ico" +IDI_SYSTRAY_6 ICON "../../UI/FileManager/trayico/tray06.ico" +IDI_SYSTRAY_7 ICON "../../UI/FileManager/trayico/tray07.ico" +IDI_SYSTRAY_8 ICON "../../UI/FileManager/trayico/tray08.ico" +IDI_SYSTRAY_9 ICON "../../UI/FileManager/trayico/tray09.ico" +IDI_SYSTRAY_10 ICON "../../UI/FileManager/trayico/tray10.ico" +IDI_SYSTRAY_11 ICON "../../UI/FileManager/trayico/tray11.ico" +IDI_SYSTRAY_12 ICON "../../UI/FileManager/trayico/tray12.ico" +IDI_SYSTRAY_13 ICON "../../UI/FileManager/trayico/tray13.ico" +IDI_SYSTRAY_14 ICON "../../UI/FileManager/trayico/tray14.ico" +//IDI_SYSTRAY_15 ICON "../../UI/FileManager/trayico/tray15.ico" +//IDI_SYSTRAY_16 ICON "../../UI/FileManager/trayico/tray16.ico" diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2IconRes.h b/CPP/7zip/UI/FileManager/ProgressDialog2IconRes.h new file mode 100644 index 000000000..3cb89efe6 --- /dev/null +++ b/CPP/7zip/UI/FileManager/ProgressDialog2IconRes.h @@ -0,0 +1,18 @@ +// Win32 resource IDs — must remain #define for rc.exe (cpp:S5028 N/A). +#define IDI_SYSTRAY_0 310 // NOSONAR +#define IDI_SYSTRAY_1 311 // NOSONAR +#define IDI_SYSTRAY_2 312 // NOSONAR +#define IDI_SYSTRAY_3 313 // NOSONAR +#define IDI_SYSTRAY_4 314 // NOSONAR +#define IDI_SYSTRAY_5 315 // NOSONAR +#define IDI_SYSTRAY_6 316 // NOSONAR +#define IDI_SYSTRAY_7 317 // NOSONAR +#define IDI_SYSTRAY_8 318 // NOSONAR +#define IDI_SYSTRAY_9 319 // NOSONAR +#define IDI_SYSTRAY_10 320 // NOSONAR +#define IDI_SYSTRAY_11 321 // NOSONAR +#define IDI_SYSTRAY_12 322 // NOSONAR +#define IDI_SYSTRAY_13 323 // NOSONAR +#define IDI_SYSTRAY_14 324 // NOSONAR +//#define IDI_SYSTRAY_15 325 +//#define IDI_SYSTRAY_16 326 diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h index 736c7179a..e06a75df2 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h +++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h @@ -3,6 +3,7 @@ #define IDS_CLOSE 408 #define IDS_CONTINUE 411 +#define IDS_CANCEL 415 // NOSONAR cpp:S5028 — Win32 rc.exe needs #define #define IDB_PROGRESS_BACKGROUND 444 #define IDS_PROGRESS_FOREGROUND 445 @@ -25,6 +26,7 @@ #define IDL_PROGRESS_MESSAGES 101 #define IDT_PROGRESS_FILE_NAME 102 #define IDT_PROGRESS_STATUS 103 +#define IDC_PROGRESS_PERCENT 104 // NOSONAR cpp:S5028 — Win32 rc.exe needs #define #define IDT_PROGRESS_PACKED_VAL 110 #define IDT_PROGRESS_FILES_VAL 111 diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc index dc7d797ff..b3605c75b 100644 --- a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc +++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc @@ -39,6 +39,7 @@ #define yc (z0 + z0s + bys) +#define percent_width 23 DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT CAPTION "Progress" @@ -75,7 +76,8 @@ CAPTION "Progress" RTEXT "", IDT_PROGRESS_RATIO_VAL, x3, y4, x3s, MY_TEXT_NOPREFIX LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX - CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s + CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc - percent_width, z2s + RTEXT "", IDC_PROGRESS_PERCENT, m + xc - percent_width, z2, percent_width, z2s, SS_NOPREFIX | SS_CENTERIMAGE CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp index bab209a02..59e601d63 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.cpp +++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp @@ -32,6 +32,8 @@ static LPCTSTR const kFolderHistoryValueName = TEXT("FolderHistory"); static LPCTSTR const kFastFoldersValueName = TEXT("FolderShortcuts"); static LPCTSTR const kCopyHistoryValueName = TEXT("CopyHistory"); +static LPCTSTR const kClose7ZipValueName = TEXT("Close7Zip"); + static NSynchronization::CCriticalSection g_CS; #define Set32(p, v) SetUi32(((Byte *)p), v) @@ -211,6 +213,21 @@ static bool ReadUi32Val(const TCHAR *name, UInt32 &value) return key.GetValue_UInt32_IfOk(name, value) == ERROR_SUCCESS; } +static void SaveBoolVal(const TCHAR *name, bool value) +{ + CKey key; + key.Create(HKEY_CURRENT_USER, kCUBasePath); + key.SetValue(name, value); +} + +static bool ReadBoolVal(const TCHAR *name, bool &value) +{ + CKey key; + if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS) + return false; + return key.GetValue_bool_IfOk(name, value) == ERROR_SUCCESS; +} + void SaveToolbarsMask(UInt32 toolbarMask) { SaveUi32Val(kToolbars, toolbarMask); @@ -330,3 +347,16 @@ void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s) i++; list.Insert(0, s); } + +void Save_Close7Zip(bool close7Zip) +{ + SaveBoolVal(kClose7ZipValueName, close7Zip); +} + +bool Read_Close7Zip() +{ + bool b; + if (!ReadBoolVal(kClose7ZipValueName, b)) + return false; + return b; +} diff --git a/CPP/7zip/UI/FileManager/ViewSettings.h b/CPP/7zip/UI/FileManager/ViewSettings.h index 02af0a155..eba0aac6d 100644 --- a/CPP/7zip/UI/FileManager/ViewSettings.h +++ b/CPP/7zip/UI/FileManager/ViewSettings.h @@ -112,4 +112,7 @@ void ReadCopyHistory(UStringVector &folders); void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s); +void Save_Close7Zip(bool close7Zip); +bool Read_Close7Zip(); + #endif diff --git a/CPP/7zip/UI/FileManager/trayico/tray00.ico b/CPP/7zip/UI/FileManager/trayico/tray00.ico new file mode 100644 index 000000000..8899fae6a Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray00.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray01.ico b/CPP/7zip/UI/FileManager/trayico/tray01.ico new file mode 100644 index 000000000..ac8c72051 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray01.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray02.ico b/CPP/7zip/UI/FileManager/trayico/tray02.ico new file mode 100644 index 000000000..0eb0d027e Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray02.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray03.ico b/CPP/7zip/UI/FileManager/trayico/tray03.ico new file mode 100644 index 000000000..7c6d19ff4 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray03.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray04.ico b/CPP/7zip/UI/FileManager/trayico/tray04.ico new file mode 100644 index 000000000..42953770f Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray04.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray05.ico b/CPP/7zip/UI/FileManager/trayico/tray05.ico new file mode 100644 index 000000000..e0419234f Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray05.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray06.ico b/CPP/7zip/UI/FileManager/trayico/tray06.ico new file mode 100644 index 000000000..ab2035591 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray06.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray07.ico b/CPP/7zip/UI/FileManager/trayico/tray07.ico new file mode 100644 index 000000000..38fec32cd Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray07.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray08.ico b/CPP/7zip/UI/FileManager/trayico/tray08.ico new file mode 100644 index 000000000..746de5612 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray08.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray09.ico b/CPP/7zip/UI/FileManager/trayico/tray09.ico new file mode 100644 index 000000000..5f9a865f7 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray09.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray10.ico b/CPP/7zip/UI/FileManager/trayico/tray10.ico new file mode 100644 index 000000000..8542a9b0a Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray10.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray11.ico b/CPP/7zip/UI/FileManager/trayico/tray11.ico new file mode 100644 index 000000000..c34cae78f Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray11.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray12.ico b/CPP/7zip/UI/FileManager/trayico/tray12.ico new file mode 100644 index 000000000..4105ed1f1 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray12.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray13.ico b/CPP/7zip/UI/FileManager/trayico/tray13.ico new file mode 100644 index 000000000..4f043eb1f Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray13.ico differ diff --git a/CPP/7zip/UI/FileManager/trayico/tray14.ico b/CPP/7zip/UI/FileManager/trayico/tray14.ico new file mode 100644 index 000000000..4788031d0 Binary files /dev/null and b/CPP/7zip/UI/FileManager/trayico/tray14.ico differ diff --git a/CPP/7zip/UI/GUI/ExtractDialog.cpp b/CPP/7zip/UI/GUI/ExtractDialog.cpp index 5ccac5aa3..80beec020 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.cpp +++ b/CPP/7zip/UI/GUI/ExtractDialog.cpp @@ -5,6 +5,7 @@ #include "../../../Common/StringConvert.h" #include "../../../Common/Wildcard.h" +#include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/ResourceString.h" @@ -15,13 +16,18 @@ #include "../FileManager/BrowseDialog.h" +#include "../FileManager/FormatUtils.h" #include "../FileManager/LangUtils.h" #include "../FileManager/resourceGui.h" +#include "../FileManager/ViewSettings.h" + #include "ExtractDialog.h" #include "ExtractDialogRes.h" #include "ExtractRes.h" +extern void FormatPathFreeSpace(UString &strPath, UString &strText); + using namespace NWindows; using namespace NFile; using namespace NName; @@ -135,6 +141,21 @@ void CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) #endif +static void StartApplication(const UString &dir, const UString &path) +{ + SHELLEXECUTEINFOW execInfo; + ZeroMemory(&execInfo, sizeof(execInfo)); + execInfo.cbSize = sizeof(execInfo); + execInfo.fMask = SEE_MASK_FLAG_DDEWAIT; + execInfo.hwnd = NULL; + execInfo.lpVerb = NULL; + execInfo.lpFile = path; + execInfo.lpParameters = NULL; + execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir; + execInfo.nShow = SW_SHOWNORMAL; + ShellExecuteExW(&execInfo); +} + bool CExtractDialog::OnInit() { #ifdef Z7_LANG @@ -161,6 +182,9 @@ bool CExtractDialog::OnInit() _pathName.Attach(GetItem(IDE_EXTRACT_NAME)); #endif + _freeSpace.Attach(GetItem(IDC_STATIC_EXTRACT_FREE_SPACE)); + _freeSpace.SetText(L""); + #ifdef Z7_NO_REGISTRY PathMode = NExtract::NPathMode::kFullPaths; @@ -210,6 +234,7 @@ bool CExtractDialog::OnInit() #endif _path.SetText(pathPrefix); + ShowPathFreeSpace(pathPrefix); #ifndef Z7_NO_REGISTRY for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++) @@ -261,6 +286,17 @@ bool CExtractDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND) case IDB_EXTRACT_SET_PATH: OnButtonSetPath(); return true; + + case IDC_EXTRACT_BUTTON_OPEN_PATH: + OnButtonOpenPath(); + return true; + +#ifndef Z7_SFX + case IDC_CHECK_DELETE_SOURCE_FILE: + DeleteSourceFile = IsButtonCheckedBool(IDC_CHECK_DELETE_SOURCE_FILE); + return true; +#endif + #ifndef Z7_SFX case IDX_EXTRACT_NAME_ENABLE: ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE)); @@ -287,6 +323,7 @@ void CExtractDialog::OnButtonSetPath() _path.SetCurSel(-1); #endif _path.SetText(resultPath); + ShowPathFreeSpace(resultPath); } void AddUniqueString(UStringVector &list, const UString &s); @@ -420,3 +457,62 @@ void CExtractDialog::OnHelp() CModalDialog::OnHelp(); } #endif + + +void CExtractDialog::OnButtonOpenPath() +{ + UString currentPath; + _path.GetText(currentPath); + + if (NFind::DoesDirExist_FollowLink(us2fs(currentPath))) + { + StartApplication(currentPath, currentPath); + } + else + { + const UString msg = MyFormatNew( + L"Folder \"{0}\" is not available yet.\n\n" + L"Note: the program will create the folder automatically when extracting.", + currentPath); + MessageBoxW(*this, msg, L"7-Zip", MB_ICONEXCLAMATION); + } +} + +void CExtractDialog::ShowPathFreeSpace(UString & strPath) +{ + UString strText; + FormatPathFreeSpace(strPath, strText); + _freeSpace.SetText(strText); +} + +bool CExtractDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam) +{ + if (itemID == IDC_EXTRACT_PATH) + { +#ifdef Z7_NO_REGISTRY + if (code == EN_CHANGE) +#else + if (code == CBN_EDITCHANGE) +#endif + { + UString strPath; + _path.GetText(strPath); + ShowPathFreeSpace(strPath); + return true; + } +#ifndef Z7_NO_REGISTRY + else if (code == CBN_SELCHANGE) + { + int nSel = _path.GetCurSel(); + if (nSel != CB_ERR) + { + UString strPath; + _path.GetLBText(nSel, strPath); + ShowPathFreeSpace(strPath); + } + return true; + } +#endif + } + return CModalDialog::OnCommand(code, itemID, lParam); +} diff --git a/CPP/7zip/UI/GUI/ExtractDialog.h b/CPP/7zip/UI/GUI/ExtractDialog.h index 1a3676b89..414f19b68 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.h +++ b/CPP/7zip/UI/GUI/ExtractDialog.h @@ -7,6 +7,7 @@ #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Edit.h" +#include "../../../Windows/Control/Static.h" #include "../Common/ExtractMode.h" @@ -45,12 +46,13 @@ class CExtractDialog: public NWindows::NControl::CModalDialog NWindows::NControl::CComboBox _pathMode; NWindows::NControl::CComboBox _overwriteMode; #endif + NWindows::NControl::CStatic _freeSpace; #ifndef Z7_SFX // int GetFilesMode() const; void UpdatePasswordControl(); #endif - + void OnButtonSetPath(); void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); @@ -58,15 +60,18 @@ class CExtractDialog: public NWindows::NControl::CModalDialog virtual bool OnInit() Z7_override; virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override; virtual void OnOK() Z7_override; - + void OnButtonOpenPath(); + bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam) Z7_override; + #ifndef Z7_NO_REGISTRY virtual void OnHelp() Z7_override; NExtract::CInfo _info; - + #endif - + + void ShowPathFreeSpace(UString & strPath); bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); } public: // bool _enableSelectedFilesButton; @@ -79,11 +84,13 @@ class CExtractDialog: public NWindows::NControl::CModalDialog #ifndef Z7_SFX UString Password; #endif - bool PathMode_Force; - bool OverwriteMode_Force; + bool PathMode_Force = false; + bool OverwriteMode_Force = false; NExtract::NPathMode::EEnum PathMode; NExtract::NOverwriteMode::EEnum OverwriteMode; + bool DeleteSourceFile = false; + #ifndef Z7_SFX // CBoolPair AltStreams; CBoolPair NtSecurity; @@ -102,9 +109,7 @@ class CExtractDialog: public NWindows::NControl::CModalDialog return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent); } - CExtractDialog(): - PathMode_Force(false), - OverwriteMode_Force(false) + CExtractDialog() { ElimDup.Val = true; } diff --git a/CPP/7zip/UI/GUI/ExtractDialog.rc b/CPP/7zip/UI/GUI/ExtractDialog.rc index fab199f59..8dc3d3adf 100644 --- a/CPP/7zip/UI/GUI/ExtractDialog.rc +++ b/CPP/7zip/UI/GUI/ExtractDialog.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 336 -#define yc 168 +#define yc 200 #undef g1xs #undef g2x @@ -18,6 +18,13 @@ #define g2xs (xc - g1xs - gSpace) #define g2xs2 (g2xs - m - m) +#define bxsOpen 30 +#define xsSpace 4 + +#define FREE_SPACE_Y 58 +#define EXTRA_Y_TOP 42 +#define EXTRA_Y_BOTTOM 58 + #undef GROUP_Y_SIZE #ifdef UNDER_CE #define GROUP_Y_SIZE 8 @@ -29,33 +36,36 @@ IDD_EXTRACT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT CAPTION "Extract" BEGIN LTEXT "E&xtract to:", IDT_EXTRACT_EXTRACT_TO, m, m, xc, 8 - COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - 12, 100, MY_COMBO_WITH_EDIT - PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots, m + 12 - 2, bxsDots, bys, WS_GROUP + COMBOBOX IDC_EXTRACT_PATH, m, m + 12, xc - bxsDots - xsSpace - bxsOpen - xsSpace, 160, MY_COMBO_WITH_EDIT + PUSHBUTTON "...", IDB_EXTRACT_SET_PATH, xs - m - bxsDots - xsSpace - bxsOpen, m + 12 - 1, bxsDots, bys-1, WS_GROUP + PUSHBUTTON "&Open", IDC_EXTRACT_BUTTON_OPEN_PATH, xs - m - bxsOpen, m + 12 - 1, bxsOpen, bys-1, WS_GROUP CONTROL "", IDX_EXTRACT_NAME_ENABLE, MY_CHECKBOX, m, m + 34, 12, 10 - EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, g1xs - 12 - 2, 14, ES_AUTOHSCROLL + EDITTEXT IDE_EXTRACT_NAME, m + 12 + 2, m + 32, xc - 12 - 2, 14, ES_AUTOHSCROLL - LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52, g1xs, 8 - COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64, g1xs, 140, MY_COMBO + LTEXT "", IDC_STATIC_EXTRACT_FREE_SPACE, m, FREE_SPACE_Y, xc, 8 + GROUPBOX "After extraction completes successfully", IDC_GUI_AFTER_EXTRACT, m, FREE_SPACE_Y + 12, xc, 27 + CONTROL "O&pen target folder", IDX_EXTRACT_OPEN_TRG_FLD, MY_CHECKBOX, 14, FREE_SPACE_Y + 24, 100, 10 + CONTROL "&Delete source archives", IDC_CHECK_DELETE_SOURCE_FILE, MY_CHECKBOX, 125, FREE_SPACE_Y + 24, 120, 10 - CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, - m, m + 84, g1xs, 10 + LTEXT "Path mode:", IDT_EXTRACT_PATH_MODE, m, m + 52 + EXTRA_Y_TOP, g1xs, 8 + COMBOBOX IDC_EXTRACT_PATH_MODE, m, m + 64 + EXTRA_Y_TOP, g1xs, 140, MY_COMBO - LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104, g1xs, 8 - COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116, g1xs, 140, MY_COMBO + CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, + m, m + 84 + EXTRA_Y_TOP, g1xs, 10 - CONTROL "Open target folder", IDX_EXTRACT_OPEN_TRG_FLD, MY_CHECKBOX, - g2x, m + 34, g2xs, 10 + LTEXT "Overwrite mode:", IDT_EXTRACT_OVERWRITE_MODE, m, m + 104 + EXTRA_Y_TOP, g1xs, 8 + COMBOBOX IDC_EXTRACT_OVERWRITE_MODE, m, m + 116 + EXTRA_Y_TOP, g1xs, 140, MY_COMBO - GROUPBOX "Password", IDG_PASSWORD, g2x, m + 50, g2xs, GROUP_Y_SIZE - EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 64, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL - CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 86, g2xs2, 10 + GROUPBOX "Password", IDG_PASSWORD, g2x, m + 36 + EXTRA_Y_BOTTOM, g2xs, GROUP_Y_SIZE + EDITTEXT IDE_EXTRACT_PASSWORD, g2x2, m + 50 + EXTRA_Y_BOTTOM, g2xs2, 14, ES_PASSWORD | ES_AUTOHSCROLL + CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, g2x2, m + 72 + EXTRA_Y_BOTTOM, g2xs2, 10 // CONTROL "Restore alternate data streams", IDX_EXTRACT_ALT_STREAMS, MY_CHECKBOX, -// g2x, m + 114, g2xs, 10 +// g2x, m + 104, g2xs, 10 CONTROL "Restore file security", IDX_EXTRACT_NT_SECUR, MY_CHECKBOX, - g2x, m + 114, g2xs, 10 - + g2x, m + 100 + EXTRA_Y_BOTTOM, g2xs, 10 + DEFPUSHBUTTON "OK", IDOK, bx3, by, bxs, bys, WS_GROUP PUSHBUTTON "Cancel", IDCANCEL, bx2, by, bxs, bys PUSHBUTTON "Help", IDHELP, bx1, by, bxs, bys @@ -93,7 +103,7 @@ BEGIN LTEXT "Password", IDG_PASSWORD, m, m + 76, g1xs, 8 EDITTEXT IDE_EXTRACT_PASSWORD, m + g1xs, m + 76, xc - g1xs, 14, ES_PASSWORD | ES_AUTOHSCROLL CONTROL "Show Password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, m + 92, xc, 10 - + OK_CANCEL END diff --git a/CPP/7zip/UI/GUI/ExtractDialogRes.h b/CPP/7zip/UI/GUI/ExtractDialogRes.h index f77267d6d..6c68af5dd 100644 --- a/CPP/7zip/UI/GUI/ExtractDialogRes.h +++ b/CPP/7zip/UI/GUI/ExtractDialogRes.h @@ -8,6 +8,12 @@ #define IDX_EXTRACT_OPEN_TRG_FLD 104 +// Win32 resource IDs — must remain #define for rc.exe (cpp:S5028 N/A). +#define IDC_EXTRACT_BUTTON_OPEN_PATH 105 // NOSONAR +#define IDC_STATIC_EXTRACT_FREE_SPACE 107 // NOSONAR +#define IDC_CHECK_DELETE_SOURCE_FILE 108 // NOSONAR +#define IDC_GUI_AFTER_EXTRACT 109 // NOSONAR + #define IDE_EXTRACT_PASSWORD 120 #define IDE_EXTRACT_NAME 130 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index 21e6c2c0c..c78d80b64 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -207,7 +207,10 @@ HRESULT ExtractGUI( CExtractCallbackImp *extractCallback, HWND hwndParent) { + bool deleteSourceFile = false; + messageWasDisplayed = false; + ProgressDialog_SetError(false); CThreadExtracting extracter; /* @@ -267,7 +270,9 @@ HRESULT ExtractGUI( options.OverwriteMode = dialog.OverwriteMode; options.PathMode = dialog.PathMode; options.ElimDup = dialog.ElimDup; - + + deleteSourceFile = dialog.DeleteSourceFile; + #ifndef Z7_SFX OpnTrgFold = dialog.OpnTrgFold.Val; // options.NtOptions.AltStreams = dialog.AltStreams; @@ -333,6 +338,12 @@ HRESULT ExtractGUI( RINOK(extracter.Create(title, hwndParent)) messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed; + if (extracter.ThreadFinishedOK && !ProgressDialog_HadError() && deleteSourceFile) + { + for (unsigned i = 0; i < archivePathsFull.Size(); i++) + DeleteFileIfArchive(us2fs(archivePathsFull[i])); + } + #ifndef Z7_SFX // browse/navigate to target path: if (OpnTrgFold && extracter.Result == S_OK) { diff --git a/CPP/Windows/Control/Dialog.cpp b/CPP/Windows/Control/Dialog.cpp index 5695ac577..e70d04568 100644 --- a/CPP/Windows/Control/Dialog.cpp +++ b/CPP/Windows/Control/Dialog.cpp @@ -97,6 +97,7 @@ bool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam); case WM_TIMER: return OnTimer(wParam, lParam); case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam)); + case WM_GETMINMAXINFO: return OnGetMinMaxInfo((PMINMAXINFO)lParam); case WM_DESTROY: return OnDestroy(); case WM_HELP: OnHelp(); return true; /* @@ -141,6 +142,14 @@ bool CDialog::OnButtonClicked(unsigned buttonID, HWND /* buttonHWND */) return true; } +void CDialog::Set_MinTrackSize_FromCurrent(int numX, int denX, int numY, int denY) +{ + RECT rc; + GetWindowRect(&rc); + _minTrackSize.cx = RECT_SIZE_X(rc) * numX / denX; + _minTrackSize.cy = RECT_SIZE_Y(rc) * numY / denY; +} + #ifndef UNDER_CE /* in win2000/win98 : monitor functions are supported. We need dynamic linking, if we want nt4/win95 support in program. diff --git a/CPP/Windows/Control/Dialog.h b/CPP/Windows/Control/Dialog.h index 2510c8f15..34f6948b8 100644 --- a/CPP/Windows/Control/Dialog.h +++ b/CPP/Windows/Control/Dialog.h @@ -15,10 +15,14 @@ namespace NControl { class CDialog: public CWindow { // Z7_CLASS_NO_COPY(CDialog) +private: + SIZE _minTrackSize; public: - CDialog(HWND wnd = NULL): CWindow(wnd) {} + explicit CDialog(HWND wnd = nullptr): CWindow(wnd) { _minTrackSize.cx = 0; _minTrackSize.cy = 0; } virtual ~CDialog() {} + void Set_MinTrackSize_FromCurrent(int numX, int denX, int numY, int denY); + HWND GetItem(unsigned itemID) const { return GetDlgItem(_window, (int)itemID); } @@ -129,6 +133,12 @@ class CDialog: public CWindow // virtual bool OnCommand2(WPARAM wParam, LPARAM lParam); virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam); virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; } + virtual bool OnGetMinMaxInfo(PMINMAXINFO pMMI) + { + if (_minTrackSize.cx > 0) pMMI->ptMinTrackSize.x = _minTrackSize.cx; + if (_minTrackSize.cy > 0) pMMI->ptMinTrackSize.y = _minTrackSize.cy; + return false; + } virtual bool OnDestroy() { return false; } /* diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index ad0d8c9dd..50a75227c 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp @@ -602,6 +602,15 @@ bool DeleteFileAlways(CFSTR path) } +bool DeleteFileIfArchive(CFSTR path) +{ + const DWORD attrib = NFind::GetFileAttrib(path); + if (attrib == INVALID_FILE_ATTRIBUTES + || (attrib & FILE_ATTRIBUTE_ARCHIVE) == 0) + return false; + return DeleteFileAlways(path); +} + bool RemoveDirWithSubItems(const FString &path) { @@ -1131,6 +1140,12 @@ bool DeleteFileAlways(CFSTR path) return (remove(path) == 0); } +bool DeleteFileIfArchive(CFSTR path) +{ + // POSIX has no ARCHIVE attribute; treat all regular files as candidates. + return DeleteFileAlways(path); +} + bool SetCurrentDir(CFSTR path) { return (chdir(path) == 0); diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 9ba98fcae..d2afa4397 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h @@ -88,6 +88,7 @@ bool CreateDir(CFSTR path); bool CreateComplexDir(CFSTR path); bool DeleteFileAlways(CFSTR name); +bool DeleteFileIfArchive(CFSTR path); bool RemoveDirWithSubItems(const FString &path); #ifdef _WIN32 bool RemoveDirAlways_if_Empty(const FString &path);