View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001536 | Double Commander | Graphical user interface | public | 2016-09-19 02:22 | 2021-09-05 15:10 |
| Reporter | cordylus | Assigned To | Alexx2000 | ||
| Priority | normal | Severity | feature | Reproducibility | always |
| Status | closed | Resolution | fixed | ||
| Projection | none | ETA | none | ||
| Product Version | 0.7.5 | ||||
| Target Version | 0.9.0 | Fixed in Version | 0.9.0 | ||
| Summary | 0001536: Добавить "Сравнить" в диалог "Заменить ... файлом ...?" | ||||
| Description | Диалог, который открывается при попытке скопировать или переместить файл, когда в месте назначения уже есть файл с таким именем. | ||||
| Tags | No tags attached. | ||||
| Attached Files | bug1536-preview1.patch (50,831 bytes)
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -75,7 +73,13 @@
procedure TfrmMsg.ButtonClick(Sender: TObject);
begin
iSelected:= (Sender as TComponent).Tag;
- Close;
+ if (iSelected < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(iSelected);
+ end
+ else
+ Close;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +88,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview2.patch (51,687 bytes)
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -75,7 +73,13 @@
procedure TfrmMsg.ButtonClick(Sender: TObject);
begin
iSelected:= (Sender as TComponent).Tag;
- Close;
+ if (iSelected < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(iSelected);
+ end
+ else
+ Close;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +88,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview3.patch (52,019 bytes)
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,12 +17,11 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
+ procedure HandleAction(aTag: PtrInt);
procedure ButtonClick(Sender:TObject);
procedure ButtonOtherClick(Sender:TObject);
procedure MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -44,7 +43,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -72,10 +71,23 @@
end;
end;
+procedure TfrmMsg.HandleAction(aTag: PtrInt);
+begin
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
+end;
+
procedure TfrmMsg.ButtonClick(Sender: TObject);
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ HandleAction((Sender as TComponent).Tag);
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +96,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ HandleAction((Sender as TButton).Tag);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview4.patch (52,018 bytes)
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +683,7 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ OperationsManager.AddOperationModal(Operation);
Exit(pdrInCallback);
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview5.patch (52,919 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -269,7 +269,7 @@
FWaitData := WaitData;
edtFileNameLeft.Text:= FileNameLeft;
edtFileNameRight.Text:= FileNameRight;
- FShowIdentical:= actAutoCompare.Checked;
+ FShowIdentical:= False;//actAutoCompare.Checked;
actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
if actBinaryCompare.Checked then
actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ ShowModal;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +683,7 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ OperationsManager.AddOperationModal(Operation);
Exit(pdrInCallback);
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview6.patch (56,556 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -269,7 +269,7 @@
FWaitData := WaitData;
edtFileNameLeft.Text:= FileNameLeft;
edtFileNameRight.Text:= FileNameRight;
- FShowIdentical:= actAutoCompare.Checked;
+ FShowIdentical:= False;//actAutoCompare.Checked;
actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
if actBinaryCompare.Checked then
actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ ShowModal;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -39,7 +39,7 @@
function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
class function CreateFile(const APath: String): TFile; override;
- class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+ class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
procedure Reload(const PathsToReload: TPathsArray); override;
function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
end;
end;
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
- AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+ AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
var
AFile: PGFile;
ATarget: Pgchar;
AFileType: TGFileType;
ASymlinkInfo: PGFileInfo;
+ OwnFolder: Boolean = False;
begin
Result:= CreateFile(APath);
Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
end
else if AFileType = G_FILE_TYPE_SYMBOLIC_LINK then
begin
+ if not Assigned(AFolder) then
+ begin
+ AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+ OwnFolder:= True;
+ end;
+
ATarget:= g_file_info_get_symlink_target(AFileInfo);
AFile:= g_file_get_child(AFolder, ATarget);
@@ -143,6 +150,8 @@
g_object_unref(ASymlinkInfo);
end;
g_object_unref(PGObject(AFile));
+ if OwnFolder then
+ g_object_unref(PGObject(AFolder));
end
else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetInfo: PGFileInfo;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +112,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
if (aFileName <> '.') and (aFileName <> '..') then
begin
- aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
NewFiles.Add(aFile);
if aFile.IsLink then
@@ -270,7 +277,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
g_object_unref(AInfo);
AddItem(aFile, CurrentNode);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,29 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ TargetFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo);
+ try
+ ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+ finally
+ TargetFile.Free;
+ end;
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +741,12 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetInfo := aTargetInfo;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +857,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +867,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas (revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas (working copy)
@@ -72,7 +72,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
g_object_unref(AInfo);
FFiles.Add(AFile);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -669,6 +669,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +683,7 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ OperationsManager.AddOperationModal(Operation);
Exit(pdrInCallback);
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview7.patch (58,133 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -269,7 +269,7 @@
FWaitData := WaitData;
edtFileNameLeft.Text:= FileNameLeft;
edtFileNameRight.Text:= FileNameRight;
- FShowIdentical:= actAutoCompare.Checked;
+ FShowIdentical:= False;//actAutoCompare.Checked;
actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
if actBinaryCompare.Checked then
actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ ShowModal;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -39,7 +39,7 @@
function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
class function CreateFile(const APath: String): TFile; override;
- class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+ class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
procedure Reload(const PathsToReload: TPathsArray); override;
function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
end;
end;
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
- AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+ AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
var
AFile: PGFile;
ATarget: Pgchar;
AFileType: TGFileType;
ASymlinkInfo: PGFileInfo;
+ OwnFolder: Boolean = False;
begin
Result:= CreateFile(APath);
Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
end
else if AFileType = G_FILE_TYPE_SYMBOLIC_LINK then
begin
+ if not Assigned(AFolder) then
+ begin
+ AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+ OwnFolder:= True;
+ end;
+
ATarget:= g_file_info_get_symlink_target(AFileInfo);
AFile:= g_file_get_child(AFolder, ATarget);
@@ -143,6 +150,8 @@
g_object_unref(ASymlinkInfo);
end;
g_object_unref(PGObject(AFile));
+ if OwnFolder then
+ g_object_unref(PGObject(AFolder));
end
else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetInfo: PGFileInfo;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +112,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
if (aFileName <> '.') and (aFileName <> '..') then
begin
- aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
NewFiles.Add(aFile);
if aFile.IsLink then
@@ -270,7 +277,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
g_object_unref(AInfo);
AddItem(aFile, CurrentNode);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ TargetFileSource: IFileSource;
+ TargetFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ if FOperation is TFileSourceCopyOperation then
+ TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+ else
+ TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+ if TargetFileSource is TGioFileSource then
+ TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+ else
+ begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+ TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+ end;
+
+ try
+ ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+ finally
+ TargetFile.Free;
+ end;
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +754,12 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetInfo := aTargetInfo;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +870,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas (revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas (working copy)
@@ -72,7 +72,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
g_object_unref(AInfo);
FFiles.Add(AFile);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -267,6 +267,10 @@
procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
begin
+ writeln('--------------- differ: --------------------');
+ writeln(CompareList[0]);
+ writeln(CompareList[1]);
+ writeln('--------------- /differ --------------------');
if gExternalTools[etDiffer].Enabled then
begin
if Assigned(WaitData) then
@@ -669,6 +673,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +687,7 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ OperationsManager.AddOperationModal(Operation);
Exit(pdrInCallback);
end;
@@ -792,6 +798,19 @@
var
I: Integer;
begin
+ writeln('----------- prepare files: ----------------');
+ writeln('--------------- file 1 --------------------');
+ writeln(FileSource1.ClassName);
+ writeln(SelectedFiles1[0].FullPath);
+ writeln(SelectedFiles1[0].Path);
+ writeln(SelectedFiles1[0].Name);
+ writeln('--------------- file 2 --------------------');
+ writeln(FileSource2.ClassName);
+ writeln(SelectedFiles2[0].FullPath);
+ writeln(SelectedFiles2[0].Path);
+ writeln(SelectedFiles2[0].Name);
+ writeln('--------------- /files --------------------');
+
case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
pdrSynchronous:
begin
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview8.patch (58,159 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -269,7 +269,7 @@
FWaitData := WaitData;
edtFileNameLeft.Text:= FileNameLeft;
edtFileNameRight.Text:= FileNameRight;
- FShowIdentical:= actAutoCompare.Checked;
+ FShowIdentical:= False;//actAutoCompare.Checked;
actBinaryCompare.Checked:= not (FileIsText(FileNameLeft) and FileIsText(FileNameRight));
if actBinaryCompare.Checked then
actBinaryCompareExecute(actBinaryCompare)
@@ -278,7 +278,8 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ //if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ ShowModal;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -39,7 +39,7 @@
function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
class function CreateFile(const APath: String): TFile; override;
- class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+ class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
procedure Reload(const PathsToReload: TPathsArray); override;
function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
end;
end;
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
- AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+ AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
var
AFile: PGFile;
ATarget: Pgchar;
AFileType: TGFileType;
ASymlinkInfo: PGFileInfo;
+ OwnFolder: Boolean = False;
begin
Result:= CreateFile(APath);
Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
end
else if AFileType = G_FILE_TYPE_SYMBOLIC_LINK then
begin
+ if not Assigned(AFolder) then
+ begin
+ AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+ OwnFolder:= True;
+ end;
+
ATarget:= g_file_info_get_symlink_target(AFileInfo);
AFile:= g_file_get_child(AFolder, ATarget);
@@ -143,6 +150,8 @@
g_object_unref(ASymlinkInfo);
end;
g_object_unref(PGObject(AFile));
+ if OwnFolder then
+ g_object_unref(PGObject(AFolder));
end
else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetInfo: PGFileInfo;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +112,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceMoveOperation,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
if (aFileName <> '.') and (aFileName <> '..') then
begin
- aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
NewFiles.Add(aFile);
if aFile.IsLink then
@@ -270,7 +277,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
g_object_unref(AInfo);
AddItem(aFile, CurrentNode);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ TargetFileSource: IFileSource;
+ TargetFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ if FOperation is TFileSourceCopyOperation then
+ TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+ else
+ TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+ if TargetFileSource is TGioFileSource then
+ TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+ else
+ begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+ TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+ end;
+
+ try
+ ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+ finally
+ TargetFile.Free;
+ end;
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +754,12 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetInfo := aTargetInfo;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +870,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas (revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas (working copy)
@@ -72,7 +72,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
g_object_unref(AInfo);
FFiles.Add(AFile);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -163,6 +166,23 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var TargetFile: TFile;
+begin
+ TargetFile := TFile.Create('');
+ TargetFile.FullPath := TargetFilePath;
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.RetrieveStatistics: TFileSourceMoveOperationStatistics;
begin
// Statistics have to be synchronized because there are multiple values
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -94,7 +94,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -267,6 +267,10 @@
procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
begin
+ writeln('--------------- differ: --------------------');
+ writeln(CompareList[0]);
+ writeln(CompareList[1]);
+ writeln('--------------- /differ --------------------');
if gExternalTools[etDiffer].Enabled then
begin
if Assigned(WaitData) then
@@ -669,6 +673,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +687,7 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ OperationsManager.AddOperationModal(Operation);
Exit(pdrInCallback);
end;
@@ -792,6 +798,19 @@
var
I: Integer;
begin
+ writeln('----------- prepare files: ----------------');
+ writeln('--------------- file 1 --------------------');
+ writeln(FileSource1.ClassName);
+ writeln(SelectedFiles1[0].FullPath);
+ writeln(SelectedFiles1[0].Path);
+ writeln(SelectedFiles1[0].Name);
+ writeln('--------------- file 2 --------------------');
+ writeln(FileSource2.ClassName);
+ writeln(SelectedFiles2[0].FullPath);
+ writeln(SelectedFiles2[0].Path);
+ writeln(SelectedFiles2[0].Name);
+ writeln('--------------- /files --------------------');
+
case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
pdrSynchronous:
begin
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview9.patch (64,161 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -39,7 +39,7 @@
function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
class function CreateFile(const APath: String): TFile; override;
- class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+ class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
procedure Reload(const PathsToReload: TPathsArray); override;
function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
end;
end;
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
- AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+ AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
var
AFile: PGFile;
ATarget: Pgchar;
AFileType: TGFileType;
ASymlinkInfo: PGFileInfo;
+ OwnFolder: Boolean = False;
begin
Result:= CreateFile(APath);
Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
end
else if AFileType = G_FILE_TYPE_SYMBOLIC_LINK then
begin
+ if not Assigned(AFolder) then
+ begin
+ AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+ OwnFolder:= True;
+ end;
+
ATarget:= g_file_info_get_symlink_target(AFileInfo);
AFile:= g_file_get_child(AFolder, ATarget);
@@ -143,6 +150,8 @@
g_object_unref(ASymlinkInfo);
end;
g_object_unref(PGObject(AFile));
+ if OwnFolder then
+ g_object_unref(PGObject(AFolder));
end
else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetInfo: PGFileInfo;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +112,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceMoveOperation,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
if (aFileName <> '.') and (aFileName <> '..') then
begin
- aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
NewFiles.Add(aFile);
if aFile.IsLink then
@@ -270,7 +277,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
g_object_unref(AInfo);
AddItem(aFile, CurrentNode);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,42 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ TargetFileSource: IFileSource;
+ TargetFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ if FOperation is TFileSourceCopyOperation then
+ TargetFileSource := TFileSourceCopyOperation(FOperation).TargetFileSource
+ else
+ TargetFileSource := (FOperation as TFileSourceMoveOperation).TargetFileSource;
+
+ if TargetFileSource is TGioFileSource then
+ TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo)
+ else
+ begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+ TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+ end;
+
+ try
+ ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+ finally
+ TargetFile.Free;
+ end;
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +754,12 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetInfo := aTargetInfo;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +870,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +880,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas (revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas (working copy)
@@ -72,7 +72,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
g_object_unref(AInfo);
FFiles.Add(AFile);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +178,24 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,35 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +606,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -56,7 +56,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +84,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,8 +267,12 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
+ writeln('--------------- differ: --------------------');
+ writeln(CompareList[0]);
+ writeln(CompareList[1]);
+ writeln('--------------- /differ --------------------');
if gExternalTools[etDiffer].Enabled then
begin
if Assigned(WaitData) then
@@ -275,7 +281,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +641,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +676,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +690,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +774,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +790,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +802,27 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ writeln('----------- prepare files: ----------------');
+ writeln('--------------- file 1 --------------------');
+ writeln(FileSource1.ClassName);
+ writeln(SelectedFiles1[0].FullPath);
+ writeln(SelectedFiles1[0].Path);
+ writeln(SelectedFiles1[0].Name);
+ writeln('--------------- file 2 --------------------');
+ writeln(FileSource2.ClassName);
+ writeln(SelectedFiles2[0].FullPath);
+ writeln(SelectedFiles2[0].Path);
+ writeln(SelectedFiles2[0].Name);
+ writeln('--------------- /files --------------------');
+
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +834,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +842,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -886,7 +916,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +927,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,7 +966,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
Files1 := TFiles.Create(File1.Path);
@@ -946,7 +977,7 @@
try
Files2.Add(File2.Clone);
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview10.patch (64,027 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -39,7 +39,7 @@
function GetFreeSpace(Path: String; out FreeSize, TotalSize : Int64) : Boolean; override;
class function CreateFile(const APath: String): TFile; override;
- class function CreateFile(const APath: String; AFolder: PGFile; AFileInfo: PGFileInfo): TFile;
+ class function CreateFile(const APath: String; AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
procedure Reload(const PathsToReload: TPathsArray); override;
function GetParentDir(sPath : String): String; override;
@@ -103,13 +103,14 @@
end;
end;
-class function TGioFileSource.CreateFile(const APath: String; AFolder: PGFile;
- AFileInfo: PGFileInfo): TFile;
+class function TGioFileSource.CreateFile(const APath: String;
+ AFileInfo: PGFileInfo; AFolder: PGFile = nil): TFile;
var
AFile: PGFile;
ATarget: Pgchar;
AFileType: TGFileType;
ASymlinkInfo: PGFileInfo;
+ OwnFolder: Boolean = False;
begin
Result:= CreateFile(APath);
Result.Name:= g_file_info_get_name(AFileInfo);
@@ -127,6 +128,12 @@
end
else if AFileType = G_FILE_TYPE_SYMBOLIC_LINK then
begin
+ if not Assigned(AFolder) then
+ begin
+ AFolder:= g_file_new_for_commandline_arg(Pgchar(APath));
+ OwnFolder:= True;
+ end;
+
ATarget:= g_file_info_get_symlink_target(AFileInfo);
AFile:= g_file_get_child(AFolder, ATarget);
@@ -143,6 +150,8 @@
g_object_unref(ASymlinkInfo);
end;
g_object_unref(PGObject(AFile));
+ if OwnFolder then
+ g_object_unref(PGObject(AFolder));
end
else if AFileType in [G_FILE_TYPE_SHORTCUT, G_FILE_TYPE_MOUNTABLE] then
begin
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetInfo: PGFileInfo;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +73,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +88,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +112,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -142,7 +149,7 @@
if (aFileName <> '.') and (aFileName <> '..') then
begin
- aFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ aFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
NewFiles.Add(aFile);
if aFile.IsLink then
@@ -270,7 +277,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(srcPath, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(srcPath, AInfo, AFolder);
g_object_unref(AInfo);
AddItem(aFile, CurrentNode);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
@@ -677,13 +684,37 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ TargetFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ if (FOperation is TFileSourceCopyOperation) and
+ not (TFileSourceCopyOperation(FOperation).TargetFileSource is TGioFileSource) then // CopyOut detection
+ begin
+ TargetFile := TFileSourceCopyOperation(FOperation).TargetFileSource.CreateFileObject(ExtractFilePath(FCurrentTargetFilePath));
+ TargetFile.Name := ExtractFileName(FCurrentTargetFilePath);
+ end
+ else
+ TargetFile := TGioFileSource.CreateFile(ExtractFilePath(FCurrentTargetFilePath), FCurrentTargetInfo);
+
+ try
+ ShowCompareFilesUIByFileObject(FCurrentFile, TargetFile);
+ finally
+ TargetFile.Free;
+ end;
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +749,12 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetInfo := aTargetInfo;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +865,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +875,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiolistoperation.pas
===================================================================
--- src/filesources/gio/ugiolistoperation.pas (revision 7965)
+++ src/filesources/gio/ugiolistoperation.pas (working copy)
@@ -72,7 +72,7 @@
while Assigned(AInfo) do
begin
CheckOperationState;
- AFile:= TGioFileSource.CreateFile(Path, AFolder, AInfo);
+ AFile:= TGioFileSource.CreateFile(Path, AInfo, AFolder);
g_object_unref(AInfo);
FFiles.Add(AFile);
AInfo:= g_file_enumerator_next_file(AFileEnum, nil, @AError);
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUIByFileObject,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +178,24 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +607,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -56,7 +56,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +84,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,8 +267,12 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
+ writeln('--------------- differ: --------------------');
+ writeln(CompareList[0]);
+ writeln(CompareList[1]);
+ writeln('--------------- /differ --------------------');
if gExternalTools[etDiffer].Enabled then
begin
if Assigned(WaitData) then
@@ -275,7 +281,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +641,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +676,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +690,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +774,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +790,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +802,27 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ writeln('----------- prepare files: ----------------');
+ writeln('--------------- file 1 --------------------');
+ writeln(FileSource1.ClassName);
+ writeln(SelectedFiles1[0].FullPath);
+ writeln(SelectedFiles1[0].Path);
+ writeln(SelectedFiles1[0].Name);
+ writeln('--------------- file 2 --------------------');
+ writeln(FileSource2.ClassName);
+ writeln(SelectedFiles2[0].FullPath);
+ writeln(SelectedFiles2[0].Path);
+ writeln(SelectedFiles2[0].Name);
+ writeln('--------------- /files --------------------');
+
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +834,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +842,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -886,7 +916,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +927,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,7 +966,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
Files1 := TFiles.Create(File1.Path);
@@ -946,7 +977,7 @@
try
Files2.Add(File2.Clone);
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview11.patch (59,375 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +178,24 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +607,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -56,7 +56,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +84,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,7 +267,7 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
if gExternalTools[etDiffer].Enabled then
begin
@@ -275,7 +277,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +637,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +672,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +686,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +770,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +786,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +798,14 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +817,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +825,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -886,7 +899,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +910,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,17 +949,20 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
Files1 := TFiles.Create(File1.Path);
try
Files1.Add(File1.Clone);
+ Files1.Path := File1.Path;
Files2 := TFiles.Create(File2.Path);
try
Files2.Add(File2.Clone);
+ Files2.Path := File2.Path;
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview12.patch (59,859 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -427,7 +427,7 @@
SourceFileSource: IFileSource;
begin
SourceFileSource := Self;
- SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
+ if not StrBegins(SourceFiles.Path, FCurrentAddress) then SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
Result := TGioCopyOutOperation.Create(SourceFileSource, TargetFileSource, SourceFiles, TargetPath);
end;
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +178,24 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +607,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -56,7 +56,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +84,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +96,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,7 +267,7 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
if gExternalTools[etDiffer].Enabled then
begin
@@ -275,7 +277,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -635,7 +637,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +672,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +686,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +770,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +786,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +798,14 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +817,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +825,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -886,7 +899,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +910,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,7 +949,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
Files1 := TFiles.Create(File1.Path);
@@ -946,7 +960,7 @@
try
Files2.Add(File2.Clone);
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview13.patch (61,266 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationTypes,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,29 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ SourceFilesPath: String = '';
+ TargetFilesPath: String = '';
+begin
+ if Action = fsouaCompare then
+ begin
+ if FOperation.ID <> fsoCopyIn then
+ SourceFilesPath := Copy(ExtractFilePath(FCurrentFile.FullPath), Length(FGioFileSource.CurrentAddress)+1, MaxInt);
+ if FOperation.ID <> fsoCopyOut then
+ TargetFilesPath := Copy(ExtractFilePath(FCurrentTargetFilePath), Length(FGioFileSource.CurrentAddress)+1, MaxInt);
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath, SourceFilesPath, TargetFilesPath);
+ end;
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +740,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +855,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +865,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,10 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+ SourceFilesPath: String = ''; TargetFilesPath: String = '');
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +139,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +276,26 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, '', '', True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+ SourceFilesPath: String = ''; TargetFilesPath: String = '');
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList,
+ SourceFilesPath, TargetFilesPath, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,10 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+ SourceFilesPath: String = ''; TargetFilesPath: String = '');
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +82,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +179,26 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, '', '', True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String;
+ SourceFilesPath: String = ''; TargetFilesPath: String = '');
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList,
+ SourceFilesPath, TargetFilesPath, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,15 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String;
+ SourceFilesPath: String = ''; TargetFilesPath: String = '') of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +176,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +323,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1180,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1212,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1290,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +607,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -56,7 +56,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +63,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +75,10 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Files1Path: String = '';
+ Files2Path: String = '';
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +86,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +98,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,7 +269,7 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
if gExternalTools[etDiffer].Enabled then
begin
@@ -275,7 +279,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -389,7 +393,10 @@
function TEditorWaitData.GetFromPath: string;
begin
- Result := TargetFileSource.CurrentAddress + TargetPath;
+ if StrBegins(TargetPath, TargetFileSource.CurrentAddress) then
+ Result := TargetPath // Workaround for TGioFileSource
+ else
+ Result := TargetFileSource.CurrentAddress + TargetPath;
end;
procedure TEditorWaitData.ShowWaitForm;
@@ -635,7 +642,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +677,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +691,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +775,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +791,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +803,14 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +822,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +830,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -886,7 +904,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +915,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,17 +954,26 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Files1Path: String = '';
+ Files2Path: String = '';
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
- Files1 := TFiles.Create(File1.Path);
+ if Files1Path <> '' then
+ Files1 := TFiles.Create(Files1Path)
+ else
+ Files1 := TFiles.Create(File1.Path);
try
Files1.Add(File1.Clone);
- Files2 := TFiles.Create(File2.Path);
+ if Files2Path <> '' then
+ Files2 := TFiles.Create(Files2Path)
+ else
+ Files2 := TFiles.Create(File2.Path);
try
Files2.Add(File2.Clone);
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
bug1536-preview14.patch (63,902 bytes)
Index: src/fdiffer.pas
===================================================================
--- src/fdiffer.pas (revision 7965)
+++ src/fdiffer.pas (working copy)
@@ -249,7 +249,7 @@
procedure cm_SaveRight(const Params: array of string);
end;
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
implementation
@@ -262,7 +262,7 @@
const
HotkeysCategory = 'Differ';
-procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil);
+procedure ShowDiffer(const FileNameLeft, FileNameRight: String; WaitData: TWaitData = nil; Modal: Boolean = False);
begin
with TfrmDiffer.Create(Application) do
begin
@@ -278,7 +278,13 @@
OpenFileRight(FileNameRight);
if actAutoCompare.Checked then actStartCompare.Execute;
end;
- if actBinaryCompare.Checked or (FShowIdentical = False) then ShowOnTop;
+ if actBinaryCompare.Checked or (FShowIdentical = False) then
+ begin
+ if Modal then
+ ShowModal
+ else
+ ShowOnTop;
+ end;
end;
end;
Index: src/ffileexecuteyourself.pas
===================================================================
--- src/ffileexecuteyourself.pas (revision 7965)
+++ src/ffileexecuteyourself.pas (working copy)
@@ -52,7 +52,7 @@
destructor Destroy; override;
end;
- procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData);
+ procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData; Modal: Boolean = False);
function ShowFileExecuteYourSelf(aFileView: TFileView; aFile: TFile; bWithAll: Boolean): Boolean;
implementation
@@ -62,7 +62,7 @@
uses
DCOSUtils, DCStrUtils, uTempFileSystemFileSource, uFileSourceOperation, uShellExecute;
-procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData);
+procedure ShowFileEditExternal(const FileName, FromPath: string; aWaitData: TWaitData; Modal: Boolean = False);
begin
// Create wait window
with TfrmFileExecuteYourSelf.Create(Application, nil, FileName, FromPath) do
@@ -69,7 +69,10 @@
begin
FWaitData:= aWaitData;
// Show wait window
- Visible := True;
+ if Modal then
+ ShowModal
+ else
+ Visible := True;
end;
end;
Index: src/filesources/filesystem/ufilesystemcopyoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemcopyoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemcopyoperation.pas (working copy)
@@ -172,6 +172,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmCopy,
TargetPath,
Index: src/filesources/filesystem/ufilesystemmoveoperation.pas
===================================================================
--- src/filesources/filesystem/ufilesystemmoveoperation.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemmoveoperation.pas (working copy)
@@ -137,6 +137,7 @@
@AppProcessMessages,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
Thread,
fsohmMove,
TargetPath,
Index: src/filesources/filesystem/ufilesystemutil.pas
===================================================================
--- src/filesources/filesystem/ufilesystemutil.pas (revision 7965)
+++ src/filesources/filesystem/ufilesystemutil.pas (working copy)
@@ -83,11 +83,15 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
AppProcessMessages: TAppProcessMessagesFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
MoveOrCopy: TFileSystemOperationHelperMoveOrCopy;
procedure ShowError(sMessage: String);
@@ -109,6 +113,7 @@
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean;
AllowDelete: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
var AbsoluteTargetFileName: String;
AllowAppend: Boolean): TFileSourceOperationOptionFileExists;
@@ -121,6 +126,8 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+
OperationThread: TThread;
Mode: TFileSystemOperationHelperMode;
TargetPath: String;
@@ -315,6 +322,7 @@
AppProcessMessagesFunction: TAppProcessMessagesFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
OperationThread: TThread; Mode: TFileSystemOperationHelperMode;
TargetPath: String; StartingStatistics: TFileSourceCopyOperationStatistics);
begin
@@ -323,6 +331,7 @@
AppProcessMessages := AppProcessMessagesFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FOperationThread := OperationThread;
FMode := Mode;
@@ -1355,18 +1364,26 @@
Result := FDirExistsOption;
end;
+procedure TFileSystemOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TFileSystemOperationHelper.FileExists(aFile: TFile;
var AbsoluteTargetFileName: String; AllowAppend: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..11] of TFileSourceOperationUIResponse
+ Responses: array[0..12] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
- fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel, fsourAppend,
- fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource);
- ResponsesNoAppend: array[0..9] of TFileSourceOperationUIResponse
+ fsourSkipAll, fsourResume, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourAppend, fsourOverwriteSmaller, fsourOverwriteLarger,
+ fsourAutoRenameSource);
+ ResponsesNoAppend: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
- fsourOverwriteLarger, fsourAutoRenameSource);
+ fsouaCompare, fsourOverwriteLarger, fsourAutoRenameSource);
var
Answer: Boolean;
Message: String;
@@ -1407,8 +1424,11 @@
end;
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/gio/ugiocopyoperation.pas
===================================================================
--- src/filesources/gio/ugiocopyoperation.pas (revision 7965)
+++ src/filesources/gio/ugiocopyoperation.pas (working copy)
@@ -116,6 +116,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_copy,
TargetPath);
Index: src/filesources/gio/ugiofilesource.pas
===================================================================
--- src/filesources/gio/ugiofilesource.pas (revision 7965)
+++ src/filesources/gio/ugiofilesource.pas (working copy)
@@ -427,7 +427,7 @@
SourceFileSource: IFileSource;
begin
SourceFileSource := Self;
- SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
+ if not StrBegins(SourceFiles.Path, FCurrentAddress) then SourceFiles.Path:= FCurrentAddress + SourceFiles.Path;
Result := TGioCopyOutOperation.Create(SourceFileSource, TargetFileSource, SourceFiles, TargetPath);
end;
Index: src/filesources/gio/ugiofilesourceutil.pas
===================================================================
--- src/filesources/gio/ugiofilesourceutil.pas (revision 7965)
+++ src/filesources/gio/ugiofilesourceutil.pas (working copy)
@@ -7,9 +7,9 @@
uses
Classes, SysUtils, DCStrUtils, uFile, uFileSource, uFileSourceOperation,
uFileSourceCopyOperation, uFileSystemUtil, uFileSourceOperationOptions,
- uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs;
+ uFileSourceTreeBuilder, uGioFileSource, uGLib2, uGio2, uLog, uGlobs,
+ uFileSourceOperationUI;
-
const
CONST_DEFAULT_QUERY_INFO_ATTRIBUTES = FILE_ATTRIBUTE_STANDARD_TYPE + ',' + FILE_ATTRIBUTE_STANDARD_NAME + ',' +
FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME + ',' + FILE_ATTRIBUTE_STANDARD_SIZE + ',' +
@@ -51,10 +51,14 @@
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
procedure ShowError(const Message: String; AError: PGError);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -68,6 +72,7 @@
function DirExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowCopyInto: Boolean): TFileSourceOperationOptionDirectoryExists;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
@@ -82,6 +87,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction;
TargetPath: String
);
@@ -105,7 +111,7 @@
implementation
uses
- Forms, StrUtils, DCDateTimeUtils, uFileProperty, uFileSourceOperationUI,
+ Forms, StrUtils, DCDateTimeUtils, uFileProperty,
uShowMsg, uLng, uGObject2, DCFileAttributes;
procedure ShowError(AError: PGError);
@@ -677,13 +683,20 @@
end;
end;
+procedure TGioOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+end;
+
function TGioOperationHelper.FileExists(aFile: TFile; aTargetInfo: PGFileInfo;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..8] of TFileSourceOperationUIResponse
+ Responses: array[0..9] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourRenameSource, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteOlder,fsourOverwriteSmaller,
- fsourOverwriteLarger, fsourCancel);
+ fsourCancel, fsouaCompare, fsourOverwriteLarger);
var
Answer: Boolean;
Message: String;
@@ -718,8 +731,11 @@
repeat
Answer := True;
Message:= FileExistsMessage(aFile, aTargetInfo, AbsoluteTargetFileName);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- Responses, fsourOverwrite, fsourSkip) of
+ Responses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -830,6 +846,7 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
CopyMoveFileFunction: TCopyMoveFileFunction; TargetPath: String);
begin
FGioFileSource:= FileSource as IGioFileSource;
@@ -839,6 +856,7 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
FCopyMoveFile := CopyMoveFileFunction;
FFileExistsOption := fsoofeNone;
Index: src/filesources/gio/ugiomoveoperation.pas
===================================================================
--- src/filesources/gio/ugiomoveoperation.pas (revision 7965)
+++ src/filesources/gio/ugiomoveoperation.pas (working copy)
@@ -80,6 +80,7 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
g_file_move,
TargetPath);
Index: src/filesources/multiarchive/umultiarchivecopyoutoperation.pas
===================================================================
--- src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/multiarchive/umultiarchivecopyoutoperation.pas (working copy)
@@ -8,6 +8,7 @@
LazFileUtils,LazUtf8,Classes, SysUtils, StringHashList, uLog, uGlobs, un_process,
uFileSourceOperation,
uFileSourceCopyOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFileSource,
@@ -60,6 +61,11 @@
procedure CheckForErrors(const SourceName, TargetName: String; ExitStatus: LongInt);
protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
+ protected
FExProcess: TExProcess;
FTempFile: String;
FFileMask: String;
@@ -91,7 +97,7 @@
implementation
uses
- LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc, uFileSourceOperationUI,
+ LCLProc, FileUtil, uOSUtils, DCOSUtils, DCStrUtils, uMultiArc,
fMultiArchiveCopyOperationOptions, uMultiArchiveUtil, uFileProcs, uLng, DCDateTimeUtils,
DCBasicTypes, uShowMsg, uFileSystemUtil;
@@ -445,12 +451,29 @@
end;
end;
+procedure TMultiArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := FCurrentFile.Clone;
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(aFile.FullPath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TMultiArchiveCopyOutOperation.DoFileExists(aFile: TFile;
const AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
- fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel);
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsouaCompare,
+ fsourCancel);
var
Message: String;
@@ -486,8 +509,11 @@
begin
Message:= FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath,
aFile.Size, aFile.ModificationTime);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/ufilesourcecopyoperation.pas
===================================================================
--- src/filesources/ufilesourcecopyoperation.pas (revision 7965)
+++ src/filesources/ufilesourcecopyoperation.pas (working copy)
@@ -58,6 +58,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceCopyOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property TargetPath: String read FTargetPath;
public
@@ -135,7 +138,7 @@
implementation
uses
- uDCUtils, uLng, uGlobs;
+ uDCUtils, uLng, uGlobs, uShowForm;
// -- TFileSourceCopyOperation ------------------------------------------------
@@ -272,6 +275,24 @@
end;
end;
+procedure TFileSourceCopyOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceCopyOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := TargetFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(SourceFileSource, SourceFile, TargetFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
// -- TFileSourceCopyInOperation ----------------------------------------------
function TFileSourceCopyInOperation.GetID: TFileSourceOperationType;
Index: src/filesources/ufilesourcemoveoperation.pas
===================================================================
--- src/filesources/ufilesourcemoveoperation.pas (revision 7965)
+++ src/filesources/ufilesourcemoveoperation.pas (working copy)
@@ -46,6 +46,9 @@
procedure UpdateStatistics(var NewStatistics: TFileSourceMoveOperationStatistics);
procedure UpdateStatisticsAtStartTime; override;
+ procedure ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+ procedure ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+
property FileSource: IFileSource read FFileSource;
property SourceFiles: TFiles read FSourceFiles;
property TargetPath: String read FTargetPath;
@@ -78,7 +81,7 @@
implementation
uses
- uDCUtils, uLng;
+ uDCUtils, uLng, uShowForm;
// -- TFileSourceMoveOperation ------------------------------------------------
@@ -175,6 +178,24 @@
end;
end;
+procedure TFileSourceMoveOperation.ShowCompareFilesUIByFileObject(SourceFile: TFile; TargetFile: TFile);
+begin
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+end;
+
+procedure TFileSourceMoveOperation.ShowCompareFilesUI(SourceFile: TFile; const TargetFilePath: String);
+var
+ TargetFile: TFile = nil;
+begin
+ TargetFile := FFileSource.CreateFileObject(ExtractFilePath(TargetFilePath));
+ TargetFile.Name := ExtractFileName(TargetFilePath);
+ try
+ PrepareToolData(FFileSource, SourceFile, FFileSource, TargetFile, @ShowDifferByGlobList, True);
+ finally
+ TargetFile.Free;
+ end;
+end;
+
function TFileSourceMoveOperation.GetID: TFileSourceOperationType;
begin
Result := fsoMove;
Index: src/filesources/ufilesourceoperation.pas
===================================================================
--- src/filesources/ufilesourceoperation.pas (revision 7965)
+++ src/filesources/ufilesourceoperation.pas (working copy)
@@ -25,7 +25,8 @@
Classes, SysUtils, syncobjs, uLng,
uFileSourceOperationOptionsUI,
uFileSourceOperationTypes,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uFile;
type
@@ -75,11 +76,14 @@
function(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse of object;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer of object;
TAbortOperationFunction = procedure of object;
TCheckOperationStateFunction = procedure of object;
TAppProcessMessagesFunction = function(CheckState: Boolean = False): Boolean of object;
+ TShowCompareFilesUIFunction = procedure(SourceFile: TFile; const TargetFilePath: String) of object;
+ TShowCompareFilesUIByFileObjectFunction = procedure(SourceFile: TFile; TargetFile: TFile) of object;
TFileSourceOperationClass = class of TFileSourceOperation;
{en
@@ -171,8 +175,9 @@
FUIQuestion: String;
FUIPossibleResponses: array of TFileSourceOperationUIResponse;
FUIDefaultOKResponse: TFileSourceOperationUIResponse;
- FUIDefaultCancelResponse: TFileSourceOperationUIResponse;
- FUIResponse: TFileSourceOperationUIResponse;
+ FUIDefaultCancelResponse: TFileSourceOperationUIAnswer;
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ FUIResponse: TFileSourceOperationUIAnswer;
FTryAskQuestionResult: Boolean;
{en
@@ -317,8 +322,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
{en
Remember statistics at start time (used for estimating remaining time).
@@ -1173,7 +1179,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse): TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
i: Integer;
bStateChanged: Boolean = False;
@@ -1203,6 +1211,7 @@
FUIPossibleResponses[i] := PossibleResponses[i];
FUIDefaultOKResponse := DefaultOKResponse;
FUIDefaultCancelResponse := DefaultCancelResponse;
+ FUIActionHandler := ActionHandler;
if GetCurrentThreadID <> MainThreadID then
begin
@@ -1280,7 +1289,8 @@
FUIQuestion,
FUIPossibleResponses,
FUIDefaultOKResponse,
- FUIDefaultCancelResponse);
+ FUIDefaultCancelResponse,
+ FUIActionHandler);
FTryAskQuestionResult := True; // We do have an answer now.
end;
Index: src/filesources/ufilesourceoperationmessageboxesui.pas
===================================================================
--- src/filesources/ufilesourceoperationmessageboxesui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmessageboxesui.pas (working copy)
@@ -6,7 +6,8 @@
uses
Classes, SysUtils,
- uFileSourceOperationUI;
+ uFileSourceOperationUI,
+ uShowMsg;
type
@@ -13,7 +14,14 @@
{en
We assume here the UI is used only from the GUI thread.
}
+
+ { TFileSourceOperationMessageBoxesUI }
+
TFileSourceOperationMessageBoxesUI = class(TFileSourceOperationUI)
+ private
+ FUIActionHandler: TFileSourceOperationUIActionHandler;
+ protected
+ procedure QuestionActionHandler(Button: TMyMsgActionButton);
public
constructor Create; override;
destructor Destroy; override;
@@ -21,21 +29,21 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; override;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; override;
end;
implementation
-uses
- uShowMsg;
-
const
ResponseToButton: array[TFileSourceOperationUIResponse] of TMyMsgButton =
(msmbOK, msmbOK, msmbNo, msmbYes, msmbCancel, msmbNone, msmbAppend, msmbResume,
msmbCopyInto, msmbCopyIntoAll, msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions:
+ msmbCompare);
ResultToResponse: array[TMyMsgResult] of TFileSourceOperationUIResponse =
(fsourOk, fsourNo, fsourYes, fsourCancel, fsourNone, fsourAppend, fsourResume,
@@ -43,6 +51,9 @@
fsourOverwriteSmaller, fsourOverwriteLarger, fsourAutoRenameSource, fsourRenameSource,
fsourSkip, fsourSkipAll, fsourIgnore, fsourIgnoreAll, fsourAll, fsourRetry, fsourAbort, fsourRetryAdmin);
+ ButtonToUIAction: array[TMyMsgActionButton] of TFileSourceOperationUIAction =
+ (fsouaCompare);
+
constructor TFileSourceOperationMessageBoxesUI.Create;
begin
inherited;
@@ -57,8 +68,9 @@
Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer;
var
Buttons: array of TMyMsgButton;
i: Integer;
@@ -65,6 +77,8 @@
MsgResult: TMyMsgResult;
TextMessage: String;
begin
+ FUIActionHandler := ActionHandler;
+
SetLength(Buttons, Length(PossibleResponses));
for i := 0 to Length(PossibleResponses) - 1 do
Buttons[i] := ResponseToButton[PossibleResponses[i]];
@@ -77,10 +91,18 @@
MsgResult := MsgBox(TextMessage,
Buttons,
ResponseToButton[DefaultOKResponse],
- ResponseToButton[DefaultCancelResponse]);
+ ResponseToButton[DefaultCancelResponse],
+ @QuestionActionHandler);
Result := ResultToResponse[MsgResult];
end;
+procedure TFileSourceOperationMessageBoxesUI.QuestionActionHandler(
+ Button: TMyMsgActionButton);
+begin
+ if Assigned(FUIActionHandler) then
+ FUIActionHandler(ButtonToUIAction[Button]);
+end;
+
end.
Index: src/filesources/ufilesourceoperationmisc.pas
===================================================================
--- src/filesources/ufilesourceoperationmisc.pas (revision 7965)
+++ src/filesources/ufilesourceoperationmisc.pas (working copy)
@@ -69,7 +69,8 @@
procedure ShowOperationModal(OpManItem: TOperationsManagerItem);
begin
- with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+// with TfrmFileOp.Create(OpManItem.Queue.Identifier) do
+ with TfrmFileOp.Create(OpManItem.Handle) do
try
ShowModal;
finally
Index: src/filesources/ufilesourceoperationui.pas
===================================================================
--- src/filesources/ufilesourceoperationui.pas (revision 7965)
+++ src/filesources/ufilesourceoperationui.pas (working copy)
@@ -34,8 +34,16 @@
fsourAll,
fsourRetry,
fsourAbort,
- fsourRetryAdmin);
+ fsourRetryAdmin,
+ // Actions will never be returned since they do not close the window, handle them in ActionHandler.
+ fsouaCompare); // The first action, hardcoded. Add new actions after this and new answers before this line.
+ TFileSourceOperationUIAnswer = Low(TFileSourceOperationUIResponse)..Pred(fsouaCompare);
+
+ TFileSourceOperationUIAction = fsouaCompare..High(TFileSourceOperationUIResponse);
+
+ TFileSourceOperationUIActionHandler = procedure(Action: TFileSourceOperationUIAction) of object;
+
{en
General interface for communication: operation <-> user.
}
@@ -47,8 +55,9 @@
function AskQuestion(Msg: String; Question: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
DefaultOKResponse: TFileSourceOperationUIResponse;
- DefaultCancelResponse: TFileSourceOperationUIResponse
- ) : TFileSourceOperationUIResponse; virtual abstract;
+ DefaultCancelResponse: TFileSourceOperationUIAnswer;
+ ActionHandler: TFileSourceOperationUIActionHandler = nil
+ ) : TFileSourceOperationUIAnswer; virtual abstract;
// Add possibility to display files properties (for example: to compare older - newer)
// Add general option "remember this choice for all files of this type" (checkbox)
end;
Index: src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyinoperation.pas (working copy)
@@ -13,6 +13,7 @@
uFile,
uWcxModule,
uWcxArchiveFileSource,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI;
@@ -44,6 +45,10 @@
function Tar: Boolean;
procedure SetProcessDataProc(hArcData: TArcHandle);
+ protected
+ FCurrentFile: TFile;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
function FileExists(aSourceFile: TFile; aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
@@ -71,7 +76,7 @@
uses
LazUTF8, FileUtil, StrUtils, DCStrUtils, uLng, uShowMsg, fWcxArchiveCopyOperationOptions,
- uFileSystemFileSource, uFileSourceOperationUI, uFileSystemUtil, DCOSUtils, uTarWriter,
+ uFileSystemFileSource, DCOSUtils, uTarWriter,
DCConvertEncoding, DCDateTimeUtils, uArchiveFileSourceUtil;
// ----------------------------------------------------------------------------
@@ -409,6 +414,13 @@
end;
end;
+procedure TWcxArchiveCopyInOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ ShowCompareFilesUI(FCurrentFile, IncludeFrontPathDelimiter(FCurrentTargetFilePath));
+end;
+
function TWcxArchiveCopyInOperation.FileExistsMessage(aSourceFile: TFile; aTargetHeader: TWcxHeader): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + aTargetHeader.FileName + LineEnding;
@@ -423,10 +435,10 @@
function TWcxArchiveCopyInOperation.FileExists(aSourceFile: TFile;
aTargetHeader: TWcxHeader): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..7] of TFileSourceOperationUIResponse
+ PossibleResponses: array[0..8] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger,
fsourOverwriteAll, fsourSkipAll, fsourOverwriteSmaller,
- fsourOverwriteOlder, fsourCancel);
+ fsourOverwriteOlder, fsouaCompare, fsourCancel);
function OverwriteOlder: TFileSourceOperationOptionFileExists;
begin
@@ -456,8 +468,11 @@
case FFileExistsOption of
fsoofeNone:
begin
+ FCurrentFile := aSourceFile;
+ FCurrentTargetFilePath := aTargetHeader.FileName;
case AskQuestion(FileExistsMessage(aSourceFile, aTargetHeader), '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas
===================================================================
--- src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (revision 7965)
+++ src/filesources/wcxarchive/uwcxarchivecopyoutoperation.pas (working copy)
@@ -10,6 +10,7 @@
uFileSourceCopyOperation,
uFileSource,
uFileSourceOperation,
+ uFileSourceOperationUI,
uFileSourceOperationOptions,
uFileSourceOperationOptionsUI,
uFile,
@@ -65,6 +66,10 @@
procedure LogMessage(const sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
protected
+ FCurrentFilePath: String;
+ FCurrentTargetFilePath: String;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
+
procedure SetProcessDataProc(hArcData: TArcHandle);
public
@@ -91,7 +96,7 @@
uses
Forms, LazUTF8, uMasks, FileUtil, contnrs, DCOSUtils, DCStrUtils, uDCUtils,
- uFileSourceOperationUI, fWcxArchiveCopyOperationOptions, uFileSystemUtil,
+ fWcxArchiveCopyOperationOptions, uFileSystemUtil,
uFileProcs, uLng, DCDateTimeUtils, DCBasicTypes, uShowMsg, DCConvertEncoding;
// ----------------------------------------------------------------------------
@@ -538,14 +543,36 @@
end;
end;
+procedure TWcxArchiveCopyOutOperation.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+var
+ aFile: TFile;
+begin
+ if Action = fsouaCompare then
+ begin
+ aFile := TFile.Create('');
+ try
+ aFile.FullPath := IncludeFrontPathDelimiter(FCurrentFilePath);
+ ShowCompareFilesUI(aFile, FCurrentTargetFilePath);
+ finally
+ aFile.Free;
+ end;
+ end;
+end;
+
function TWcxArchiveCopyOutOperation.DoFileExists(Header: TWcxHeader;
var AbsoluteTargetFileName: String): TFileSourceOperationOptionFileExists;
const
- PossibleResponses: array[0..9] of TFileSourceOperationUIResponse
+ Responses: array[0..10] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
+ fsouaCompare, fsourRenameSource, fsourAutoRenameSource);
+ ResponsesNoCompare: array[0..9] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteLarger, fsourOverwriteAll,
+ fsourSkipAll, fsourOverwriteSmaller, fsourOverwriteOlder, fsourCancel,
fsourRenameSource, fsourAutoRenameSource);
var
+ PossibleResponses: array of TFileSourceOperationUIResponse;
Answer: Boolean;
Message: String;
@@ -580,10 +607,19 @@
fsoofeNone:
repeat
Answer := True;
+ // Can't asynchoronously extract file for comparison when multiple operations are not supported
+ // TODO: implement synchronous CopyOut to temp directory or close the connection until the question is answered
+ case FNeedsConnection of
+ True : PossibleResponses := ResponsesNoCompare;
+ False: PossibleResponses := Responses;
+ end;
Message:= FileExistsMessage(AbsoluteTargetFileName, Header.FileName,
Header.UnpSize, WcxFileTimeToDateTime(Header.FileTime));
+ FCurrentFilePath := Header.FileName;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
Index: src/filesources/wfxplugin/uwfxplugincopyinoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyinoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyIn,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoperation.pas (working copy)
@@ -130,6 +130,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopy,
TargetPath);
Index: src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxplugincopyoutoperation.pas (working copy)
@@ -142,6 +142,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmCopyOut,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginmoveoperation.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (revision 7965)
+++ src/filesources/wfxplugin/uwfxpluginmoveoperation.pas (working copy)
@@ -128,6 +128,8 @@
@RaiseAbortOperation,
@CheckOperationState,
@UpdateStatistics,
+ @ShowCompareFilesUI,
+ @ShowCompareFilesUIByFileObject,
Thread,
wpohmMove,
TargetPath);
Index: src/filesources/wfxplugin/uwfxpluginutil.pas
===================================================================
--- src/filesources/wfxplugin/uwfxpluginutil.pas (revision 7968)
+++ src/filesources/wfxplugin/uwfxpluginutil.pas (working copy)
@@ -39,10 +39,16 @@
FCopyAttributesOptions: TCopyAttributesOptions;
FFileExistsOption: TFileSourceOperationOptionFileExists;
+ FCurrentFile: TFile;
+ FCurrentTargetFile: TFile;
+ FCurrentTargetFilePath: String;
+
AskQuestion: TAskQuestionFunction;
AbortOperation: TAbortOperationFunction;
CheckOperationState: TCheckOperationStateFunction;
UpdateStatistics: TUpdateStatisticsFunction;
+ ShowCompareFilesUI: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject: TShowCompareFilesUIByFileObjectFunction;
procedure ShowError(sMessage: String);
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
@@ -50,6 +56,7 @@
function ProcessDirectory(aFile: TFile; AbsoluteTargetFileName: String): LongInt;
function ProcessFile(aFile: TFile; AbsoluteTargetFileName: String; var Statistics: TFileSourceCopyOperationStatistics): LongInt;
+ procedure QuestionActionHandler(Action: TFileSourceOperationUIAction);
function FileExists(aFile: TFile;
AbsoluteTargetFileName: String;
AllowResume: Boolean): TFileSourceOperationOptionFileExists;
@@ -62,6 +69,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -233,6 +242,18 @@
end;
end;
+procedure TWfxPluginOperationHelper.QuestionActionHandler(
+ Action: TFileSourceOperationUIAction);
+begin
+ if Action = fsouaCompare then
+ begin
+ if Assigned(FCurrentTargetFile) then
+ ShowCompareFilesUIByFileObject(FCurrentFile, FCurrentTargetFile)
+ else
+ ShowCompareFilesUI(FCurrentFile, FCurrentTargetFilePath);
+ end;
+end;
+
function FileExistsMessage(TargetFile: TFile; SourceFile: TFile): String;
begin
Result:= rsMsgFileExistsOverwrite + LineEnding + TargetFile.FullPath + LineEnding +
@@ -245,19 +266,20 @@
AbsoluteTargetFileName: String; AllowResume: Boolean
): TFileSourceOperationOptionFileExists;
const
- Responses: array[0..5] of TFileSourceOperationUIResponse
+ Responses: array[0..6] of TFileSourceOperationUIResponse
= (fsourOverwrite, fsourSkip, fsourResume, fsourOverwriteAll, fsourSkipAll,
+ fsouaCompare, fsourCancel);
+ ResponsesNoResume: array[0..5] of TFileSourceOperationUIResponse
+ = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsouaCompare,
fsourCancel);
- ResponsesNoResume: array[0..4] of TFileSourceOperationUIResponse
- = (fsourOverwrite, fsourSkip, fsourOverwriteAll, fsourSkipAll, fsourCancel);
var
Message: String;
PossibleResponses: array of TFileSourceOperationUIResponse;
- TargetFile: TFile;
begin
case FFileExistsOption of
fsoofeNone:
- begin
+ try
+ FCurrentTargetFile := nil;
case AllowResume of
True : PossibleResponses := Responses;
False: PossibleResponses := ResponsesNoResume;
@@ -264,15 +286,15 @@
end;
if FMode = wpohmCopyOut then
Message := uFileSystemUtil.FileExistsMessage(AbsoluteTargetFileName, aFile.FullPath, aFile.Size, aFile.ModificationTime)
- else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, TargetFile) then
- begin
- Message := FileExistsMessage(TargetFile, aFile);
- TargetFile.Free;
- end
+ else if FWfxPluginFileSource.FillSingleFile(AbsoluteTargetFileName, FCurrentTargetFile) then
+ Message := FileExistsMessage(FCurrentTargetFile, aFile)
else
Message := Format(rsMsgFileExistsRwrt, [AbsoluteTargetFileName]);
+ FCurrentFile := aFile;
+ FCurrentTargetFilePath := AbsoluteTargetFileName;
case AskQuestion(Message, '',
- PossibleResponses, fsourOverwrite, fsourSkip) of
+ PossibleResponses, fsourOverwrite, fsourSkip,
+ @QuestionActionHandler) of
fsourOverwrite:
Result := fsoofeOverwrite;
fsourSkip:
@@ -296,6 +318,8 @@
fsourCancel:
AbortOperation;
end;
+ finally
+ FreeAndNil(FCurrentTargetFile);
end;
else
@@ -324,6 +348,8 @@
AbortOperationFunction: TAbortOperationFunction;
CheckOperationStateFunction: TCheckOperationStateFunction;
UpdateStatisticsFunction: TUpdateStatisticsFunction;
+ ShowCompareFilesUIFunction: TShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObjectFunction: TShowCompareFilesUIByFileObjectFunction;
OperationThread: TThread;
Mode: TWfxPluginOperationHelperMode;
TargetPath: String
@@ -334,6 +360,8 @@
AbortOperation := AbortOperationFunction;
CheckOperationState := CheckOperationStateFunction;
UpdateStatistics := UpdateStatisticsFunction;
+ ShowCompareFilesUI := ShowCompareFilesUIFunction;
+ ShowCompareFilesUIByFileObject := ShowCompareFilesUIByFileObjectFunction;
FOperationThread:= OperationThread;
FMode := Mode;
FInternal:= (FMode in [wpohmCopy, wpohmMove]);
Index: src/fMsg.pas
===================================================================
--- src/fMsg.pas (revision 7965)
+++ src/fMsg.pas (working copy)
@@ -17,10 +17,8 @@
procedure FormCreate(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormKeyPress(Sender: TObject; var Key: Char);
- private
- { Private declarations }
public
- { Public declarations }
+ ActionHandler: procedure(Tag: PtrInt) of object;
Escape: Integer;
iSelected: Integer;
procedure ButtonClick(Sender:TObject);
@@ -44,7 +42,7 @@
procedure TfrmMsg.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
- if (iSelected < 0) and (Escape >= 0) then iSelected:= Escape;
+ if (iSelected = -1) and (Escape >= 0) then iSelected:= Escape;
end;
procedure TfrmMsg.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
@@ -73,9 +71,20 @@
end;
procedure TfrmMsg.ButtonClick(Sender: TObject);
+var
+ aTag: PtrInt;
begin
- iSelected:= (Sender as TComponent).Tag;
- Close;
+ aTag:= (Sender as TComponent).Tag;
+ if (aTag < -1) then
+ begin
+ if Assigned(ActionHandler) then
+ ActionHandler(aTag);
+ end
+ else
+ begin
+ iSelected:= aTag;
+ Close;
+ end;
end;
procedure TfrmMsg.MouseUpEvent(Sender: TObject; Button: TMouseButton;
@@ -84,8 +93,7 @@
{$IF DEFINED(LCLGTK) or DEFINED(LCLGTK2)}
if (Button = mbLeft) and (Sender = FindLCLControl(Mouse.CursorPos)) then
begin
- iSelected:= (Sender as TButton).Tag;
- Close;
+ ButtonClick(Sender);
end;
{$ENDIF}
end;
Index: src/platform/uosforms.pas
===================================================================
--- src/platform/uosforms.pas (revision 7965)
+++ src/platform/uosforms.pas (working copy)
@@ -319,9 +319,9 @@
end;
// If parent window is normal window then call inherited method
- if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
- Result:= inherited ShowModal
- else
+// if GetWindowLong(ActiveWindow, GWL_HWNDPARENT) <> 0 then
+// Result:= inherited ShowModal
+// else
begin
Include(FFormState, fsModal);
FParentWindow := ActiveWindow;
Index: src/ulng.pas
===================================================================
--- src/ulng.pas (revision 7965)
+++ src/ulng.pas (working copy)
@@ -329,6 +329,7 @@
rsDlgButtonAbort = 'Ab&ort';
rsDlgButtonOther = 'Ot&her';
rsDlgButtonRetryAdmin = 'As Ad&ministrator';
+ rsDlgButtonCompare = 'Compare &by content';
rsDlgButtonContinue = '&Continue';
rsDlgButtonExitProgram = 'E&xit program';
Index: src/ushowform.pas
===================================================================
--- src/ushowform.pas (revision 7966)
+++ src/ushowform.pas (working copy)
@@ -43,11 +43,12 @@
TargetPath: String;
SourceFileSource: IFileSource;
TargetFileSource: IFileSource;
+ FModal: Boolean;
function GetRelativeFileName(const FullPath: string): string;
function GetRelativeFileNames: string;
function GetFromPath: string;
public
- constructor Create(aCopyOutOperation: TFileSourceCopyOperation);
+ constructor Create(aCopyOutOperation: TFileSourceCopyOperation; Modal: Boolean = False);
destructor Destroy; override;
procedure ShowWaitForm; override;
procedure Done; override;
@@ -56,7 +57,7 @@
State: TFileSourceOperationState);
end;
- TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData);
+ TToolDataPreparedProc = procedure(const FileList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
// Callback may be called either asynchoronously or synchronously (for modal operations)
// pdrInCallback is returned when FunctionToCall either will be called or was already called
@@ -63,7 +64,8 @@
TPrepareDataResult = (pdrFailed, pdrSynchronous, pdrInCallback);
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
procedure PrepareToolData(FileSource: IFileSource; var SelectedFiles: TFiles;
FunctionToCall: TToolDataPreparedProc); overload;
@@ -74,7 +76,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc); overload;
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False); overload;
procedure RunExtDiffer(CompareList: TStringList);
@@ -82,7 +85,7 @@
procedure ShowEditorByGlob(WaitData: TEditorWaitData); overload;
procedure ShowDifferByGlob(const LeftName, RightName: String);
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
procedure ShowViewerByGlob(const sFileName: String);
procedure ShowViewerByGlobList(const FilesToView: TStringList;
@@ -94,7 +97,7 @@
SysUtils, Process, DCProcessUtf8, Dialogs, LCLIntf,
uShellExecute, uGlobs, uOSUtils, fEditor, fViewer, uDCUtils,
uTempFileSystemFileSource, uLng, fDiffer, uDebug, DCOSUtils, uShowMsg,
- DCStrUtils, uFileSourceProperty,
+ DCStrUtils, uFileSourceProperty, uWfxPluginCopyOutOperation,
uFileSourceOperationOptions, uOperationsManager, uFileSourceOperationTypes,
uMultiArchiveFileSource, fFileExecuteYourSelf;
@@ -265,7 +268,7 @@
ShowDiffer(LeftName, RightName);
end;
-procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData);
+procedure ShowDifferByGlobList(const CompareList: TStringList; WaitData: TWaitData; Modal: Boolean = False);
begin
if gExternalTools[etDiffer].Enabled then
begin
@@ -275,7 +278,7 @@
RunExtDiffer(CompareList);
end
else
- ShowDiffer(CompareList[0], CompareList[1], WaitData);
+ ShowDiffer(CompareList[0], CompareList[1], WaitData, Modal);
end;
procedure ShowViewerByGlobList(const FilesToView : TStringList;
@@ -349,7 +352,7 @@
{ TEditorWaitData }
-constructor TEditorWaitData.Create(aCopyOutOperation: TFileSourceCopyOperation);
+constructor TEditorWaitData.Create(aCopyOutOperation: TFileSourceCopyOperation; Modal: Boolean = False);
var
I: Integer;
aFileSource: ITempFileSystemFileSource;
@@ -363,6 +366,7 @@
FileTimes[I] := mbFileAge(Files[I].FullPath);
SourceFileSource := aFileSource;
TargetFileSource := aCopyOutOperation.FileSource as IFileSource;
+ FModal := Modal;
end;
destructor TEditorWaitData.Destroy;
@@ -389,12 +393,15 @@
function TEditorWaitData.GetFromPath: string;
begin
- Result := TargetFileSource.CurrentAddress + TargetPath;
+ if StrBegins(TargetPath, TargetFileSource.CurrentAddress) then
+ Result := TargetPath // Workaround for TGioFileSource
+ else
+ Result := TargetFileSource.CurrentAddress + TargetPath;
end;
procedure TEditorWaitData.ShowWaitForm;
begin
- ShowFileEditExternal(GetRelativeFileNames, GetFromPath, Self);
+ ShowFileEditExternal(GetRelativeFileNames, GetFromPath, Self, FModal);
end;
procedure TEditorWaitData.Done;
@@ -422,7 +429,10 @@
begin
Operation.AddStateChangedListener([fsosStopped], @OnCopyInStateChanged);
Operation.FileExistsOption:= fsoofeOverwrite;
- OperationsManager.AddOperation(Operation);
+ if FModal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
DoNotFreeYet:= True; // Will be free in operation
end;
end
@@ -635,7 +645,8 @@
{ PrepareData }
function PrepareData(FileSource: IFileSource; var SelectedFiles: TFiles;
- FunctionToCall: TFileSourceOperationStateChangedNotify): TPrepareDataResult;
+ FunctionToCall: TFileSourceOperationStateChangedNotify;
+ Modal: Boolean = False): TPrepareDataResult;
var
aFile: TFile;
I: Integer;
@@ -669,6 +680,8 @@
TempFileSource,
TempFiles,
TempFileSource.FileSystemRoot);
+ if Operation is TWfxPluginCopyOutOperation then
+ (Operation as TWfxPluginCopyOutOperation).NeedsConnection := False; // use separate connection
finally
TempFiles.Free;
end;
@@ -681,7 +694,10 @@
Operation.AddStateChangedListener([fsosStopped], FunctionToCall);
- OperationsManager.AddOperation(Operation);
+ if Modal then
+ OperationsManager.AddOperationModal(Operation)
+ else
+ OperationsManager.AddOperation(Operation);
Exit(pdrInCallback);
end;
@@ -762,6 +778,7 @@
protected
FFunc: TToolDataPreparedProc;
FCallOnFail: Boolean;
+ FModal: Boolean;
FFailed: Boolean;
FFileList1: TStringList;
FFileList2: TStringList;
@@ -777,7 +794,8 @@
public
constructor Create(FunctionToCall: TToolDataPreparedProc; CallOnFail: Boolean = False);
procedure Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
destructor Destroy; override;
end;
@@ -788,11 +806,14 @@
end;
procedure TToolDataPreparator2.Prepare(FileSource1: IFileSource; var SelectedFiles1: TFiles;
- FileSource2: IFileSource; var SelectedFiles2: TFiles);
+ FileSource2: IFileSource; var SelectedFiles2: TFiles;
+ Modal: Boolean = False);
var
I: Integer;
begin
- case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1) of
+ FModal := Modal;
+
+ case PrepareData(FileSource1, SelectedFiles1, @OnCopyOutStateChanged1, Modal) of
pdrSynchronous:
begin
FFileList1 := TStringList.Create;
@@ -804,7 +825,7 @@
begin
try
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
finally
Free;
end;
@@ -812,7 +833,7 @@
end;
end;
- case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2) of
+ case PrepareData(FileSource2, SelectedFiles2, @OnCopyOutStateChanged2, Modal) of
pdrSynchronous:
begin
FFileList2 := TStringList.Create;
@@ -840,7 +861,7 @@
begin
if Operation.Result = fsorFinished then
begin
- FWaitData1 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation);
+ FWaitData1 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation, FModal);
FFileList1 := FWaitData1.GetFileList;
end
else
@@ -863,7 +884,7 @@
begin
if Operation.Result = fsorFinished then
begin
- FWaitData2 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation);
+ FWaitData2 := TEditorWaitData.Create(Operation as TFileSourceCopyOperation, FModal);
FFileList2 := FWaitData2.GetFileList;
end
else
@@ -886,7 +907,7 @@
if FFailed then
begin
if FCallOnFail then
- FFunc(nil, nil);
+ FFunc(nil, nil, FModal);
Exit;
end;
if Assigned(FFileList2) then
@@ -897,10 +918,10 @@
WaitData := TWaitDataDouble.Create(FWaitData1, FWaitData2);
FWaitData1 := nil;
FWaitData2 := nil;
- FFunc(FFileList1, WaitData);
+ FFunc(FFileList1, WaitData, FModal);
end
else
- FFunc(FFileList1, nil);
+ FFunc(FFileList1, nil, FModal);
finally
Free;
end;
@@ -936,7 +957,8 @@
procedure PrepareToolData(FileSource1: IFileSource; File1: TFile;
FileSource2: IFileSource; File2: TFile;
- FunctionToCall: TToolDataPreparedProc);
+ FunctionToCall: TToolDataPreparedProc;
+ Modal: Boolean = False);
var Files1, Files2: TFiles;
begin
Files1 := TFiles.Create(File1.Path);
@@ -946,7 +968,7 @@
try
Files2.Add(File2.Clone);
with TToolDataPreparator2.Create(FunctionToCall) do
- Prepare(FileSource1, Files1, FileSource2, Files2);
+ Prepare(FileSource1, Files1, FileSource2, Files2, Modal);
finally
Files2.Free;
end;
Index: src/uShowMsg.pas
===================================================================
--- src/uShowMsg.pas (revision 7965)
+++ src/uShowMsg.pas (working copy)
@@ -54,9 +54,14 @@
msmbAppend, msmbResume, msmbCopyInto, msmbCopyIntoAll,
msmbOverwrite, msmbOverwriteAll, msmbOverwriteOlder,
msmbOverwriteSmaller, msmbOverwriteLarger, msmbAutoRenameSource, msmbRenameSource,
- msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin);
+ msmbSkip, msmbSkipAll, msmbIgnore, msmbIgnoreAll, msmbAll, msmbRetry, msmbAbort, msmbRetryAdmin,
+ // Actions, they do not close the form and therefore have no corresponding result value:
+ msmbCompare);
+ TMyMsgActionButton = msmbCompare..High(TMyMsgButton);
+ TMyMsgActionHandler = procedure(Button: TMyMsgActionButton) of object;
+
{ TDialogMainThread }
TDialogMainThread = class
@@ -103,7 +108,7 @@
procedure msgError(const sMsg: String); overload;
procedure msgError(Thread: TThread; const sMsg: String); overload;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult; overload;
function MsgBox(Thread: TThread; const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton): TMyMsgResult; overload;
function MsgTest:TMyMsgResult;
@@ -283,7 +288,10 @@
Caption:= cLngButton[Buttons[iIndex]];
Parent:= frmMsg.pnlButtons;
Constraints.MinWidth:= MinButtonWidth;
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
OnClick:= frmMsg.ButtonClick;
OnMouseUp:= frmMsg.MouseUpEvent;
if Buttons[iIndex] = ButDefault then
@@ -308,9 +316,13 @@
for iIndex:= 0 to pred(frmMsg.ComponentCount) do
begin
if frmMsg.Components[iIndex] is TButton then
- begin
- with frmMsg.Components[iIndex] as TButton do TabOrder:=(tag+(iCount+1)-iIndexDefault) mod (iCount+1); //Tricky but it does it, no "if", no negative after to check, etc.
- end;
+ with frmMsg.Components[iIndex] as TButton do
+ begin
+ if Tag >= 0 then
+ TabOrder:= (Tag+(iCount+1)-iIndexDefault) mod (iCount+1) //Tricky but it does it, no "if", no negative after to check, etc.
+ else
+ TabOrder:= (-2-Tag+(iCount+1)-iIndexDefault) mod (iCount+1);
+ end;
end;
end;
@@ -332,7 +344,10 @@
MenuItem:= TMenuItem.Create(frmMsg.mnuOther);
with MenuItem do
begin
- Tag:= iIndex;
+ if Buttons[iIndex] >= Low(TMyMsgActionButton) then
+ Tag:= -2-iIndex
+ else
+ Tag:= iIndex;
Caption:= cLngButton[Buttons[iIndex]];
OnClick:= frmMsg.ButtonClick;
frmMsg.mnuOther.Items.Add(MenuItem);
@@ -341,14 +356,33 @@
end;
end;
-function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape:TMyMsgButton):TMyMsgResult;
+type TMsgBoxHelper = class
+ Buttons: array of TMyMsgButton;
+ ActionHandler: TMyMsgActionHandler;
+ procedure MsgBoxActionHandler(Tag: PtrInt);
+end;
+
+procedure TMsgBoxHelper.MsgBoxActionHandler(Tag: PtrInt);
+begin
+ ActionHandler(Buttons[-Tag-2]);
+end;
+
+function MsgBox(const sMsg: String; const Buttons: array of TMyMsgButton; ButDefault, ButEscape: TMyMsgButton; ActionHandler: TMyMsgActionHandler = nil): TMyMsgResult;
var
frmMsg:TfrmMsg;
+ MsgBoxHelper: TMsgBoxHelper = nil;
+ I: Integer;
begin
frmMsg:=TfrmMsg.Create(Application);
try
+ MsgBoxHelper := TMsgBoxHelper.Create();
+ SetLength(MsgBoxHelper.Buttons, Length(Buttons));
+ for I := Low(Buttons) to High(Buttons) do
+ MsgBoxHelper.Buttons[I] := Buttons[I];
+ MsgBoxHelper.ActionHandler := ActionHandler;
+ frmMsg.ActionHandler := MsgBoxHelper.MsgBoxActionHandler;
- SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
+ SetMsgBoxParams(frmMsg, sMsg, Buttons, ButDefault, ButEscape);
frmMsg.ShowModal;
if (frmMsg.iSelected)=-1 then
@@ -359,6 +393,7 @@
Result:=TMyMsgResult(Buttons[frmMsg.iSelected]);
finally
frmMsg.Free;
+ MsgBoxHelper.Free;
end;
end;
@@ -769,6 +804,7 @@
cLngButton[msmbRetry] := rsDlgButtonRetry;
cLngButton[msmbAbort] := rsDlgButtonAbort;
cLngButton[msmbRetryAdmin] := rsDlgButtonRetryAdmin;
+ cLngButton[msmbCompare] := rsDlgButtonCompare;
for I:= Low(TMyMsgButton) to High(TMyMsgButton) do
begin
| ||||
| Fixed in Revision | 8197 | ||||
| Operating system | |||||
| Widgetset | |||||
| Architecture | |||||
|
|
Загрузил предварительный патч. Для всех операций, кроме CopyOut из WCX, когда плагин не поддерживает фоновые операции. GIO не тестировалось. Изменения в следующих файлах под вопросом, они потребовались для запуска модальной операции в процессе другой модальной операций (WFX FTP): src/filesources/ufilesourceoperationmisc.pas src/platform/uosforms.pas |
|
|
Новые версии патчей в соответствии с обсуждением здесь: https://doublecmd.sourceforge.io/forum/viewtopic.php?p=22589#p22589 2 - фикс сборки под линукс 3 - фикс закрытия по крестику после нажатия кнопки "сравнить" 4 - модальная операция распаковки 5 - модальный диффер 6 - фикс для gio |
|
|
Изменения "src/filesources/ufilesourceoperationmisc.pas" теоретически не должны иметь негативных последствий. Изменения "src/platform/uosforms.pas" - время покажет. >>>5 - модальный диффер Полагаю это временный вариант? Все таки модальным диффер должен быть только в этом конкретном случае. |
|
|
Да, модальность в таком виде только для проверки добавлена. Надеялся, что обойдется вообще без нее - под win почему-то и без нее работает. В конечной версии сделаю только для вызовов из этого окна. А в перспективе есть идея само окно подтверждения file exists сделать немодальным, что скажете? Открыть его немодально и заблокировать поток операции на mutex, который освободить при закрытии окна. По идее, так для самого потока AskQuestion останется "модальным", но всё остальное приложение блокироваться не будет. |
|
|
7 - добавлен отладочный вывод 8 - фикс сборки под линукс 9 - модальные операции и диффер только из окна операции 10 - фикс сборки под линукс |
|
|
Можно как-то сделать опциональную поддержку GIO под Windows, как с SVG сделали? У GIMP в папке libgio dll тоже есть. file:// в таком случае я же смогу открывать? |
|
|
На постоянно его включать мне кажется излишним. А вот чисто для теста можно включить, надо лишь поправить имена библиотек, и добавить регистрацию GioFileSource. Полагаю file:// будет работать. Хотя как по мне проще поставить Линукс в VirtualBox и тестировать в реальном окружении. У меня к примеру десяток виртуальных машин для этого. |
|
|
11 - откачены изменения в gio до начальной версии, попытка исправить в другом файле 12 - наконец, рабочий фикс gio, причина оказалась в том, что File.FullPath содержит протокол (CurrentAddress), а от Files.Path при копировании ожидалось, что не будет его содержать 13 - альтернативный фикс, отрезание CurrentAddress вместо дополнительной проверки в CopyOut. Плюс workaround для отображения правильного пути обратного копирования. 14 - модальное окно ожидания внешнего редактора и операция обратного копирования (при запуске из окна замены). Основан на версии 12 + фикс пути из версии 13. |
|
|
Применил последнюю версию патча. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2016-09-19 02:22 | cordylus | New Issue | |
| 2018-01-08 08:21 | cordylus | File Added: bug1536-preview1.patch | |
| 2018-01-08 08:21 | cordylus | Note Added: 0002497 | |
| 2018-01-08 16:51 | cordylus | File Added: bug1536-preview2.patch | |
| 2018-01-08 17:03 | cordylus | Note Edited: 0002497 | |
| 2018-01-08 18:22 | cordylus | File Added: bug1536-preview3.patch | |
| 2018-01-08 18:28 | cordylus | Note Added: 0002501 | |
| 2018-01-08 22:56 | cordylus | File Added: bug1536-preview4.patch | |
| 2018-01-09 01:10 | cordylus | File Added: bug1536-preview5.patch | |
| 2018-01-09 02:58 | cordylus | File Added: bug1536-preview6.patch | |
| 2018-01-09 03:06 | cordylus | Note Edited: 0002501 | |
| 2018-01-09 08:11 | Alexx2000 | Note Added: 0002502 | |
| 2018-01-10 01:09 | cordylus | File Added: bug1536-preview7.patch | |
| 2018-01-10 01:34 | cordylus | Note Added: 0002503 | |
| 2018-01-10 01:39 | cordylus | File Added: bug1536-preview8.patch | |
| 2018-01-10 05:53 | cordylus | File Added: bug1536-preview9.patch | |
| 2018-01-10 05:55 | cordylus | Note Added: 0002504 | |
| 2018-01-10 19:18 | cordylus | File Added: bug1536-preview10.patch | |
| 2018-01-10 23:04 | cordylus | Note Edited: 0002504 | |
| 2018-01-10 23:11 | cordylus | Note Added: 0002505 | |
| 2018-01-13 21:47 | cordylus | File Added: bug1536-preview11.patch | |
| 2018-01-14 00:57 | Alexx2000 | Note Added: 0002507 | |
| 2018-01-17 09:44 | cordylus | File Added: bug1536-preview12.patch | |
| 2018-01-19 10:12 | cordylus | File Added: bug1536-preview13.patch | |
| 2018-01-19 10:30 | cordylus | Note Added: 0002508 | |
| 2018-01-19 10:34 | cordylus | Note Edited: 0002508 | |
| 2018-01-20 00:58 | cordylus | File Added: bug1536-preview14.patch | |
| 2018-01-20 01:00 | cordylus | Note Edited: 0002508 | |
| 2018-07-08 14:35 | Alexx2000 | Note Added: 0002671 | |
| 2018-07-08 14:35 | Alexx2000 | Status | new => feedback |
| 2018-07-08 14:36 | Alexx2000 | Fixed in Revision | => 8197 |
| 2018-07-08 14:36 | Alexx2000 | Target Version | => 0.9.0 |
| 2018-12-10 09:00 | Alexx2000 | Status | feedback => resolved |
| 2018-12-10 09:00 | Alexx2000 | Fixed in Version | => 0.9.0 |
| 2018-12-10 09:00 | Alexx2000 | Resolution | open => fixed |
| 2018-12-10 09:00 | Alexx2000 | Assigned To | => Alexx2000 |
| 2021-09-05 15:10 | Alexx2000 | Status | resolved => closed |