Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1080 → Rev 1081

/Delphi/akTimeLog/Source/MainUnit.pas
0,0 → 1,746
// akTimeLog v3.0
// Copyright (c) 1999-2000 Anatoli Klassen
unit MainUnit;
 
interface
 
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, Menus, ShellApi, ExtCtrls, ImgList, AMAutoRun,
UtilsUnit, LogInfoUnit;
 
const
AK_NOTIFYICON = WM_USER + 2;
ID_ICON = 1;
 
type
TakTimeLogMainForm = class(TForm)
MainMenu: TMainMenu;
FileMenu: TMenuItem;
ExitItem: TMenuItem;
HelpMenu: TMenuItem;
AboutItem: TMenuItem;
StatusBar: TStatusBar;
IconPopupMenu: TPopupMenu;
ShowPopupItem: TMenuItem;
PopupMenuLine03: TMenuItem;
ExitPopupItem: TMenuItem;
Timer: TTimer;
MenuLine01: TMenuItem;
ChangePasswordItem: TMenuItem;
OptionsItem: TMenuItem;
HelpContentsItem: TMenuItem;
MenuImageList: TImageList;
PopupMenuLine01: TMenuItem;
ChangePasswordPopupItem: TMenuItem;
OptionsPopupItem: TMenuItem;
PopupMenuLine02: TMenuItem;
AboutPopupItem: TMenuItem;
HelpContentsPopupItem: TMenuItem;
AutoRun: TAMAutoRun;
TimeTree: TTreeView;
TreePopupMenu: TPopupMenu;
DeleteBranchPopupItem: TMenuItem;
EditMenu: TMenuItem;
DeleteBranchItem: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure ExitItemClick(Sender: TObject);
procedure AboutItemClick(Sender: TObject);
procedure ShowPopupItemClick(Sender: TObject);
procedure FormHide(Sender: TObject);
procedure TimerTimer(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure ChangePasswordItemClick(Sender: TObject);
procedure OptionsItemClick(Sender: TObject);
procedure HelpContentsItemClick(Sender: TObject);
procedure DeleteBranchItemClick(Sender: TObject);
procedure TimeTreeChange(Sender: TObject; Node: TTreeNode);
procedure TimeTreeKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
FShow : boolean;
FExit : boolean; // Exit item was clicked
FProgStart : TDateTime;
procedure IconCallBack(var WMN : TWMNotify); message AK_NOTIFYICON;
procedure SendParams(var WMN : TWMNotify); message AK_SENDPARAM;
procedure EndSession(var WMN : TWMNotify); message WM_QUERYENDSESSION;
procedure AddIcon;
procedure DeleteIcon;
procedure ModifyIcon(Tip : string);
procedure AppMinimize(Sender : TObject);
procedure CalcTime;
procedure DeleteTimeBranch(Branch : TTreeNode);
procedure DeleteTime(ATime : TDateTime; Kind : TInfoType);
function EncodeTime(Pwd : string;
Time : TDateTime; Position : longint) : Int64;
function DecodeTime(Pwd : string;
Code : Int64; Position : longint) : TDateTime;
public
procedure ShowWindow;
end;
 
var
akTimeLogMainForm: TakTimeLogMainForm;
 
implementation
 
uses AboutUnit, Registry, OptionsUnit, ChangePasswordUnit, PasswordUnit;
 
{$R *.DFM}
 
//= TakTimeLogMainForm =========================================================
 
procedure TakTimeLogMainForm.FormCreate(Sender: TObject);
var
Reg : TRegIniFile;
LogFile : file of Int64;
StartCode : Int64;
StopCode : Int64;
Pwd : string;
 
begin
try
Reg := TRegIniFile.Create(RegistryRoot);
 
Top := Reg.ReadInteger('Main Window', 'Top', Top);
Left := Reg.ReadInteger('Main Window', 'Left', Left);
Width := Reg.ReadInteger('Main Window', 'Width', Width);
Height := Reg.ReadInteger('Main Window', 'Height', Height);
 
Reg.Free;
except
end;
 
Application.OnMinimize := AppMinimize;
FExit := False;
FShow := False;
AddIcon;
 
if WriteLog then
try
System.Assign(LogFile, LogFileName);
try
System.Reset(LogFile);
System.Seek(LogFile, FileSize(LogFile));
except
System.Rewrite(LogFile);
end;
 
Pwd := DecodePassword(Password);
FProgStart := Now;
StartCode := EncodeTime(Pwd, FProgStart, System.FilePos(LogFile));
StopCode := EncodeTime(Pwd, FProgStart, System.FilePos(LogFile)+1);
 
Write(LogFile, StartCode);
Write(LogFile, StopCode);
System.Close(LogFile);
ModifyIcon('akTimeLog - Started ' + DateTimeToStr(FProgStart));
except
MessageBox(0, PChar('Error writting ' + LogFileName),
'akTimeLog', MB_ICONERROR or MB_OK);
end;
 
Timer.Enabled := True;
ShowPopupItem.Enabled := not Application.ShowMainForm;
end;
 
procedure TakTimeLogMainForm.CalcTime;
procedure AddItem(Info : TLogInfo);
var
Node : TTreeNode;
 
begin
case Info.InfoType of
itYear: Node := nil;
 
itMonth: begin
Node := TimeTree.Items.GetFirstNode;
while (Node <> nil) and not (((TLogInfo(Node.Data)).InfoType = itYear)
and ((TLogInfo(Node.Data)).Year = Info.Year))
do Node := Node.GetNext;
end;
 
itDay: begin
Node := TimeTree.Items.GetFirstNode;
while (Node <> nil) and not (((TLogInfo(Node.Data)).InfoType = itMonth)
and ((TLogInfo(Node.Data)).Month = Info.Month))
do Node := Node.GetNext;
end;
 
itTime: begin
Node := TimeTree.Items.GetFirstNode;
while (Node <> nil) and not (((TLogInfo(Node.Data)).InfoType = itDay)
and ((TLogInfo(Node.Data)).Day = Info.Day))
do Node := Node.GetNext;
end;
 
else Exit;
end;
 
Node := TimeTree.Items.AddChild(Node, '');
Node.Data := Info;
end;
 
procedure UpdateItems;
var
Node : TTreeNode;
Y, M, D : word;
 
begin
DecodeDate(Now, Y, M, D);
Node := TimeTree.Items.GetFirstNode;
while Node <> nil do
with TLogInfo(Node.Data) do begin
Node.Text := ToString;
 
case InfoType of
itYear : if Year = Y then Node.Expand(False);
itMonth : if Month = M then Node.Expand(False);
itDay : if Day = D then Node.Expand(False);
end;
 
Node := Node.GetNext;
end;
end;
 
var
Pwd : string;
LogFile : file of Int64;
StartCode : Int64;
StopCode : Int64;
StartTime : TDateTime;
StopTime : TDateTime;
Time1 : TDateTime;
Time2 : TDateTime;
Year, Month, Day, Time, Total : TLogInfo;
 
begin
DeleteTimeBranch(nil);
 
try
System.Assign(LogFile, LogFileName);
System.Reset(LogFile);
 
Pwd := DecodePassword(Password);
 
Total := nil;
Year := nil;
Month := nil;
Day := nil;
 
while not EoF(LogFile) do begin
Read(LogFile, StartCode, StopCode);
 
StartTime := DecodeTime(Pwd, StartCode, System.FilePos(LogFile)-2);
StopTime := DecodeTime(Pwd, StopCode, System.FilePos(LogFile)-1);
 
if StopTime < StartTime then begin
Application.MessageBox(PChar('Incorrect record in ' + LogFileName),
'akTimeLog', MB_OK or MB_ICONERROR);
Break;
end;
 
Time1 := StartTime;
Time2 := Trunc(Time1)+1;
 
repeat
if Time2 > StopTime then Time2 := StopTime;
 
Time := TLogInfo.Create(itTime, Time1, Time2);
 
if Total = nil then Total := TLogInfo.Create(itTotal, Time1, Time1);
 
if (Year = nil) or (Year.Year <> Time.Year) then begin
Year := TLogInfo.Create(itYear, Time1, Time1);
AddItem(Year);
end;
 
if (Month = nil) or (Month.Month <> Time.Month) then begin
Month := TLogInfo.Create(itMonth, Time1, Time1);
AddItem(Month);
end;
 
if (Day = nil) or (Day.Day <> Time.Day) then begin
Day := TLogInfo.Create(itDay, Time1, Time1);
AddItem(Day);
end;
 
AddItem(Time);
 
Total.AddTime(Time.Duration);
Year.AddTime(Time.Duration);
Month.AddTime(Time.Duration);
Day.AddTime(Time.Duration);
 
if Time2 >= StopTime then Break;
Time1 := Trunc(Time1)+1;
Time2 := Trunc(Time1)+1;
until False;
end;
 
System.Close(LogFile);
UpdateItems;
 
StatusBar.Panels[0].Text := Total.ToString;
Total.Free;
except
Application.MessageBox(PChar('Error reading ' + LogFileName),
'akTimeLog', MB_OK or MB_ICONERROR);
end;
end;
 
procedure TakTimeLogMainForm.DeleteTimeBranch(Branch : TTreeNode);
var
Node, Node2 : TTreeNode;
 
begin
if Branch = nil then
Node := TimeTree.Items.GetFirstNode
else
Node := Branch.GetFirstChild;
 
while Node <> nil do begin
DeleteTimeBranch(Node);
if Node.Data <> nil then TLogInfo(Node.Data).Free;
Node2 := Node.GetNextSibling;
Node.Delete;
Node := Node2;
end;
end;
 
procedure TakTimeLogMainForm.AddIcon;
var
ID : TNotifyIconData;
 
begin
if not WriteLog then Exit;
 
ID.cbSize := SizeOf(ID);
ID.Wnd := Handle;
 
ID.uID := ID_ICON;
ID.uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
ID.uCallbackMessage := AK_NOTIFYICON;
ID.hIcon := Icon.Handle;
ID.szTip := 'akTimeLog';
Shell_NotifyIcon(NIM_ADD, @ID);
end;
 
procedure TakTimeLogMainForm.ModifyIcon(Tip : string);
var
ID : TNotifyIconData;
 
begin
if not WriteLog then Exit;
 
ID.cbSize := SizeOf(ID);
ID.Wnd := Handle;
 
ID.uID := ID_ICON;
ID.uFlags := NIF_TIP;
StrPCopy(ID.szTip, Copy(Tip, 1, 62));
Shell_NotifyIcon(NIM_MODIFY, @ID);
end;
 
procedure TakTimeLogMainForm.DeleteIcon;
var
ID : TNotifyIconData;
 
begin
if not WriteLog then Exit;
 
ID.cbSize := SizeOf(ID);
ID.Wnd := Handle;
ID.uID := ID_ICON;
Shell_NotifyIcon(NIM_DELETE, @ID);
end;
 
procedure TakTimeLogMainForm.IconCallBack;
var
p : TPoint;
 
begin
inherited;
case longint(WMN.NMHdr) of
WM_RBUTTONUP: begin
GetCursorPos(p);
IconPopupMenu.Popup(p.x, p.y);
end;
 
WM_LBUTTONDBLCLK: begin
ShowWindow;
Application.Restore;
Application.BringToFront;
end;
end;
end;
 
procedure TakTimeLogMainForm.AppMinimize(Sender : TObject);
begin
if WriteLog then Hide;
end;
 
procedure TakTimeLogMainForm.ShowPopupItemClick(Sender: TObject);
begin
ShowWindow;
Application.Restore;
Application.BringToFront;
end;
 
procedure TakTimeLogMainForm.FormHide(Sender: TObject);
begin
ShowPopupItem.Enabled := True;
end;
 
procedure TakTimeLogMainForm.DeleteTime(ATime : TDateTime; Kind : TInfoType);
type
TTimes = array[0..MaxInt div 32] of TLogInfo;
 
var
LogFile : file of Int64;
Times : ^TTimes;
n, i, k : longint;
Code1, Code2 : Int64;
Pwd : string;
CurWritten : boolean;
TimeNow : TDateTime;
ControlTime : TLogInfo;
 
begin
try
Pwd := DecodePassword(Password);
CurWritten := False;
 
System.Assign(LogFile, LogFileName);
System.Reset(LogFile);
GetMem(Times, System.FileSize(LogFile) * SizeOf(Pointer) div 2);
 
n := 0;
while not EoF(LogFile) do begin
Read(LogFile, Code1, Code2);
Times^[n] := TLogInfo.Create(itTime,
DecodeTime(Pwd, Code1, n*2),
DecodeTime(Pwd, Code2, n*2+1));
Inc(n);
end;
System.Close(LogFile);
 
ControlTime := TLogInfo.Create(itTime, ATime, ATime);
System.Rewrite(LogFile);
k := 0;
for i := 0 to n-1 do begin
case Kind of
itTotal : Continue;
itYear : if Times^[i].Year = ControlTime.Year then Continue;
itMonth : if Times^[i].Month = ControlTime.Month then Continue;
itDay : if Times^[i].Day = ControlTime.Day then Continue;
itTime : if Times^[i].Start = ControlTime.Start then Continue;
end;
 
if Times^[i].Start = FProgStart then CurWritten := True;
Code1 := EncodeTime(Pwd, Times^[i].Start, k*2);
Code2 := EncodeTime(Pwd, Times^[i].Stop, k*2+1);
Write(LogFile, Code1, Code2);
Inc(k);
end;
 
if not CurWritten then begin
TimeNow := Now;
Code1 := EncodeTime(Pwd, TimeNow, k*2);
Code2 := EncodeTime(Pwd, TimeNow, k*2+1);
 
Write(LogFile, Code1, Code2);
end;
 
System.Close(LogFile);
FreeMem(Times, System.FileSize(LogFile) * SizeOf(Int64));
except
end;
end;
 
procedure TakTimeLogMainForm.TimerTimer(Sender: TObject);
var
LogFile : file of Int64;
CurTime : Int64;
Pwd : string;
 
begin
if WriteLog then
try
System.Assign(LogFile, LogFileName);
System.Reset(LogFile);
System.Seek(LogFile, FileSize(LogFile)-1);
 
Pwd := DecodePassword(Password);
CurTime := EncodeTime(Pwd, Now, System.FilePos(LogFile));
 
Write(LogFile, CurTime);
System.Close(LogFile);
 
CalcTime;
except
MessageBox(0, PChar('Error writting ' + LogFileName),
'akTimeLog', MB_ICONERROR or MB_OK);
end;
end;
 
procedure TakTimeLogMainForm.FormDestroy(Sender: TObject);
var
Reg : TRegIniFile;
 
begin
Timer.Enabled := False;
TimerTimer(Sender);
DeleteIcon;
 
try
Reg := TRegIniFile.Create(RegistryRoot);
 
Reg.WriteInteger('Main Window', 'Top', Top);
Reg.WriteInteger('Main Window', 'Left', Left);
Reg.WriteInteger('Main Window', 'Width', Width);
Reg.WriteInteger('Main Window', 'Height', Height);
 
Reg.Free;
except
end;
end;
 
procedure TakTimeLogMainForm.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
begin
if WriteLog and not FExit then begin
CanClose := False;
Hide;
end
else
CanClose := True;
end;
 
function TakTimeLogMainForm.EncodeTime
(Pwd : string; Time : TDateTime; Position : longint) : Int64;
var
i, p : longint;
PwdArray : array[1..8] of char;
PwdPart : int64 absolute PwdArray;
TimeInt : int64 absolute Time;
 
begin
Inc(Position);
if Pwd = '' then
Result := TimeInt
else begin
for i := 1 to 8 do begin
p := (Position+i-2) mod Length(Pwd) + 1;
PwdArray[i] := Pwd[p];
end;
 
Result := TimeInt xor PwdPart;
end
end;
 
function TakTimeLogMainForm.DecodeTime
(Pwd : string; Code : Int64; Position : longint) : TDateTime;
var
i, p : longint;
PwdArray : array[1..8] of char;
PwdPart : int64 absolute PwdArray;
Time : TDateTime absolute Code;
 
begin
Inc(Position);
if Pwd = '' then
Result := Time
else begin
for i := 1 to 8 do begin
p := (Position+i-2) mod Length(Pwd) + 1;
PwdArray[i] := Pwd[p];
end;
 
Code := Code xor PwdPart;
Result := Time;
end
end;
 
procedure TakTimeLogMainForm.ChangePasswordItemClick(Sender: TObject);
type
TTimeCodes = array[0..MaxInt div 16] of Int64;
 
var
OldPwd, NewPwd : string;
RetypeNewPwd : string;
LogFile : file of Int64;
TimeCodes : ^TTimeCodes;
n, i : longint;
TimeCode : Int64;
 
begin
if not ChangePasswordForm.Execute(OldPwd, NewPwd, RetypeNewPwd) then Exit;
 
if DecodePassword(Password) <> OldPwd then begin
Application.MessageBox('Incorrect old password',
'akTimeLog', MB_OK or MB_ICONERROR);
Exit;
end;
 
if (NewPwd <> '') and (NewPwd <> RetypeNewPwd) then begin
Application.MessageBox('You''ve entered not equal new passwords',
'akTimeLog', MB_OK or MB_ICONERROR);
Exit;
end;
 
if DecodePassword(Password) = NewPwd then Exit;
 
Password := EncodePassword(NewPwd);
 
try
System.Assign(LogFile, LogFileName);
System.Reset(LogFile);
GetMem(TimeCodes, System.FileSize(LogFile) * SizeOf(Int64));
n := 0;
while not EoF(LogFile) do begin
Read(LogFile, TimeCodes^[n], TimeCodes^[n+1]);
Inc(n, 2);
end;
System.Close(LogFile);
 
System.Rewrite(LogFile);
for i := 0 to n-1 do begin
TimeCode := EncodeTime(NewPwd, DecodeTime(OldPwd, TimeCodes^[i], i), i);
Write(LogFile, TimeCode);
end;
System.Close(LogFile);
FreeMem(TimeCodes, System.FileSize(LogFile) * SizeOf(Int64));
except
end;
end;
 
procedure TakTimeLogMainForm.OptionsItemClick(Sender: TObject);
begin
OptionsForm.Execute;
end;
 
procedure TakTimeLogMainForm.ExitItemClick(Sender: TObject);
begin
FExit := True;
Close;
end;
 
procedure TakTimeLogMainForm.HelpContentsItemClick(Sender: TObject);
begin
;
end;
 
procedure TakTimeLogMainForm.AboutItemClick(Sender: TObject);
begin
AboutBox.ShowModal;
end;
 
procedure TakTimeLogMainForm.SendParams(var WMN : TWMNotify);
var
Params : string;
LogFile : file of Int64;
StartCode : Int64;
StopCode : Int64;
StartTime : TDateTime;
Pwd : string;
 
begin
if MapHandle = 0 then Exit;
 
Params := MapFile;
DeleteIcon;
ParseParamsString(Params);
AddIcon;
 
if WriteLog then
try
System.Assign(LogFile, LogFileName);
try
System.Reset(LogFile);
System.Seek(LogFile, FileSize(LogFile));
except
System.Rewrite(LogFile);
end;
 
Pwd := DecodePassword(Password);
StartTime := Now;
StartCode := EncodeTime(Pwd, StartTime, System.FilePos(LogFile));
StopCode := EncodeTime(Pwd, StartTime, System.FilePos(LogFile)+1);
 
Write(LogFile, StartCode);
Write(LogFile, StopCode);
System.Close(LogFile);
ModifyIcon('akTimeLog - Started ' + DateTimeToStr(StartTime));
except
MessageBox(0, PChar('Error writting ' + LogFileName),
'akTimeLog', MB_ICONERROR or MB_OK);
end
else
Show;
end;
 
procedure TakTimeLogMainForm.EndSession(var WMN : TWMNotify);
begin
FExit := True;
WMN.Result := 1;
end;
 
procedure TakTimeLogMainForm.ShowWindow;
var
Pwd, Control : string;
 
begin
DeleteTimeBranch(nil);
ShowPopupItem.Enabled := False;
 
if Password <> '' then begin
Pwd := PasswordForm.Execute;
if Pwd = '' then Exit;
 
try
Control := DecodePassword(Password);
except
Application.MessageBox('Error during decoding the password',
'akTimeLog', MB_OK or MB_ICONERROR);
end;
 
if Pwd <> Control then begin
Application.MessageBox('Password Incorrect', 'akTimeLog',
MB_OK or MB_ICONERROR);
Exit;
end;
end;
 
DeleteBranchItem.Enabled := False;
DeleteBranchPopupItem.Enabled := False;
CalcTime;
Show;
end;
 
procedure TakTimeLogMainForm.DeleteBranchItemClick(Sender: TObject);
begin
if Application.MessageBox('Delete selected branch?', 'akTimeLog',
MB_YESNO or MB_ICONWARNING) = IDYES
then begin
with TLogInfo(TimeTree.Selected.Data) do
DeleteTime(Start, InfoType);
CalcTime;
end;
end;
 
procedure TakTimeLogMainForm.TimeTreeChange(Sender: TObject;
Node: TTreeNode);
begin
DeleteBranchItem.Enabled := True;
DeleteBranchPopupItem.Enabled := True;
end;
 
procedure TakTimeLogMainForm.TimeTreeKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_DELETE then DeleteBranchItemClick(Sender);
end;
 
end.