From 2e39205afb249626b24b1af2251297ff039a60ca Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Fri, 25 Dec 2009 18:28:30 +0100 Subject: Sanitize Overwrite and DirDelete dialog response values Also respect localized button accelerators --- UCore.pas | 12 ++-- UCoreUtils.pas | 10 +++ UCoreWorkers.pas | 198 +++++++++++++++++++++++++++---------------------------- UDirDelete.pas | 85 ++++++++++++++---------- UMain.pas | 4 +- UOverwrite.pas | 61 +++++++++-------- 6 files changed, 201 insertions(+), 169 deletions(-) diff --git a/UCore.pas b/UCore.pas index bd68d46..b4425c3 100644 --- a/UCore.pas +++ b/UCore.pas @@ -620,7 +620,7 @@ var AFSymLink: TFSymlink; try FDirDelete := TFDirDelete.Create(AFSymlink); FDirDelete.Caption := LANGDialogMakeSymlink; - FDirDelete.AddButtons(2); + FDirDelete.AddButtons(DIR_DELETE_SET_SYMLINK_ERROR); FDirDelete.Label1.Caption := LANGTheSymbolicLink; FDirDelete.Label2.Caption := NewName; FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]); @@ -631,7 +631,7 @@ var AFSymLink: TFSymlink; FDirDelete.Free; end; case Response of - 1 : Result := HandleCreateSymlink(OldName, NewName); + DIR_DELETE_RETRY : Result := HandleCreateSymlink(OldName, NewName); else Result := False; end; end; @@ -672,7 +672,7 @@ var Data: PDataItem; try FDirDelete := TFDirDelete.Create(AFSymlink); FDirDelete.Caption := LANGDialogEditSymlink; - FDirDelete.AddButtons(2); + FDirDelete.AddButtons(DIR_DELETE_SET_SYMLINK_ERROR); FDirDelete.Label1.Caption := LANGTheSymbolicLink; FDirDelete.Label2.Caption := StrToUTF8(ExistingName); FDirDelete.Label3.Caption := Format(LANGCouldNotBeDeletedS, [Error^.message]); @@ -683,7 +683,7 @@ var Data: PDataItem; FDirDelete.Free; end; case Response of - 1 : HandleEditSymlink(ExistingName, PointTo); + DIR_DELETE_RETRY : HandleEditSymlink(ExistingName, PointTo); end; Exit; end; @@ -694,7 +694,7 @@ var Data: PDataItem; try FDirDelete := TFDirDelete.Create(AFSymlink); FDirDelete.Caption := LANGDialogMakeSymlink; - FDirDelete.AddButtons(2); + FDirDelete.AddButtons(DIR_DELETE_SET_SYMLINK_ERROR); FDirDelete.Label1.Caption := LANGTheSymbolicLink; FDirDelete.Label2.Caption := StrToUTF8(ExistingName); FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]); @@ -705,7 +705,7 @@ var Data: PDataItem; FDirDelete.Free; end; case Response of - 1 : Result := HandleEditSymlink(ExistingName, PointTo); + DIR_DELETE_RETRY : Result := HandleEditSymlink(ExistingName, PointTo); else Result := False; end; end; diff --git a/UCoreUtils.pas b/UCoreUtils.pas index faf6eb5..c4e71a7 100644 --- a/UCoreUtils.pas +++ b/UCoreUtils.pas @@ -67,6 +67,8 @@ function MakeString(const Separator: string; var SubStrings: TOpenStringArray): procedure CopyArray(var src: TOpenStringArray; var dst: TOpenStringArray); procedure DeleteFromArray(Index: integer; var SubStrings: TOpenStringArray); +function ExtractAccelerator(const LabelText: string): string; + function ProcessPattern(Engine: TPanelEngine; Pattern, APath, FileName: string; const Directory: boolean): string; // Processess pattern with FileName located in APath and return destination path+filename @@ -974,6 +976,14 @@ begin end; end; +(********************************************************************************************************************************) +function ExtractAccelerator(const LabelText: string): string; +begin + Result := ''; + if (Pos('_', LabelText) > 0) and (Pos('_', LabelText) < Length(LabelText)) then + Result := Copy(LabelText, Pos('_', LabelText) + 1, 1); +end; + (********************************************************************************************************************************) function GetStrSize(s: string): Int64; var i: integer; diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas index a1e65ba..97077aa 100644 --- a/UCoreWorkers.pas +++ b/UCoreWorkers.pas @@ -20,7 +20,7 @@ unit UCoreWorkers; interface -uses glib2, gtk2, SyncObjs, Classes, GTKForms, GTKView, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore; +uses glib2, gtk2, SyncObjs, Classes, GTKForms, GTKView, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore, UDirDelete; type TWorkerThreadJobType = (WORKER_JOB_DUMMY, WORKER_JOB_DELETE, WORKER_JOB_COPY, WORKER_JOB_MOVE, WORKER_JOB_EXTRACT_TO_TEMP, @@ -99,17 +99,15 @@ type TVFSCallbackThread = class(TThread) procedure UpdateCaption1(const CaptionText: string); procedure UpdateCaption2(const CaptionText: string); - FDirDeleteButtonsType: integer; - FDirDeleteLabel1Text, FDirDeleteLabel2Text, FDirDeleteLabel3Text, FDirDeleteCaption: string; - FDirDeleteLabel2Visible, FDirDeleteLabel3Visible: boolean; - function ShowDirDeleteDialog(ButtonsType: integer; const Label1Text: string; const Label2Text: string = ''; - const Label3Text: string = ''; const DirDeleteCaption: string = ''): integer; + FDirDeleteButtonsType: TFDirDeleteButtonSet; + FDirDeleteTitle, FDirDeleteFileName: string; + FDirDeleteError: PGError; + function ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Title, FileName: string; Error: PGError): integer; - FOverwriteButtonsType: integer; - FOverwriteFromLabel, FOverwriteFromInfoLabel, FOverwriteToLabel, FOverwriteToInfoLabel, - FOverwriteRenameStr, FOverwriteSourceFile, FOverwriteDestFile: string; - function ShowOverwriteDialog(ButtonsType: integer; const FromLabel, FromInfoLabel, ToLabel, ToInfoLabel, RenameStr, - SourceFile, DestFile: string): integer; + FOverwriteShowAppend: boolean; + FOverwriteSourceItem, FOverwriteDestItem: PDataItem; + FOverwriteSourceFile, FOverwriteDestFile, FOverwriteRenameStr: string; + function ShowOverwriteDialog(ShowAppend: boolean; SourceItem, DestItem: PDataItem; const SourceFile, DestFile: string; var RenameStr: string): integer; FNewDirCaption, FNewDirLabel, FNewDirEdit: string; function ShowNewDirDialog(Caption, LabelCaption, Edit: string): integer; @@ -212,7 +210,7 @@ procedure ProcessThreadEvents(SenderThread: TVFSCallbackThread); implementation -uses SysUtils, DateUtils, StrUtils, UConfig, UDirDelete, UOverwrite, ULocale, +uses SysUtils, DateUtils, StrUtils, UConfig, UOverwrite, ULocale, UFileAssoc, UCoreClasses, URemoteWait, UMain, UGnome, UNewDir, UProgress, crc; @@ -511,38 +509,32 @@ begin FGUIMutex.Release; end; -function TWorkerThread.ShowDirDeleteDialog(ButtonsType: integer; const Label1Text: string; const Label2Text: string = ''; const Label3Text: string = ''; const DirDeleteCaption: string = ''): integer; +function TWorkerThread.ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Title, FileName: string; Error: PGError): integer; begin - FDialogResultDirDelete := integer(mbCancel); - FDirDeleteLabel1Text := Label1Text; - FDirDeleteLabel2Text := Label2Text; - FDirDeleteLabel3Text := Label3Text; - FDirDeleteLabel2Visible := Label2Text <> ''; - FDirDeleteLabel3Visible := Label3Text <> ''; + FDialogResultDirDelete := DIR_DELETE_CANCEL; + FDirDeleteTitle := Title; + FDirDeleteFileName := FileName; + FDirDeleteError := Error; FDirDeleteButtonsType := ButtonsType; - if DirDeleteCaption = '' then FDirDeleteCaption := LANGRemoveDirectory - else FDirDeleteCaption := DirDeleteCaption; FDialogShowDirDelete := True; FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultDirDelete; end; -function TWorkerThread.ShowOverwriteDialog(ButtonsType: integer; const FromLabel, FromInfoLabel, ToLabel, ToInfoLabel, RenameStr, SourceFile, DestFile: string): integer; +function TWorkerThread.ShowOverwriteDialog(ShowAppend: boolean; SourceItem, DestItem: PDataItem; const SourceFile, DestFile: string; var RenameStr: string): integer; begin - FDialogResultOverwrite := integer(mbCancel); - FOverwriteButtonsType := ButtonsType; - FOverwriteFromLabel := FromLabel; - FOverwriteFromInfoLabel := FromInfoLabel; - FOverwriteToLabel := ToLabel; - FOverwriteToInfoLabel := ToInfoLabel; - FOverwriteRenameStr := RenameStr; + FDialogResultOverwrite := OVERWRITE_CANCEL; + FOverwriteShowAppend := ShowAppend; + FOverwriteSourceItem := SourceItem; + FOverwriteDestItem := DestItem; FOverwriteSourceFile := SourceFile; FOverwriteDestFile := DestFile; FDialogShowOverwrite := True; FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultOverwrite; + RenameStr := FOverwriteRenameStr; end; function TWorkerThread.ShowNewDirDialog(Caption, LabelCaption, Edit: string): integer; @@ -604,6 +596,7 @@ var AFDirDelete: TFDirDelete; ParentDialogForm: TCustomGTKForm; b, ShowRemoteWait: boolean; StartTime: TDateTime; + InfoLabelFormat: string; begin DebugMsg([' ** ProcessThreadEvents --begin']); ShowRemoteWait := False; @@ -712,18 +705,16 @@ begin AFDirDelete := nil; try AFDirDelete := TFDirDelete.Create(ParentDialogForm); - AFDirDelete.Caption := FDirDeleteCaption; AFDirDelete.AddButtons(FDirDeleteButtonsType); - AFDirDelete.Label1.Caption := FDirDeleteLabel1Text; - AFDirDelete.Label2.Caption := FDirDeleteLabel2Text; - AFDirDelete.Label3.Caption := FDirDeleteLabel3Text; - AFDirDelete.Label2.Visible := FDirDeleteLabel2Visible; - AFDirDelete.Label3.Visible := FDirDeleteLabel3Visible; + AFDirDelete.Label1.Caption := FDirDeleteTitle; + AFDirDelete.Label2.Caption := FDirDeleteFileName; + if FDirDeleteError <> nil then + AFDirDelete.Label3.Caption := FDirDeleteError^.message; FDialogResultDirDelete := Integer(AFDirDelete.Run); - if (FDirDeleteButtonsType = 3) and (FDialogResultDirDelete = 2) and (JobType = WORKER_JOB_MOVE) + if (FDirDeleteButtonsType = DIR_DELETE_SET_COPY_ERROR) and (FDialogResultDirDelete = DIR_DELETE_IGNORE) and (JobType = WORKER_JOB_MOVE) then case Application.MessageBox(LANGIgnoreError, [mbYes, mbNo{, mbCancel}], mbWarning, mbYes, mbNo) of - mbNo: FDialogResultDirDelete := 1; - mbCancel: FDialogResultDirDelete := 0; + mbNo: FDialogResultDirDelete := DIR_DELETE_IGNORE; + mbCancel: FDialogResultDirDelete := DIR_DELETE_SKIP; end; finally AFDirDelete.Free; @@ -736,12 +727,16 @@ begin AFOverwrite := nil; try AFOverwrite := TFOverwrite.Create(ParentDialogForm); - AFOverwrite.AddButtons(FOverwriteButtonsType); - AFOverwrite.FromLabel.Caption := FOverwriteFromLabel; - AFOverwrite.FromInfoLabel.Caption := FOverwriteFromInfoLabel; - AFOverwrite.ToLabel.Caption := FOverwriteToLabel; - AFOverwrite.ToInfoLabel.Caption := FOverwriteToInfoLabel; - AFOverwrite.RenameStr := FOverwriteRenameStr; + AFOverwrite.AddButtons(FOverwriteShowAppend); + case ConfSizeFormat of + 5: InfoLabelFormat := '%s, %s'; + else InfoLabelFormat := LANGOvewriteSBytesS; + end; + AFOverwrite.FromLabel.Caption := Format(LANGOverwriteS, [StrToUTF8(FOverwriteSourceItem^.FDisplayName)]); + AFOverwrite.FromInfoLabel.Caption := Format(InfoLabelFormat, [FormatSize(FOverwriteSourceItem^.Size, 0), FormatDate(FOverwriteSourceItem^.mtime, True, True)]); + AFOverwrite.ToLabel.Caption := Format(LANGWithFileS, [StrToUTF8(FOverwriteDestItem^.FDisplayName)]); + AFOverwrite.ToInfoLabel.Caption := Format(InfoLabelFormat, [FormatSize(FOverwriteDestItem^.Size, 0), FormatDate(FOverwriteDestItem^.mtime, True, True)]); + AFOverwrite.RenameStr := ExtractFileName(FOverwriteDestFile); AFOverwrite.SourceFile := FOverwriteSourceFile; AFOverwrite.DestFile := FOverwriteDestFile; FDialogResultOverwrite := Integer(AFOverwrite.Run); @@ -788,8 +783,8 @@ begin with SenderThread as TWorkerThread do if FShowCancelMessage then begin if FCancelMessage = LANGUserCancelled - then Application.MessageBox(FCancelMessage, [mbOK], mbWarning, mbNone, mbOK) - else Application.MessageBox(FCancelMessage, [mbOK], mbError, mbNone, mbOK); + then Application.MessageBox(PGtkWindow(ParentDialogForm.FWidget), FCancelMessage, [mbOK], mbWarning, mbNone, mbOK) + else Application.MessageBox(PGtkWindow(ParentDialogForm.FWidget), FCancelMessage, [mbOK], mbError, mbNone, mbOK); end; // Close all dialogs @@ -830,20 +825,19 @@ var SkipAll: boolean; if not Res then if SkipAll then Result := True else begin - Response := ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName), - Format(LANGCouldNotBeDeletedS, [Error^.message])); + Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error deleting file/directory:', String(AFileRec^.DataItem^.FDisplayName), Error); + if Error <> nil then + g_error_free(Error); case Response of - 1 : Result := True; - 3 : begin + DIR_DELETE_SKIP : Result := True; + DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end; - 2 : Result := HandleDelete(AFileRec); + DIR_DELETE_RETRY : Result := HandleDelete(AFileRec); else Result := False; end; end; - if Error <> nil then - g_error_free(Error); end; var i: longint; @@ -886,12 +880,11 @@ begin if (not DeleteAll) and (PDataItemSL(AList[i])^.Level = 1) and PDataItemSL(AList[i])^.Stage1 and PDataItemSL(AList[i])^.DataItem^.IsDir and (not PDataItemSL(AList[i])^.DataItem^.IsLnk) and (i < AList.Count - 2) and (PDataItemSL(AList[i + 1])^.Level = 2) then begin - Response := ShowDirDeleteDialog(4, Format(LANGTheDirectorySIsNotEmpty, [string(PDataItemSL(AList[i])^.DataItem^.FDisplayName)]), - LANGDoYouWantToDeleteItWithAllItsFilesAndSubdirectories); + Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_NON_EMPTY, 'The directory is not empty, do you want to delete it with all its files and subdirectories?', string(PDataItemSL(AList[i])^.DataItem^.FDisplayName), nil); case Response of - 1 : ; // Do nothing in this case - I will not bother with changing the structure; it works :-) - 2 : DeleteAll := True; - 3 : SkipToNext := True; + DIR_DELETE_DELETE : ; // Do nothing in this case - I will not bother with changing the structure; it works :-) + DIR_DELETE_ALL : DeleteAll := True; + DIR_DELETE_SKIP : SkipToNext := True; else Break; end; end; @@ -965,18 +958,18 @@ end; if ErrorType <> 1 then s3 := StrToUTF8(FileName) else s3 := ''; - // * TODO: fix error string - case ShowDirDeleteDialog(3, s, s3, 'ahoj' { GetErrorString(ErrorNum)} , s2) of - 0, 252 : begin // Cancel button, Escape + // * TODO: fix error string, port to GError + case ShowDirDeleteDialog(DIR_DELETE_SET_COPY_ERROR, s, s3, nil) of + DIR_DELETE_CANCEL : begin Result := False; FCancelled := True; end; - 2 : Result := True; // Ignore - 3 : begin // Skip All + DIR_DELETE_IGNORE : Result := True; + DIR_DELETE_SKIP_ALL : begin FCopySkipAllErrors := True; { Skip All Err } Result := False; //** True? end; - else {1, 124, 255 :} Result := False; // Skip + else Result := False; // Skip end; end; end; @@ -1207,6 +1200,7 @@ var DefResponse: integer; // Global variables for this function Item: PDataItem; s, s1, s3, cap: string; FromInfoLabel, ToInfoLabel, InfoLabelFormat: string; + RenameStr: string; begin Result := True; try @@ -1258,7 +1252,8 @@ var DefResponse: integer; // Global variables for this function (not ((JobType = WORKER_JOB_MOVE) and (not TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, False)) and TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, True))) then begin Response := DefResponse; - // * TODO: check error + // * TODO: check error --> display dialog + // * TODO: should be SrcEngine? Item := DestEngine.GetFileInfo(NewFilePath, False, True, nil); if Item = nil then begin DebugMsg(['Something went terribly wrong during copy - Item := DestEngine.GetFileInfoSL(NewFilePath) == NULL!']); @@ -1270,47 +1265,42 @@ var DefResponse: integer; // Global variables for this function 5: InfoLabelFormat := '%s, %s'; else InfoLabelFormat := LANGOvewriteSBytesS; end; - FromInfoLabel := Format(InfoLabelFormat, [FormatSize(Item^.Size, 0), FormatDate(Item^.mtime, True, True)]); - ToInfoLabel := Format(InfoLabelFormat, [FormatSize(AFileRec^.DataItem^.Size, 0), FormatDate(AFileRec^.DataItem^.mtime, True, True)]); - Response := ShowOverwriteDialog(1 + Ord((JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP])), Format(LANGOverwriteS, [StrToUTF8(NewFilePath)]), FromInfoLabel, - Format(LANGWithFileS, [AFileRec^.DataItem^.FDisplayName]), ToInfoLabel, - ExtractFileName(StrToUTF8(NewFilePath)), ExtractFileName(AFileRec^.DataItem^.FDisplayName), ExtractFileName(StrToUTF8(NewFilePath))); - s := FOverwriteRenameStr; + RenameStr := ExtractFileName(NewFilePath); + Response := ShowOverwriteDialog(JobType in [WORKER_JOB_COPY], Item, AFileRec^.DataItem, NewFilePath, AFileRec^.DataItem^.FName, RenameStr); case Response of - // 1: Overwrite - // 3: Skip - 2 {Overwrite All}, 5 {Overwrite All Older}, 6 {Skip All}: DefResponse := Response; - 4 {Cancel}, 124 {Close Window}, 255: begin + // OVERWRITE_OVERWRITE + // OVERWRITE_SKIP + OVERWRITE_OVERWRITE_ALL, OVERWRITE_OVERWRITE_ALL_OLDER, OVERWRITE_SKIP_ALL: DefResponse := Response; + OVERWRITE_CANCEL, 124 {Close Window}, 255: begin Result := False; Exit; end; - 7: {Rename} begin - NewFilePath := Copy(NewFilePath, 1, LastDelimiter(PathDelim, NewFilePath)) + s; + OVERWRITE_RENAME: begin + NewFilePath := Copy(NewFilePath, 1, LastDelimiter(PathDelim, NewFilePath)) + RenameStr; Result := HandleCopy(AFileRec, NewFilePath); Exit; end; - 8 {Append}: begin + OVERWRITE_APPEND: begin Res := DoOperation(AFileRec, NewFilePath, ErrorKind, True); end; end; end; // Remove destination file if exists and should be overwritten - if (Response in [1, 2]) or ((Response = 5) and (Item^.mtime < AFileRec^.DataItem^.mtime)) then begin + if (Response in [OVERWRITE_OVERWRITE, OVERWRITE_OVERWRITE_ALL]) or ((Response = OVERWRITE_OVERWRITE_ALL_OLDER) and (Item^.mtime < AFileRec^.DataItem^.mtime)) then begin // * TODO: check error r := ord(DestEngine.Remove(NewFilePath, nil)); while r <> 0 do begin - // * TODO: check error - Res := ShowDirDeleteDialog(1, LANGTheFile, StrToUTF8(String(NewFilePath)), - Format(LANGCouldNotBeDeletedS, ['ahoj' {GetErrorString(r)}]), LANGCopyError); + // * TODO: check error, port to GError + Res := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'The file could not be deleted', StrToUTF8(String(NewFilePath)), nil); case Res of - 1: begin + DIR_DELETE_SKIP: begin Result := True; Exit; end; // * TODO: check error - 2: r := Ord(DestEngine.Remove(NewFilePath, nil)); - 0, 124, 255: begin + DIR_DELETE_RETRY: r := Ord(DestEngine.Remove(NewFilePath, nil)); + DIR_DELETE_CANCEL, 124, 255: begin Result := False; Exit; end; @@ -1351,11 +1341,11 @@ var DefResponse: integer; // Global variables for this function s3 := GetErrorString(ErrorKind); end; end; } - Response := ShowDirDeleteDialog(1, s1, StrToUTF8(String(NewFilePath)), s3, cap); + Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, s1, StrToUTF8(String(NewFilePath)), nil); case Response of - 1 : Result := True; // Skip - 2 : Result := HandleCopy(AFileRec, NewFilePath); // Retry - 3 : begin // Skip All + DIR_DELETE_SKIP : Result := True; // Skip + DIR_DELETE_RETRY : Result := HandleCopy(AFileRec, NewFilePath); // Retry + DIR_DELETE_SKIP_ALL : begin // Skip All SkipAll := True; Result := True; end; @@ -1968,6 +1958,7 @@ var SkipAll: boolean; function HandleChmod(AFileRec: PDataItemSL): boolean; var Response: integer; Res: boolean; + Error: PGError; begin Result := True; // DebugMsg(['Chmod Debug: IsDir: ', AFileRec^.IsDir, ', Stage1: ', AFileRec^.Stage1, ', IsLnk: ', AFileRec^.IsLnk, '; Result = ', AFileRec^.IsDir and AFileRec^.Stage1 and (not AFileRec^.IsLnk)]); @@ -1975,21 +1966,23 @@ var SkipAll: boolean; if (not AFileRec^.DataItem^.IsDir) and (ChmodRecurseType >= 0) and (ChmodRecurseType = 1) then Exit; // Directories only if AFileRec^.DataItem^.IsDir and (ChmodRecurseType >= 0) and (ChmodRecurseType = 2) then Exit; // Files only // * TODO: check error - Res := AEngine.Chmod(String(AFileRec^.DataItem^.FName), ChmodMode, nil); + Error := nil; + Res := AEngine.Chmod(String(AFileRec^.DataItem^.FName), ChmodMode, @Error); // DebugMsg(['Result : ', Res]); if not Res then if SkipAll then Result := True else begin // * TODO: check error - Response := ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName), Format(LANGCouldNotBeChmoddedS, - ['ahoj' {GetErrorString(Res)}]), LANGDialogChangePermissions); + Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing permissions', String(AFileRec^.DataItem^.FDisplayName), Error); + if Error <> nil then + g_error_free(Error); case Response of - 1 : Result := True; - 3 : begin + DIR_DELETE_SKIP : Result := True; + DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end; - 2 : Result := HandleChmod(AFileRec); + DIR_DELETE_RETRY : Result := HandleChmod(AFileRec); else Result := False; end; end; @@ -2042,27 +2035,30 @@ var SkipAll: boolean; function HandleChown(AFileRec: PDataItemSL): boolean; var Response: integer; Res: boolean; + Error: PGError; begin Result := True; // DebugMsg(['Chown Debug: IsDir: ', AFileRec^.IsDir, ', Stage1: ', AFileRec^.Stage1, ', IsLnk: ', AFileRec^.IsLnk, '; Result = ', AFileRec^.IsDir and AFileRec^.Stage1 and (not AFileRec^.IsLnk)]); if (AFileRec^.DataItem^.IsDir and ChownRecursive and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk)) or ((not AFileRec^.DataItem^.IsDir) and ChownRecursive) then Exit; // * TODO: check error - Res := AEngine.Chown(String(AFileRec^.DataItem^.FName), ChownUID, ChownGID, nil); + Error := nil; + Res := AEngine.Chown(String(AFileRec^.DataItem^.FName), ChownUID, ChownGID, @Error); // DebugMsg(['Result : ', Res]); if not Res then if SkipAll then Result := True else begin // * TODO: check error - Response := ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName), Format(LANGCouldNotBeChownedS, - ['ahoj' {GetErrorString(Res)}]), LANGDialogChangeOwner); + Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing owner', String(AFileRec^.DataItem^.FDisplayName), Error); + if Error <> nil then + g_error_free(Error); case Response of - 1 : Result := True; - 3 : begin + DIR_DELETE_SKIP : Result := True; + DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end; - 2 : Result := HandleChown(AFileRec); + DIR_DELETE_RETRY : Result := HandleChown(AFileRec); else Result := False; end; end; diff --git a/UDirDelete.pas b/UDirDelete.pas index 4fa9b5c..8d22d42 100644 --- a/UDirDelete.pas +++ b/UDirDelete.pas @@ -24,27 +24,41 @@ interface uses SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts; -type - TFDirDelete = class(TGTKDialog) - Label1, Label2, Label3: TGTKLabel; - procedure FormCreate(Sender: TObject); override; - procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); - public - procedure AddButtons(Sel: integer); - end; +const DIR_DELETE_CANCEL = 0; + DIR_DELETE_DELETE = 1; + DIR_DELETE_ALL = 2; + DIR_DELETE_RETRY = 3; + DIR_DELETE_SKIP = 4; + DIR_DELETE_SKIP_ALL = 5; + DIR_DELETE_IGNORE = 6; + +type TFDirDeleteButtonSet = (DIR_DELETE_SET_DELETE_ERROR, + DIR_DELETE_SET_SYMLINK_ERROR, + DIR_DELETE_SET_COPY_ERROR, + DIR_DELETE_SET_DELETE_NON_EMPTY); + + TFDirDelete = class(TGTKDialog) + Label1, Label2, Label3: TGTKLabel; + procedure FormCreate(Sender: TObject); override; + procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); + public + procedure AddButtons(ButtonSet: TFDirDeleteButtonSet); + end; + + var FDirDelete: TFDirDelete; implementation -uses ULocale; +uses gdk2, ULocale, UCoreUtils; procedure TFDirDelete.FormCreate(Sender: TObject); begin WindowPosition := wpCenter; - Caption := LANGRemoveDirectory; + Caption := ''; Label1 := TGTKLabel.Create(Self); Label1.Caption := 'The directory /tmp is not empty!'; Label2 := TGTKLabel.Create(Self); @@ -57,39 +71,44 @@ begin OnKeyDown := FormKeyDown; end; -procedure TFDirDelete.AddButtons(Sel: integer); +procedure TFDirDelete.AddButtons(ButtonSet: TFDirDeleteButtonSet); begin - case Sel of - 1 : begin - AddButton(LANGSkipButton_Caption, 1); - AddButton(LANGSkipAllButton_Caption, 3); - AddButton(LANGRetry, 2); - AddButton(LANGCancel, 0); + case ButtonSet of + DIR_DELETE_SET_DELETE_ERROR: begin + AddButton(LANGSkipButton_Caption, DIR_DELETE_SKIP); + AddButton(LANGSkipAllButton_Caption, DIR_DELETE_SKIP_ALL); + AddButton(LANGRetry, DIR_DELETE_RETRY); + AddButton(LANGCancel, DIR_DELETE_CANCEL); end; - 2 : begin - AddButton(LANGRetry, 1); - AddButton(LANGCancel, 0); + DIR_DELETE_SET_SYMLINK_ERROR: begin + AddButton(LANGRetry, DIR_DELETE_RETRY); + AddButton(LANGCancel, DIR_DELETE_CANCEL); end; - 3 : begin - AddButton(LANGSkipButton_Caption, 1); - AddButton(LANGSkipAllButton_Caption, 3); - AddButton(LANGIgnoreButton_Caption, 2); - AddButton(LANGCancel, 0); + DIR_DELETE_SET_COPY_ERROR: begin + AddButton(LANGSkipButton_Caption, DIR_DELETE_SKIP); + AddButton(LANGSkipAllButton_Caption, DIR_DELETE_SKIP_ALL); + AddButton(LANGIgnoreButton_Caption, DIR_DELETE_IGNORE); + AddButton(LANGCancel, DIR_DELETE_CANCEL); end; - 4 : begin - AddButton(LANGDeleteButton_Caption, 1); - AddButton(LANGAll, 2); - AddButton(LANGSkipButton_Caption, 3); - AddButton(LANGCancel, 0); + DIR_DELETE_SET_DELETE_NON_EMPTY: begin + AddButton(LANGDeleteButton_Caption, DIR_DELETE_DELETE); + AddButton(LANGAll, DIR_DELETE_ALL); + AddButton(LANGSkipButton_Caption, DIR_DELETE_SKIP); + AddButton(LANGCancel, DIR_DELETE_CANCEL); end; end; end; procedure TFDirDelete.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); begin - case Key of - GDK_ESCAPE: ModalResult := TMessageButton(255); - end; + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGSkipButton_Caption))))) then ModalResult := TMessageButton(DIR_DELETE_SKIP) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGSkipAllButton_Caption))))) then ModalResult := TMessageButton(DIR_DELETE_SKIP_ALL) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGRetry))))) then ModalResult := TMessageButton(DIR_DELETE_RETRY) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGCancel))))) then ModalResult := TMessageButton(DIR_DELETE_CANCEL) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGIgnoreButton_Caption))))) then ModalResult := TMessageButton(DIR_DELETE_IGNORE) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGDeleteButton_Caption))))) then ModalResult := TMessageButton(DIR_DELETE_DELETE) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGAll))))) then ModalResult := TMessageButton(DIR_DELETE_ALL) else + if (Key = GDK_ESCAPE) then ModalResult := TMessageButton(DIR_DELETE_CANCEL); end; diff --git a/UMain.pas b/UMain.pas index 868f3a5..e690e4b 100644 --- a/UMain.pas +++ b/UMain.pas @@ -259,12 +259,12 @@ var implementation uses ULibc, - UCore, UCoreWorkers, USelect, UNewDir, UDirDelete, UProgress, UCopyMove, + UCore, UCoreWorkers, USelect, UNewDir, UCopyMove, UCoreUtils, ULocale, UChecksum, UChecksumDruid, USplitFile, UFileTypeSettings, UFileAssoc, UChmod, UChown, USymlink, UPreferences, UViewer, UToolTips, UMounterPrefs, UColumns, UTestPlugin, UConnectionManager, USearch, UProperties, - URemoteWait, URunFromVFS, uVFSprototypes, UQuickConnect, + URunFromVFS, uVFSprototypes, UQuickConnect, UConnectionProperties, UError; diff --git a/UOverwrite.pas b/UOverwrite.pas index b35a197..78f057b 100644 --- a/UOverwrite.pas +++ b/UOverwrite.pas @@ -22,7 +22,16 @@ unit UOverwrite; interface uses - SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts; + gtk2, SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts; + +const OVERWRITE_CANCEL = 0; + OVERWRITE_OVERWRITE = 1; + OVERWRITE_OVERWRITE_ALL = 2; + OVERWRITE_SKIP = 3; + OVERWRITE_OVERWRITE_ALL_OLDER = 4; + OVERWRITE_SKIP_ALL = 5; + OVERWRITE_RENAME = 6; + OVERWRITE_APPEND = 7; type TFOverwrite = class(TGTKDialog) @@ -35,7 +44,7 @@ type procedure ButtonClick(Sender: TObject); public RenameStr, SourceFile, DestFile: string; - procedure AddButtons(Sel: integer); + procedure AddButtons(ShowAppend: boolean); procedure DoRename; procedure DoAppend; end; @@ -45,7 +54,7 @@ var implementation -uses ULocale, UCopyMove; +uses gdk2, ULocale, UCopyMove, UCoreUtils; procedure TFOverwrite.FormCreate(Sender: TObject); @@ -103,19 +112,18 @@ end; procedure TFOverwrite.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); begin - case Key of - GDK_O : ModalResult := TMessageButton(1); - GDK_A : ModalResult := TMessageButton(2); - GDK_S : ModalResult := TMessageButton(3); - GDK_C, GDK_ESCAPE : ModalResult := TMessageButton(4); - GDK_D : ModalResult := TMessageButton(5); - GDK_K : ModalResult := TMessageButton(6); - GDK_R : DoRename; - GDK_P : DoAppend; - end; + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGCancel))))) then ModalResult := TMessageButton(OVERWRITE_CANCEL) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGOverwriteButton_Caption))))) then ModalResult := TMessageButton(OVERWRITE_OVERWRITE) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGOverwriteAllButton_Caption))))) then ModalResult := TMessageButton(OVERWRITE_OVERWRITE_ALL) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGSkipButton_Caption))))) then ModalResult := TMessageButton(OVERWRITE_SKIP) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGOverwriteAllOlderButton_Caption))))) then ModalResult := TMessageButton(OVERWRITE_OVERWRITE_ALL_OLDER) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGSkipAllButton_Caption))))) then ModalResult := TMessageButton(OVERWRITE_SKIP_ALL) else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGRenameButton_Caption))))) then DoRename else + if (Key = gdk_keyval_to_lower(gdk_keyval_from_name(PChar(ExtractAccelerator(LANGAppendButton_Caption))))) then DoAppend else + if (Key = GDK_ESCAPE) then ModalResult := TMessageButton(OVERWRITE_CANCEL); end; -procedure TFOverwrite.AddButtons(Sel: integer); +procedure TFOverwrite.AddButtons(ShowAppend: boolean); begin ButtonTable.AddControl(0, 0, 1, 1, OverwriteButton, 0, 0); ButtonTable.AddControl(1, 0, 1, 1, OverwriteAllButton, 0, 0); @@ -124,19 +132,18 @@ begin ButtonTable.AddControl(1, 1, 1, 1, OverwriteAllOlderButton, 0, 0); ButtonTable.AddControl(2, 1, 1, 1, SkipAllButton, 0, 0); ButtonTable.AddControl(0, 2, 1, 1, RenameButton, 0, 0); - case Sel of - 2 : ButtonTable.AddControl(1, 2, 1, 1, AppendButton, 0, 0); - end; + if ShowAppend then + ButtonTable.AddControl(1, 2, 1, 1, AppendButton, 0, 0); end; procedure TFOverwrite.ButtonClick(Sender: TObject); begin - if Sender = OverwriteButton then ModalResult := TMessageButton(1) else - if Sender = OverwriteAllButton then ModalResult := TMessageButton(2) else - if Sender = SkipButton then ModalResult := TMessageButton(3) else - if Sender = CancelButton then ModalResult := TMessageButton(4) else - if Sender = OverwriteAllOlderButton then ModalResult := TMessageButton(5) else - if Sender = SkipAllButton then ModalResult := TMessageButton(6) else + if Sender = OverwriteButton then ModalResult := TMessageButton(OVERWRITE_OVERWRITE) else + if Sender = OverwriteAllButton then ModalResult := TMessageButton(OVERWRITE_OVERWRITE_ALL) else + if Sender = SkipButton then ModalResult := TMessageButton(OVERWRITE_SKIP) else + if Sender = CancelButton then ModalResult := TMessageButton(OVERWRITE_CANCEL) else + if Sender = OverwriteAllOlderButton then ModalResult := TMessageButton(OVERWRITE_OVERWRITE_ALL_OLDER) else + if Sender = SkipAllButton then ModalResult := TMessageButton(OVERWRITE_SKIP_ALL) else if Sender = RenameButton then DoRename else if Sender = AppendButton then DoAppend; end; @@ -149,10 +156,10 @@ begin AFCopyMove.Entry.Text := RenameStr; AFCopyMove.Caption := LANGRename; AFCopyMove.Label1.Caption := Format(LANGRenameFile, [RenameStr]); - AFCopyMove.Entry.SelectRegion(0, Length(AFCopyMove.Entry.Text)); + AFCopyMove.Entry.SelectAll; if AFCopyMove.Run = mbOK then begin RenameStr := AFCopyMove.Entry.Text; - ModalResult := TMessageButton(7); + ModalResult := TMessageButton(OVERWRITE_RENAME); end; finally AFCopyMove.Free; @@ -161,8 +168,8 @@ end; procedure TFOverwrite.DoAppend; begin - if Application.MessageBox(Format(LANGAppendQuestion, [SourceFile, DestFile]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes - then ModalResult := TMessageButton(8); + if Application.MessageBox(PGtkWindow(FWidget), Format(LANGAppendQuestion, [StrToUTF8(ExtractFileName(SourceFile)), StrToUTF8(ExtractFileName(DestFile))]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes + then ModalResult := TMessageButton(OVERWRITE_APPEND); end; -- cgit v1.2.3