diff options
Diffstat (limited to 'installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/PanelOperations.cpp')
-rw-r--r-- | installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/PanelOperations.cpp | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/PanelOperations.cpp b/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/PanelOperations.cpp new file mode 100644 index 000000000..5a0d052c4 --- /dev/null +++ b/installerbuilder/libinstaller/3rdparty/p7zip_9.04/unix/CPP/7zip/UI/FileManager/PanelOperations.cpp @@ -0,0 +1,470 @@ +// PanelOperations.cpp + +#include "StdAfx.h" + +#include "resource.h" + +#include "Panel.h" + +#include "Common/StringConvert.h" +#include "Common/DynamicBuffer.h" +#include "Windows/FileDir.h" +#include "Windows/ResourceString.h" +#include "Windows/Thread.h" +#include "Windows/COM.h" + +#include "ComboDialog.h" + +#include "FSFolder.h" +#include "LangUtils.h" +#include "FormatUtils.h" + +#include "UpdateCallback100.h" + +using namespace NWindows; +using namespace NFile; + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +enum EFolderOpType +{ + FOLDER_TYPE_CREATE_FOLDER = 0, + FOLDER_TYPE_DELETE = 1, + FOLDER_TYPE_RENAME = 2 +}; + +struct CThreadFolderOperations +{ + EFolderOpType OpType; + UString Name; + UInt32 Index; + CRecordVector<UInt32> Indices; + + CMyComPtr<IFolderOperations> FolderOperations; + CMyComPtr<IProgress> UpdateCallback; + CUpdateCallback100Imp *UpdateCallbackSpec; + HRESULT Result; + + CThreadFolderOperations(EFolderOpType opType); + + void Process() + { +#ifdef _WIN32 + NCOM::CComInitializer comInitializer; +#endif + UpdateCallbackSpec->ProgressDialog.WaitCreating(); + + switch(OpType) + { + case FOLDER_TYPE_CREATE_FOLDER: + Result = FolderOperations->CreateFolder(Name, UpdateCallback); + break; + case FOLDER_TYPE_DELETE: + Result = FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback); + break; + case FOLDER_TYPE_RENAME: + Result = FolderOperations->Rename(Index, Name, UpdateCallback); + break; + default: + Result = E_FAIL; + } + UpdateCallbackSpec->ProgressDialog.MyClose(); + } + + static THREAD_FUNC_DECL MyThreadFunction(void *param) + { + ((CThreadFolderOperations *)param)->Process(); + return 0; + } +}; + +CThreadFolderOperations::CThreadFolderOperations(EFolderOpType opType): OpType(opType) {}; + +static void DoOperation(CThreadFolderOperations &op, CPanel &panel, const UString &progressTitle) +{ + op.UpdateCallbackSpec = new CUpdateCallback100Imp; + op.UpdateCallback = op.UpdateCallbackSpec; + + bool usePassword = false; + UString password; + if (panel._parentFolders.Size() > 0) + { + const CFolderLink &fl = panel._parentFolders.Back(); + usePassword = fl.UsePassword; + password = fl.Password; + } + + op.UpdateCallbackSpec->Init(panel.GetParent(), usePassword, password); + + op.UpdateCallbackSpec->ProgressDialog.MainWindow = panel._mainWindow; + op.UpdateCallbackSpec->ProgressDialog.MainTitle = LangString(IDS_APP_TITLE, 0x03000000); + op.UpdateCallbackSpec->ProgressDialog.MainAddTitle = progressTitle + UString(L" "); + + // op.FolderOperations = folderOperations; + // op.Index = realIndex; + // op.Name = newName; + // HRESULT result = folderOperations->Rename(realIndex, newName, 0); + + NWindows::CThread thread; + if (thread.Create(CThreadFolderOperations::MyThreadFunction, &op) != S_OK) + throw 271824; + op.UpdateCallbackSpec->StartProgressDialog(progressTitle); +} + +#ifndef _UNICODE +typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp); +#endif + +void CPanel::DeleteItems(bool toRecycleBin) +{ + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CRecordVector<UInt32> indices; + GetOperatedItemIndices(indices); + if (indices.IsEmpty()) + return; + CSelectedState state; + SaveSelectedState(state); + bool useInternalDelete = false; + if (IsFSFolder() && toRecycleBin) + { + #ifndef _UNICODE + if (!g_IsNT) + { + CDynamicBuffer<CHAR> buffer; + size_t size = 0; + for (int i = 0; i < indices.Size(); i++) + { + const AString path = GetSystemString(GetFsPath() + GetItemRelPath(indices[i])); + buffer.EnsureCapacity(size + path.Length() + 1); + memmove(((CHAR *)buffer) + size, (const CHAR *)path, (path.Length() + 1) * sizeof(CHAR)); + size += path.Length() + 1; + } + buffer.EnsureCapacity(size + 1); + ((CHAR *)buffer)[size] = 0; + SHFILEOPSTRUCTA fo; + fo.hwnd = GetParent(); + fo.wFunc = FO_DELETE; + fo.pFrom = (const CHAR *)buffer; + fo.pTo = 0; + fo.fFlags = 0; + if (toRecycleBin) + fo.fFlags |= FOF_ALLOWUNDO; + // fo.fFlags |= FOF_NOCONFIRMATION; + // fo.fFlags |= FOF_NOERRORUI; + // fo.fFlags |= FOF_SILENT; + // fo.fFlags |= FOF_WANTNUKEWARNING; + fo.fAnyOperationsAborted = FALSE; + fo.hNameMappings = 0; + fo.lpszProgressTitle = 0; + /* int res = */ ::SHFileOperationA(&fo); + } + else + #endif + { + CDynamicBuffer<WCHAR> buffer; + size_t size = 0; + int maxLen = 0; + for (int i = 0; i < indices.Size(); i++) + { + // L"\\\\?\\") doesn't work here. + const UString path = GetFsPath() + GetItemRelPath(indices[i]); + if (path.Length() > maxLen) + maxLen = path.Length(); + buffer.EnsureCapacity(size + path.Length() + 1); + memmove(((WCHAR *)buffer) + size, (const WCHAR *)path, (path.Length() + 1) * sizeof(WCHAR)); + size += path.Length() + 1; + } + buffer.EnsureCapacity(size + 1); + ((WCHAR *)buffer)[size] = 0; +#ifdef _WIN32 + if (maxLen >= MAX_PATH) + { + if (toRecycleBin) + { + MessageBoxErrorLang(IDS_ERROR_LONG_PATH_TO_RECYCLE, 0x03020218); + return; + } + useInternalDelete = true; + } + else + { + SHFILEOPSTRUCTW fo; + fo.hwnd = GetParent(); + fo.wFunc = FO_DELETE; + fo.pFrom = (const WCHAR *)buffer; + fo.pTo = 0; + fo.fFlags = 0; + if (toRecycleBin) + fo.fFlags |= FOF_ALLOWUNDO; + fo.fAnyOperationsAborted = FALSE; + fo.hNameMappings = 0; + fo.lpszProgressTitle = 0; + int res; + #ifdef _UNICODE + res = ::SHFileOperationW(&fo); + #else + SHFileOperationWP shFileOperationW = (SHFileOperationWP) + ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW"); + if (shFileOperationW == 0) + return; + res = shFileOperationW(&fo); + #endif + } +#else + // FIXME - how to use the recycle bin undex Gnome or KDE ? + useInternalDelete = true; +#endif + } + /* + if (fo.fAnyOperationsAborted) + MessageBoxError(result, LangString(IDS_ERROR_DELETING, 0x03020217)); + */ + } + else + useInternalDelete = true; + if (useInternalDelete) + DeleteItemsInternal(indices); + RefreshListCtrl(state); +} + +void CPanel::DeleteItemsInternal(CRecordVector<UInt32> &indices) +{ + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + UString title; + UString message; + if (indices.Size() == 1) + { + int index = indices[0]; + const UString itemName = GetItemRelPath(index); + if (IsItemFolder(index)) + { + title = LangString(IDS_CONFIRM_FOLDER_DELETE, 0x03020211); + message = MyFormatNew(IDS_WANT_TO_DELETE_FOLDER, 0x03020214, itemName); + } + else + { + title = LangString(IDS_CONFIRM_FILE_DELETE, 0x03020210); + message = MyFormatNew(IDS_WANT_TO_DELETE_FILE, 0x03020213, itemName); + } + } + else + { + title = LangString(IDS_CONFIRM_ITEMS_DELETE, 0x03020212); + message = MyFormatNew(IDS_WANT_TO_DELETE_ITEMS, 0x03020215, + NumberToString(indices.Size())); + } + if (::MessageBoxW(GetParent(), message, title, MB_OKCANCEL | MB_ICONQUESTION) != IDOK) + return; + + { + CThreadFolderOperations op(FOLDER_TYPE_DELETE); + op.FolderOperations = folderOperations; + op.Indices = indices; + DoOperation(op, *this, LangString(IDS_DELETING, 0x03020216)); + if (op.Result != S_OK) + MessageBoxError(op.Result, LangString(IDS_ERROR_DELETING, 0x03020217)); + } + RefreshTitleAlways(); +} + +#ifdef _WIN32 +BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh) +{ + int realIndex = GetRealIndex(lpnmh->item); + if (realIndex == kParentIndex) + return TRUE; + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + return TRUE; + return FALSE; +} + +BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh) +{ + if (lpnmh->item.pszText == NULL) + return FALSE; + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return FALSE; + } + const UString newName = lpnmh->item.pszText; + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + + SaveSelectedState(_selectedState); + + int realIndex = GetRealIndex(lpnmh->item); + if (realIndex == kParentIndex) + return FALSE; + const UString prefix = GetItemPrefix(realIndex); + + + { + CThreadFolderOperations op(FOLDER_TYPE_RENAME); + op.FolderOperations = folderOperations; + op.Index = realIndex; + op.Name = newName; + DoOperation(op, *this, LangString(IDS_RENAMING, 0x03020220)); + if (op.Result != S_OK) + { + MessageBoxError(op.Result, LangString(IDS_ERROR_RENAMING, 0x03020221)); + return FALSE; + } + } + + // Can't use RefreshListCtrl here. + // RefreshListCtrlSaveFocused(); + _selectedState.FocusedName = prefix + newName; + _selectedState.SelectFocused = true; + + // We need clear all items to disable GetText before Reload: + // number of items can change. + // _listView.DeleteAllItems(); + // But seems it can still call GetText (maybe for current item) + // so we can't delete items. + + _dontShowMode = true; + + PostMessage(kReLoadMessage); + return TRUE; +} +#endif + +void CPanel::CreateFolder() +{ + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CSelectedState state; + SaveSelectedState(state); + CComboDialog comboDialog; + comboDialog.Title = LangString(IDS_CREATE_FOLDER, 0x03020230); + comboDialog.Static = LangString(IDS_CREATE_FOLDER_NAME, 0x03020231); + comboDialog.Value = LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, /*0x03020232*/ (UInt32)-1); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + + UString newName = comboDialog.Value; + + { + CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER); + op.FolderOperations = folderOperations; + op.Name = newName; + DoOperation(op, *this, LangString(IDS_CREATE_FOLDER, 0x03020230)); + + if (op.Result != S_OK) + { + MessageBoxError(op.Result, LangString(IDS_CREATE_FOLDER_ERROR, 0x03020233)); + return; + } + } + int pos = newName.Find(L'\\'); + if (pos >= 0) + newName = newName.Left(pos); + if (!_mySelectMode) + state.SelectedNames.Clear(); + state.FocusedName = newName; + state.SelectFocused = true; + RefreshTitleAlways(); + RefreshListCtrl(state); +} + +void CPanel::CreateFile() +{ + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + CSelectedState state; + SaveSelectedState(state); + CComboDialog comboDialog; + comboDialog.Title = LangString(IDS_CREATE_FILE, 0x03020240); + comboDialog.Static = LangString(IDS_CREATE_FILE_NAME, 0x03020241); + comboDialog.Value = LangString(IDS_CREATE_FILE_DEFAULT_NAME, /*0x03020242*/ (UInt32)-1); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + UString newName = comboDialog.Value; + HRESULT result = folderOperations->CreateFile(newName, 0); + if (result != S_OK) + { + MessageBoxError(result, LangString(IDS_CREATE_FILE_ERROR, 0x03020243)); + return; + } + int pos = newName.Find(L'\\'); + if (pos >= 0) + newName = newName.Left(pos); + if (!_mySelectMode) + state.SelectedNames.Clear(); + state.FocusedName = newName; + state.SelectFocused = true; + RefreshListCtrl(state); +} + +void CPanel::RenameFile() +{ + int index = _listView.GetFocusedItem(); + if (index >= 0) + _listView.EditLabel(index); +} + +void CPanel::ChangeComment() +{ + CPanel::CDisableTimerProcessing disableTimerProcessing2(*this); + int index = _listView.GetFocusedItem(); + if (index < 0) + return; + int realIndex = GetRealItemIndex(index); + if (realIndex == kParentIndex) + return; + CSelectedState state; + SaveSelectedState(state); + CMyComPtr<IFolderOperations> folderOperations; + if (_folder.QueryInterface(IID_IFolderOperations, &folderOperations) != S_OK) + { + MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); + return; + } + + UString comment; + { + NCOM::CPropVariant propVariant; + if (_folder->GetProperty(realIndex, kpidComment, &propVariant) != S_OK) + return; + if (propVariant.vt == VT_BSTR) + comment = propVariant.bstrVal; + else if (propVariant.vt != VT_EMPTY) + return; + } + UString name = GetItemRelPath(realIndex); + CComboDialog comboDialog; + comboDialog.Title = name + L" " + LangString(IDS_COMMENT, 0x03020290); + comboDialog.Value = comment; + comboDialog.Static = LangString(IDS_COMMENT2, 0x03020291); + if (comboDialog.Create(GetParent()) == IDCANCEL) + return; + NCOM::CPropVariant propVariant(comboDialog.Value); + + HRESULT result = folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL); + if (result != S_OK) + { + MessageBoxError(result, L"Set Comment Error"); + } + RefreshListCtrl(state); +} + |