mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
ADD: Processing file comments
This commit is contained in:
parent
d4f2745228
commit
cbd3d2b699
10 changed files with 340 additions and 10 deletions
|
|
@ -49,7 +49,7 @@
|
|||
<PackageName Value="imagesforlazarus"/>
|
||||
</Item5>
|
||||
</RequiredPackages>
|
||||
<Units Count="34">
|
||||
<Units Count="35">
|
||||
<Unit0>
|
||||
<Filename Value="doublecmd.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
|
@ -319,6 +319,11 @@
|
|||
<ResourceFilename Value="ftweakplugin.lrs"/>
|
||||
<UnitName Value="fTweakPlugin"/>
|
||||
</Unit33>
|
||||
<Unit34>
|
||||
<Filename Value="udescr.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="uDescr"/>
|
||||
</Unit34>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ uses
|
|||
uPixMapManager, uVFS, fFileAssoc,
|
||||
KASComp, fconfigtoolbar, uWCXprototypes, uDCUtils, uOSUtils,
|
||||
dmDialogs, fViewer, fOptions, fCopyDlg, fMoveDlg, fFindDlg,
|
||||
fSymLink, fMultiRename, fSplitter, fPackDlg, fExtractDlg;
|
||||
fSymLink, fMultiRename, fSplitter, fPackDlg, fExtractDlg, uDescr;
|
||||
|
||||
{$IFDEF MSWINDOWS}
|
||||
{$R XP.res}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ type
|
|||
|
||||
implementation
|
||||
uses
|
||||
LCLProc, SysUtils, Classes, uLng, uGlobs, uLog, uShowMsg, uFileProcs, uFindEx, uDCUtils, uOSUtils, uClassesEx;
|
||||
LCLProc, SysUtils, Classes, uLng, uGlobs, uLog, uShowMsg, uFileProcs, uFindEx,
|
||||
uDCUtils, uOSUtils, uClassesEx, uDescr;
|
||||
|
||||
procedure TCopyThread.MainExecute;
|
||||
var
|
||||
|
|
@ -44,6 +45,7 @@ begin
|
|||
FReplaceAll:=False;
|
||||
FSkipAll:=False;
|
||||
iCoped:=0;
|
||||
|
||||
for xIndex:=0 to NewFileList.Count-1 do // copy
|
||||
begin
|
||||
if Terminated then
|
||||
|
|
@ -70,6 +72,7 @@ begin
|
|||
FFileOpDlg.iProgress2Pos:=iCoped;
|
||||
Synchronize(@FFileOpDlg.UpdateDlg);
|
||||
end;
|
||||
|
||||
// writeln('iCoped:',iCoped,' FFileSize', FFilesSize);
|
||||
end;
|
||||
|
||||
|
|
@ -138,6 +141,10 @@ begin
|
|||
end;
|
||||
Result:=CopyFile(fr^.sName, sDst+fr^.sPath+sDstNew, FAppend);
|
||||
|
||||
// process comments if need
|
||||
if Result and gProcessComments and Assigned(FDescr) then
|
||||
FDescr.CopyDescription(fr^.sName, sDst+fr^.sPath+sDstNew);
|
||||
|
||||
if Result then
|
||||
// write log success
|
||||
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ begin
|
|||
logWrite(Self, Format(rsMsgLogError+rsMsgLogDelete, [fr^.sName]), lmtError);
|
||||
|
||||
end;
|
||||
// process comments if need
|
||||
if Result and gProcessComments and Assigned(FDescr) then
|
||||
FDescr.DeleteDescription(fr^.sName);
|
||||
except
|
||||
DebugLN('Can not delete ', fr^.sName);
|
||||
end;
|
||||
|
|
|
|||
293
udescr.pas
Normal file
293
udescr.pas
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
{
|
||||
Double commander
|
||||
-------------------------------------------------------------------------
|
||||
This unit contains class for working with file comments.
|
||||
|
||||
Copyright (C) 2008 Koblov Alexander (Alexx2000@mail.ru)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
}
|
||||
|
||||
unit uDescr;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, uClassesEx;
|
||||
|
||||
type
|
||||
|
||||
{ TDescription }
|
||||
|
||||
TDescription = class(TStringListEx)
|
||||
private
|
||||
FLastDescrFile: String;
|
||||
FDestDescr: TDescription;
|
||||
procedure PrepareDescrFile(FileName: String);
|
||||
function Find(const S: string; var Index: Integer): Boolean; override;
|
||||
function GetDescription(Index: Integer): String;
|
||||
function GetDescription(const FileName: String): String;
|
||||
procedure SetDescription(Index: Integer; const AValue: String);
|
||||
procedure SetDescription(const FileName: String; const AValue: String);
|
||||
public
|
||||
{en
|
||||
Create TDescription class
|
||||
@param(UseSubDescr @true if need Copy/Move functions)
|
||||
}
|
||||
constructor Create(UseSubDescr: Boolean);
|
||||
{en
|
||||
Destroy TDescription class
|
||||
}
|
||||
destructor Destroy; override;
|
||||
{en
|
||||
Add description for file
|
||||
@param(FileName File name)
|
||||
@param(Descr Description)
|
||||
@returns(Index of added item)
|
||||
}
|
||||
function AddDescription(FileName, Descr: String): Integer;
|
||||
{en
|
||||
Read description by file name
|
||||
@param(FileName File name)
|
||||
@returns(Description of file)
|
||||
}
|
||||
function ReadDescription(FileName: String): String;
|
||||
{en
|
||||
Write description for file
|
||||
@param(FileName File name)
|
||||
@param(Descr Description)
|
||||
}
|
||||
procedure WriteDescription(FileName: String; const Descr: String);
|
||||
{en
|
||||
Delete description by file name
|
||||
@param(FileName File name)
|
||||
@returns(The function returns @true if successful, @false otherwise)
|
||||
}
|
||||
function DeleteDescription(const FileName: String): Boolean;
|
||||
{en
|
||||
Copy description for file
|
||||
@param(FileNameFrom Source file name)
|
||||
@param(FileNameTo Destination file name)
|
||||
@returns(The function returns @true if successful, @false otherwise)
|
||||
}
|
||||
function CopyDescription(const FileNameFrom, FileNameTo: String): Boolean;
|
||||
{en
|
||||
Move description for file
|
||||
@param(FileNameFrom Source file name)
|
||||
@param(FileNameTo Destination file name)
|
||||
@returns(The function returns @true if successful, @false otherwise)
|
||||
}
|
||||
function MoveDescription(const FileNameFrom, FileNameTo: String): Boolean;
|
||||
{en
|
||||
Save all changes to description file
|
||||
}
|
||||
procedure SaveDescription;
|
||||
{en
|
||||
Get description by file name
|
||||
}
|
||||
property DescrByFileName[const FileName: String]: String read GetDescription write SetDescription;
|
||||
{en
|
||||
Get description by file name index
|
||||
}
|
||||
property DescrByIndex[Index: Integer]: String read GetDescription write SetDescription;
|
||||
end;
|
||||
|
||||
implementation
|
||||
uses
|
||||
LCLProc, uOSUtils;
|
||||
|
||||
{ TDescription }
|
||||
|
||||
procedure TDescription.PrepareDescrFile(FileName: String);
|
||||
var
|
||||
sDescrFile: String;
|
||||
begin
|
||||
sDescrFile:= ExtractFilePath(FileName) + 'descript.ion';
|
||||
if sDescrFile <> FLastDescrFile then
|
||||
begin
|
||||
SaveToFile(FLastDescrFile);
|
||||
FLastDescrFile:= sDescrFile;
|
||||
if mbFileExists(FLastDescrFile) then
|
||||
LoadFromFile(FLastDescrFile);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDescription.Find(const S: string; var Index: Integer): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
sFileName: String;
|
||||
begin
|
||||
Result:= False;
|
||||
sFileName:= ExtractFileName(S);
|
||||
for I:= Count-1 downto 0 do
|
||||
begin
|
||||
DebugLn(Self[I]);
|
||||
if Pos(sFileName, Self[I]) <> 0 then
|
||||
begin
|
||||
Index:= I;
|
||||
Exit(True);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDescription.GetDescription(Index: Integer): String;
|
||||
var
|
||||
sLine: String;
|
||||
iDescrStart: Integer;
|
||||
begin
|
||||
sLine:= Self[Index];
|
||||
if Pos(#34, sLine) <> 1 then
|
||||
begin
|
||||
iDescrStart:= Pos(#32, sLine);
|
||||
Result:= Copy(sLine, iDescrStart+1, Length(sLine) - iDescrStart);
|
||||
end
|
||||
else
|
||||
begin
|
||||
iDescrStart:= Pos(#34#32, sLine);
|
||||
Result:= Copy(sLine, iDescrStart+1, Length(sLine) - iDescrStart);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDescription.GetDescription(const FileName: String): String;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
Result:= '';
|
||||
if Find(FileName, I) then
|
||||
Result:= GetDescription(I);
|
||||
end;
|
||||
|
||||
procedure TDescription.SetDescription(Index: Integer; const AValue: String);
|
||||
var
|
||||
sLine,
|
||||
sFileName: String;
|
||||
iDescrStart: Integer;
|
||||
begin
|
||||
sLine:= Self[Index];
|
||||
if Pos('"', sLine) <> 1 then
|
||||
begin
|
||||
iDescrStart:= Pos(#32, sLine);
|
||||
sFileName:= Copy(sLine, 1, iDescrStart);
|
||||
Self[Index]:= sFileName + AValue;
|
||||
end
|
||||
else
|
||||
begin
|
||||
iDescrStart:= Pos(#34#32, sLine);
|
||||
sFileName:= Copy(sLine, 1, iDescrStart+1);
|
||||
Self[Index]:= sFileName + AValue;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDescription.SetDescription(const FileName: String;
|
||||
const AValue: String);
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
if Find(FileName, I) then
|
||||
SetDescription(I, AValue)
|
||||
else
|
||||
AddDescription(FileName, AValue);
|
||||
end;
|
||||
|
||||
constructor TDescription.Create(UseSubDescr: Boolean);
|
||||
begin
|
||||
if UseSubDescr then
|
||||
FDestDescr:= TDescription.Create(False)
|
||||
else
|
||||
FDestDescr:= nil;
|
||||
inherited Create;
|
||||
end;
|
||||
|
||||
destructor TDescription.Destroy;
|
||||
begin
|
||||
if Assigned(FDestDescr) then
|
||||
FreeAndNil(FDestDescr);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TDescription.AddDescription(FileName, Descr: String): Integer;
|
||||
begin
|
||||
FileName:= ExtractFileName(FileName);
|
||||
if Pos(#32, FileName) <> 0 then
|
||||
Add(#34+FileName+#34#32+Descr)
|
||||
else
|
||||
Add(FileName+#32+Descr)
|
||||
end;
|
||||
|
||||
function TDescription.ReadDescription(FileName: String): String;
|
||||
begin
|
||||
PrepareDescrFile(FileName);
|
||||
Result:= GetDescription(FileName);
|
||||
end;
|
||||
|
||||
procedure TDescription.WriteDescription(FileName: String; const Descr: String);
|
||||
begin
|
||||
PrepareDescrFile(FileName);
|
||||
SetDescription(FileName, Descr);
|
||||
end;
|
||||
|
||||
function TDescription.DeleteDescription(const FileName: String): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
Result:= False;
|
||||
PrepareDescrFile(FileName);
|
||||
if Find(FileName, I) then
|
||||
begin
|
||||
Delete(I);
|
||||
Result:= True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDescription.CopyDescription(const FileNameFrom, FileNameTo: String): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
Result:= False;
|
||||
PrepareDescrFile(FileNameFrom);
|
||||
if Find(FileNameFrom, I) then
|
||||
begin
|
||||
DebugLn(FileNameFrom, '=', DescrByIndex[I]);
|
||||
FDestDescr.WriteDescription(FileNameTo, DescrByIndex[I]);
|
||||
Result:= True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDescription.MoveDescription(const FileNameFrom, FileNameTo: String): Boolean;
|
||||
var
|
||||
I: Integer;
|
||||
begin
|
||||
Result:= False;
|
||||
PrepareDescrFile(FileNameFrom);
|
||||
if Find(FileNameFrom, I) then
|
||||
begin
|
||||
DebugLn(FileNameFrom, '=', DescrByIndex[I]);
|
||||
FDestDescr.WriteDescription(FileNameTo, DescrByIndex[I]);
|
||||
Delete(I);
|
||||
Result:= True;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDescription.SaveDescription;
|
||||
begin
|
||||
SaveToFile(FLastDescrFile);
|
||||
if Assigned(FDestDescr) then
|
||||
FDestDescr.SaveDescription;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ unit uFileOpThread;
|
|||
interface
|
||||
|
||||
uses
|
||||
Classes, uFileList, fFileOpDlg, uTypes, fMsg, uShowMsg {$IFNDEF NOFAKETHREAD}, uFakeThread{$ENDIF};
|
||||
Classes, uFileList, fFileOpDlg, uTypes, uDescr, fMsg, uShowMsg {$IFNDEF NOFAKETHREAD}, uFakeThread{$ENDIF};
|
||||
|
||||
type
|
||||
{ TFileOpThread }
|
||||
|
|
@ -45,6 +45,7 @@ type
|
|||
FAppend: Boolean; // used mainly for pass information between move and copy
|
||||
FSymLinkAll, // process all symlinks
|
||||
FNotSymLinkAll : Boolean; // process all real files/folders
|
||||
FDescr: TDescription;
|
||||
|
||||
procedure Execute; override;
|
||||
procedure MainExecute; virtual; abstract; // main loop for copy /delete ...
|
||||
|
|
@ -76,7 +77,8 @@ const
|
|||
implementation
|
||||
|
||||
uses
|
||||
SysUtils, uLng, uFileProcs, uFileOp, Forms, uFindEx, uDCUtils, uOSUtils, LCLProc;
|
||||
SysUtils, uLng, uFileProcs, uFileOp, Forms, uFindEx, uDCUtils, uOSUtils,
|
||||
LCLProc, uGlobs;
|
||||
|
||||
{ TFileOpThread }
|
||||
|
||||
|
|
@ -212,6 +214,9 @@ try
|
|||
try
|
||||
FillAndCount; // gets full list of files (rekursive)
|
||||
|
||||
if gProcessComments then
|
||||
FDescr:= TDescription.Create(True);
|
||||
|
||||
if UseForm then
|
||||
begin
|
||||
//FFileOpDlg:=TfrmFileOp.Create(Application);
|
||||
|
|
@ -233,11 +238,16 @@ try
|
|||
|
||||
finally
|
||||
if UseForm then
|
||||
begin
|
||||
Synchronize(@FFileOpDlg.Close);
|
||||
DebugLN('TFileOpThread finally');
|
||||
end;
|
||||
if assigned(NewFileList) then
|
||||
begin
|
||||
Synchronize(@FFileOpDlg.Close);
|
||||
DebugLN('TFileOpThread finally');
|
||||
end;
|
||||
if gProcessComments and Assigned(FDescr) then
|
||||
begin
|
||||
FDescr.SaveDescription;
|
||||
FreeAndNil(FDescr);
|
||||
end;
|
||||
if Assigned(NewFileList) then
|
||||
FreeAndNil(NewFileList);
|
||||
end;
|
||||
except
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ var
|
|||
gCopyBlockSize : Integer;
|
||||
gDropReadOnlyFlag : Boolean = True;
|
||||
gWipePassNumber: Integer;
|
||||
gProcessComments: Boolean;
|
||||
|
||||
gRenameSelOnlyName:boolean;
|
||||
|
||||
|
|
@ -478,6 +479,7 @@ begin
|
|||
gDropReadOnlyFlag := gIni.ReadBool('Configuration', 'DropReadOnlyFlag', True);
|
||||
gUseMmapInSearch := gIni.ReadBool('Configuration', 'UseMmapInSearch', False);
|
||||
gWipePassNumber:= gIni.ReadInteger('Configuration', 'WipePassNumber', 1);
|
||||
gProcessComments := gIni.ReadBool('Configuration', 'ProcessComments', True);
|
||||
gRenameSelOnlyName:= gIni.ReadBool('Configuration', 'RenameSelOnlyName', false);
|
||||
{ Log }
|
||||
gLogFile := gIni.ReadBool('Configuration', 'LogFile', True);
|
||||
|
|
@ -639,6 +641,7 @@ begin
|
|||
gIni.WriteBool('Configuration', 'DropReadOnlyFlag', gDropReadOnlyFlag);
|
||||
gIni.WriteBool('Configuration', 'UseMmapInSearch', gUseMmapInSearch);
|
||||
gIni.WriteInteger('Configuration', 'WipePassNumber', gWipePassNumber);
|
||||
gIni.WriteBool('Configuration', 'ProcessComments', gProcessComments);
|
||||
gIni.WriteBool('Configuration', 'RenameSelOnlyName', gRenameSelOnlyName);
|
||||
{ Log }
|
||||
gIni.WriteBool('Configuration', 'LogFile', gLogFile);
|
||||
|
|
|
|||
|
|
@ -119,6 +119,10 @@ begin
|
|||
end
|
||||
else
|
||||
begin // rename succes
|
||||
// process comments if need
|
||||
if gProcessComments and Assigned(FDescr) then
|
||||
FDescr.MoveDescription(pr^.sName, sDstPath+pr^.sPath+ sDstNew);
|
||||
// write log
|
||||
if (log_cp_mv_ln in gLogOptions) and (log_success in gLogOptions) then
|
||||
logWrite(Self, Format(rsMsgLogSuccess+rsMsgLogMove, [pr^.sName+' -> '+sDstPath+pr^.sPath+ sDstNew]), lmtSuccess)
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@ uosforms.pas
|
|||
uvfs.pas
|
||||
uexts.pas
|
||||
ufileprocs.pas
|
||||
udescr.pas
|
||||
|
|
|
|||
|
|
@ -368,6 +368,10 @@ begin
|
|||
WipeDir(fr^.sName)
|
||||
else // files
|
||||
WipeFile(fr^.sName);
|
||||
|
||||
// process comments if need
|
||||
if gProcessComments and Assigned(FDescr) then
|
||||
FDescr.DeleteDescription(fr^.sName);
|
||||
except
|
||||
DebugLn('Can not wipe ', fr^.sName);
|
||||
end;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue