Files
lazarus-ccr/components/flashfiler/sourcelaz/server/uffsindx.pas
2016-12-07 13:31:59 +00:00

458 lines
12 KiB
ObjectPascal

{*********************************************************}
{* User-defined index dialog and maintenance for server *}
{*********************************************************}
(* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower FlashFiler
*
* The Initial Developer of the Original Code is
* TurboPower Software
*
* Portions created by the Initial Developer are Copyright (C) 1996-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** *)
unit uFFSIndx;
{$I FFDEFINE.INC}
interface
uses
Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ExtCtrls, Windows, Grids, ComCtrls, ToolWin, Menus,
{$IFDEF DCC4ORLATER}
ImgList,
{$ENDIF}
FFLLBase,
ffllgrid,
FFSrEng;
type
TffKeyProcItemRec = class(TffUCStrListItem)
kirTable : TffFullFileName;
kirIndexID : longint;
kirDLL : TffFullFileName;
kirBuildKey: TffName;
kirCompKey : TffName;
constructor Create;
end;
type
TFFIndexForm = class(TForm)
pnlBottom: TPanel;
btnSave: TBitBtn;
btnDiscard: TBitBtn;
dlgOpenTable: TOpenDialog;
dlgOpenDLL: TOpenDialog;
grdIndexes: TffStringGrid;
tbMain: TToolBar;
pbDelete: TToolButton;
ToolButton2: TToolButton;
pbBrowse: TToolButton;
imMain: TImageList;
mnuMain: TMainMenu;
mnuIndex: TMenuItem;
mnuIndexBrowse: TMenuItem;
mnuIndexDelete: TMenuItem;
procedure btnBrowseClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure grdIndexesExitCell(Sender: TffStringGrid; aCol,
aRow: Integer; const text: String);
procedure grdIndexesDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure grdIndexesKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure grdIndexesKeyPress(Sender: TObject; var Key: Char);
procedure grdIndexesSortColumn(Sender: TffStringGrid; aCol: Integer);
procedure grdIndexesSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
private
{ Private declarations }
FEngine : TffServerEngine;
procedure ifPopulateColHeaders;
procedure ifPopulateGrid;
procedure ifSetEngine(anEngine : TffServerEngine);
public
{ Public declarations }
property ServerEngine: TffServerEngine read FEngine write ifSetEngine;
end;
var
FFIndexForm: TFFIndexForm;
implementation
uses
FFLLUNC,
FFLLExcp,
FFSRBde,
FFSrCfg;
{$R *.DFM}
const
{ Column constants }
cnTableName = 0;
cnIndex = 1;
cnDLLName = 2;
cnBuildKey = 3;
cnCompareKey = 4;
{ Cell margin constants }
cnTopMargin = 2;
cnLeftMargin = 2;
{===TffKeyProcItemRec==================================================}
constructor TffKeyProcItemRec.Create;
begin
inherited Create('');
end;
{====================================================================}
{===Helper methods===================================================}
procedure TFFIndexForm.ifSetEngine(anEngine : TffServerEngine);
begin
FEngine := anEngine;
{ Set the row count. }
grdIndexes.RowCount := FEngine.Configuration.KeyProcList.Count + 2;
grdIndexes.Row := 1;
end;
{====================================================================}
{===Form methods=====================================================}
procedure TFFIndexForm.FormShow(Sender: TObject);
begin
ifPopulateColHeaders;
ifPopulateGrid;
grdIndexes.SetFocus;
end;
{====================================================================}
{===Grid methods & event handlers====================================}
procedure TFFIndexForm.grdIndexesDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
Grid : TffStringGrid absolute Sender;
aStr : string;
begin
{ Leave fixed portion of the grid alone}
if gdFixed in State then
Exit;
aStr := Grid.Cells[aCol, aRow];
with Grid do begin
if (aCol = cnTableName) or (aCol = cnDLLName) then begin
if (aStr <> '') and (not FFFileExists(aStr)) then begin
Canvas.Brush.Color := clRed;
Canvas.Font.Color := clWhite;
end;
end;
Canvas.FillRect(Rect);
Canvas.TextRect(Rect, Rect.Left + cnLeftMargin, Rect.Top + cnTopMargin, aStr);
end;
end;
{--------}
procedure TFFIndexForm.grdIndexesExitCell(Sender: TffStringGrid; aCol,
aRow: Integer; const text: String);
begin
if ((aCol = cnTableName) or (aCol = cnDLLName)) and
(Text <> '') and FFFileExists(Text) then
Sender.Cells[aCol, aRow] := FFExpandUNCFileName(text);
end;
{--------}
procedure TFFIndexForm.grdIndexesKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Grid : TffStringGrid absolute Sender;
begin
{ Change the selected cell (Enter as tab)}
case Key of
VK_RETURN :
with Grid do begin
if Col < Pred(ColCount) then
Col := Col + 1
else if Row < Pred(RowCount) then begin
Row := Row + 1;
Col := cnTableName;
end else begin
{ Is this cell blank? }
if Cells[Col, Row] = '' then begin
{ Yes. Wrap to first row of grid. }
Row := 1;
Col := cnTableName;
end else begin
{ No. Add a new blank row. }
RowCount := RowCount + 1;
Row := Pred(RowCount);
Col := cnTableName;
end;
end;
end;
VK_DOWN :
with Grid do begin
{ Are we trying to arrow down from an incomplete row? }
if (Row = pred(RowCount)) then
if AnyCellIsEmpty(Row) then begin
{ Yes. Do not allow this to occur. }
Key := 0;
MessageBeep(0);
end else
{ No. Make sure we have a new blank row. }
RowCount := RowCount + 1;
end;
VK_UP, VK_TAB :
with Grid do begin
{ Are we trying to arrow up from or Tab forward out of a new,
completed row? }
if (Row = pred(RowCount)) and RowIsFilled(Row) then
{ Yes. Add a new blank row. }
RowCount := RowCount + 1;
end;
end; { case }
end;
{--------}
procedure TFFIndexForm.grdIndexesKeyPress(Sender: TObject; var Key: Char);
const
validDigits = ['0'..'9'];
validEditKeys = [#8, #13];
var
Grid : TffStringGrid absolute Sender;
Ignore: Boolean;
Value: string;
begin
if not (Key in validEditKeys) then begin
{ Validate data entry as key's are pressed}
case Grid.Col of
cnTableName, cnDLLName :
begin
Value := Grid.Cells[Grid.Col, Grid.Row];
Ignore := (Length(Value) >= ffcl_Path);
end;
cnIndex :
Ignore := not (Key in validDigits);
else
Ignore := False;
end; { case }
if Ignore then begin
Key := #0;
MessageBeep(0);
end;
end;
end;
{--------}
procedure TFFIndexForm.grdIndexesSelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
pbBrowse.Enabled := (ACol = cnTableName) or (ACol = cnDLLName);
mnuIndexBrowse.Enabled := pbBrowse.Enabled;
end;
{--------}
procedure TFFIndexForm.grdIndexesSortColumn(Sender: TffStringGrid;
aCol: Integer);
var
aStr : string;
i, j : integer;
LastRow : integer;
begin
if (Sender.RowCount > 1) and (aCol <> cnIndex) then
with Sender do begin
if LastRowIsEmpty then
LastRow := (RowCount - 2)
else
LastRow := pred(RowCount);
BeginUpdate;
try
for i := 1 to LastRow do begin
SaveRow(i);
aStr := Cells[aCol, i];
j := i;
while (j > 1) and
(ansiCompareStr(Cells[aCol, j-1], aStr) > 0) do begin
CopyRow(j-1, j);
dec(j);
end; { while }
RestoreToRow(j);
end; { for }
finally
EndUpdate;
end;
end; { with }
end;
{--------}
procedure TFFIndexForm.ifPopulateColHeaders;
begin
with grdIndexes do begin
BeginUpdate;
try
Cells[cnTableName, 0] := 'Table Name & Path';
Cells[cnIndex, 0] := 'Index';
Cells[cnDLLName, 0] := 'DLL Name & Path';
Cells[cnBuildKey, 0] := 'Build Key';
Cells[cnCompareKey, 0] := 'Compare Key';
finally
EndUpdate;
end;
end;
end;
{--------}
procedure TFFIndexForm.ifPopulateGrid;
var
Item : TffKeyProcItem;
Inx : integer;
begin
with grdIndexes do begin
BeginUpdate;
try
for Inx := 1 to FEngine.Configuration.KeyProcList.Count do begin
Item := FEngine.Configuration.KeyProcList[pred(Inx)];
Cells[cnTableName, Inx] := Item.Path + '\' + Item.Table + '.' + {!!.03}
ffc_ExtForData; {!!.03}
Cells[cnIndex, Inx] := IntToStr(Item.IndexID);
Cells[cnDLLName, Inx] := Item.DLLName;
Cells[cnBuildKey, Inx] := Item.BuildKeyName;
Cells[cnCompareKey, Inx] := Item.CompareKeyName;
end;
finally
EndUpdate;
end;
end;
end;
{====================================================================}
{===Button event handlers============================================}
procedure TFFIndexForm.btnBrowseClick(Sender: TObject);
var
aDlg : TOpenDialog;
begin
with grdIndexes do begin
if (Col <> cnTableName) and (Col <> cnDLLName) then
exit;
if Col = cnTableName then
aDlg := dlgOpenTable
else
aDlg := dlgOpenDLL;
if aDlg.Execute then begin
BeginUpdate;
try
Cells[Col, Row] := FFExpandUNCFileName(aDlg.FileName);
finally
EndUpdate;
end;
end;
end;
end;
{--------}
procedure TFFIndexForm.btnDeleteClick(Sender: TObject);
var
DeletedRow : integer;
Inx : integer;
LastEmpty : boolean;
LastRow : integer;
begin
if (grdIndexes.RowCount < 2) then
Exit;
with grdIndexes do begin
BeginUpdate;
try
DeletedRow := Row;
LastRow := pred(RowCount);
LastEmpty := LastRowIsEmpty;
{ Situations where delete is okay:
1. Non-last row
2. Last row and it is not empty }
{ Does user want to delete the last row? }
if (DeletedRow < LastRow) then begin
{ No. Move the rows up by one. }
for Inx := succ(DeletedRow) to lastRow do
CopyRow(Inx, pred(Inx));
{ Get rid of the last row. }
RowCount := RowCount - 1;
end else if (not LastEmpty) then
{ Yes, user wants to delete last row and it is not empty. }
BlankRow(Row);
finally
EndUpdate;
end;
end;
end;
{--------}
procedure TFFIndexForm.btnSaveClick(Sender: TObject);
var
Inx : integer;
Path : TffPath;
Table : TffTableName;
errStr : array [0..127] of char;
aResult : TffResult;
begin
FEngine.Configuration.KeyProcList.Empty;
{ Xfer the info from the grid to the engine's index list. }
with grdIndexes do
for Inx := 1 to pred(RowCount) do
if RowIsFilled(Inx) then begin
Path := FFExtractPath(Cells[cnTableName, Inx]);
Table := FFExtractFileName(Cells[cnTableName, Inx]);
FEngine.Configuration.AddKeyProc(Path,
Table,
StrToInt(Cells[cnIndex, Inx]),
Cells[cnDLLName, Inx],
Cells[cnBuildKey, Inx],
Cells[cnCompareKey, Inx]);
end;
aResult := FEngine.WriteKeyProcData;
if aResult <> DBIERR_NONE then begin
ffStrResBDE.GetASCIIZ(aResult, errStr, sizeof(DBIMSG));
showMessage(format('Could not save user-defined indexes: %s [$%x/%d])',
[strPas(errStr), aResult, aResult]));
self.modalResult := mrNone;
end;
end;
{====================================================================}
end.