|
@@ -2,23 +2,14 @@ unit UFRMOperationExplorer;
|
|
|
|
|
|
{$mode delphi}
|
|
|
|
|
|
-{ Copyright (c) 2018 by Herman Schoenfeld
|
|
|
-
|
|
|
- Distributed under the MIT software license, see the accompanying file LICENSE
|
|
|
- or visit http://www.opensource.org/licenses/mit-license.php.
|
|
|
-
|
|
|
- Acknowledgements:
|
|
|
- - Albert Molina: portions of code copied from https://github.com/PascalCoin/PascalCoin/blob/master/Units/Forms/UFRMWallet.pas
|
|
|
-}
|
|
|
-
|
|
|
+{$modeswitch nestedprocvars}
|
|
|
|
|
|
interface
|
|
|
|
|
|
-{$I ..\config.inc}
|
|
|
-
|
|
|
uses
|
|
|
- LCLIntf, LCLType, SysUtils, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Grids, Menus, Classes,
|
|
|
- UCommon.UI, UConst, UDataSources, UNode, UVisualGrid, UCellRenderers, UCommon.Data, UCoreUtils;
|
|
|
+ Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus,
|
|
|
+ ExtCtrls, Buttons, UVisualGrid, UCommon.UI, Generics.Collections,
|
|
|
+ UAccounts, UDataSources, UNode;
|
|
|
|
|
|
type
|
|
|
|
|
@@ -27,35 +18,32 @@ type
|
|
|
TFRMOperationExplorer = class(TApplicationForm)
|
|
|
ebFilterOperationsEndBlock: TEdit;
|
|
|
ebFilterOperationsStartBlock: TEdit;
|
|
|
- grpOperationExplorer: TGroupBox;
|
|
|
- Label2: TLabel;
|
|
|
- OperationsExplorerMenu: TMainMenu;
|
|
|
+ gpRecentOps: TGroupBox;
|
|
|
+ gpFilter: TGroupBox;
|
|
|
+ miFindOperationByHash: TMenuItem;
|
|
|
miDecodePayload: TMenuItem;
|
|
|
- miFindOperationByOpHash: TMenuItem;
|
|
|
miTools: TMenuItem;
|
|
|
- Panel1: TPanel;
|
|
|
- paGrid: TPanel;
|
|
|
+ OperationExplorerMenu: TMainMenu;
|
|
|
+ paOperations: TPanel;
|
|
|
procedure ebFilterOperationsAccountExit(Sender: TObject);
|
|
|
procedure ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: char);
|
|
|
procedure FormCreate(Sender: TObject);
|
|
|
procedure miDecodePayloadClick(Sender: TObject);
|
|
|
- procedure miFindOperationByOpHashClick(Sender: TObject);
|
|
|
-
|
|
|
- protected
|
|
|
- procedure OnNodeNewAccount(Sender: TObject);
|
|
|
- procedure OnNodeNewOperation(Sender: TObject);
|
|
|
- procedure OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
|
|
|
+ procedure miFindOperationByHashClick(Sender: TObject);
|
|
|
private
|
|
|
- { private declarations }
|
|
|
+ FMaxBlocks: integer;
|
|
|
FUpdating: boolean;
|
|
|
FBlockStart, FBlockEnd: int64;
|
|
|
- FMaxBlocks: integer;
|
|
|
FNodeNotifyEvents: TNodeNotifyEvents;
|
|
|
FOperationsGrid: TVisualGrid;
|
|
|
FOperationsDataSource: TOperationsDataSource;
|
|
|
- procedure SetMaxBlocks(AValue: integer);
|
|
|
- procedure UpdateVisualGridUI();
|
|
|
+ procedure RefreshOperationsGrid;
|
|
|
procedure SetBlocks(AStart, AEnd: int64);
|
|
|
+ procedure SetMaxBlocks(AValue: integer);
|
|
|
+ protected
|
|
|
+ procedure OnNodeBlocksChanged(Sender: TObject);
|
|
|
+ procedure OnNodeNewOperation(Sender: TObject);
|
|
|
+ procedure OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
|
|
|
public
|
|
|
{ public declarations }
|
|
|
property MaxBlocks: integer read FMaxBlocks write SetMaxBlocks;
|
|
@@ -63,102 +51,59 @@ type
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-{$r *.lfm}
|
|
|
-
|
|
|
-uses UUserInterface, UMemory, UFRMPayloadDecoder, UBlockChain, UWallet, Generics.Collections;
|
|
|
-
|
|
|
-procedure TFRMOperationExplorer.FormCreate(Sender: TObject);
|
|
|
-begin
|
|
|
-
|
|
|
- // event registrations
|
|
|
- FNodeNotifyEvents := TNodeNotifyEvents.Create(self);
|
|
|
- FNodeNotifyEvents.OnBlocksChanged := OnNodeNewAccount;
|
|
|
- FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
|
|
|
-
|
|
|
- FUpdating := False;
|
|
|
- FBlockStart := -1;
|
|
|
- FBlockEnd := -1;
|
|
|
- FMaxBlocks := 300;
|
|
|
-
|
|
|
- UpdateVisualGridUI();
|
|
|
+uses
|
|
|
+ UUserInterface, UCellRenderers, UBlockChain, UWallet, UCrypto,
|
|
|
+ UCommon, UMemory, Generics.Defaults, UCommon.Data, UCommon.Collections;
|
|
|
|
|
|
-end;
|
|
|
+{$R *.lfm}
|
|
|
|
|
|
-procedure TFRMOperationExplorer.miDecodePayloadClick(Sender: TObject);
|
|
|
-begin
|
|
|
- TUserInterface.ShowOperationInfoDialog(Self, '');
|
|
|
-end;
|
|
|
+{ TFRMOperationExplorer }
|
|
|
|
|
|
-procedure TFRMOperationExplorer.miFindOperationByOpHashClick(Sender: TObject);
|
|
|
+procedure TFRMOperationExplorer.ebFilterOperationsAccountExit(Sender: TObject);
|
|
|
var
|
|
|
- ophash: string;
|
|
|
+ LStart, LEnd: int64;
|
|
|
begin
|
|
|
- if not InputQuery('Search operation by OpHash', 'Insert Operation Hash value (OpHash)', ophash) then
|
|
|
- Exit;
|
|
|
-
|
|
|
- TUserInterface.ShowOperationInfoDialog(Self, ophash);
|
|
|
+ if not FUpdating then
|
|
|
+ try
|
|
|
+ FUpdating := True;// move to finally
|
|
|
+ LStart := StrToInt64Def(ebFilterOperationsStartBlock.Text, -1);
|
|
|
+ if LStart >= 0 then
|
|
|
+ ebFilterOperationsStartBlock.Text := IntToStr(LStart)
|
|
|
+ else
|
|
|
+ ebFilterOperationsStartBlock.Text := '';
|
|
|
+ LEnd := StrToInt64Def(ebFilterOperationsEndBlock.Text, -1);
|
|
|
+ if LEnd >= 0 then
|
|
|
+ ebFilterOperationsEndBlock.Text := IntToStr(LEnd)
|
|
|
+ else
|
|
|
+ ebFilterOperationsEndBlock.Text := '';
|
|
|
+ SetBlocks(LStart, LEnd);
|
|
|
+ finally
|
|
|
+ FUpdating := False;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.OnNodeNewAccount(Sender: TObject);
|
|
|
+procedure TFRMOperationExplorer.ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: char);
|
|
|
begin
|
|
|
- UpdateVisualGridUI(); //main
|
|
|
+ if Key = #13 then
|
|
|
+ ebFilterOperationsAccountExit(nil);
|
|
|
end;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.OnNodeNewOperation(Sender: TObject);
|
|
|
+procedure TFRMOperationExplorer.FormCreate(Sender: TObject);
|
|
|
begin
|
|
|
- UpdateVisualGridUI();
|
|
|
-end;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
|
|
|
-var
|
|
|
- LRow: longint;
|
|
|
- LOperationResumeList: TList<TOperationResume>;
|
|
|
- LGC: TDisposables;
|
|
|
-begin
|
|
|
- LOperationResumeList := LGC.AddObject(TList<TOperationResume>.Create) as TList<TOperationResume>;
|
|
|
- LRow := ASelection.Row;
|
|
|
- if (LRow >= 0) and (LRow < FOperationsGrid.RowCount) then
|
|
|
- begin
|
|
|
- FOperationsDataSource.FetchAll(LOperationResumeList);
|
|
|
- TUserInterface.ShowOperationInfoDialog(self, LOperationResumeList[LRow]);
|
|
|
- FOperationsGrid.ClearSelection;
|
|
|
- end;
|
|
|
-end;
|
|
|
+ FUpdating := False;
|
|
|
+ FBlockStart := -1;
|
|
|
+ FBlockEnd := -1;
|
|
|
+ FMaxBlocks := 300;
|
|
|
+ // event registrations
|
|
|
+ FNodeNotifyEvents := TNodeNotifyEvents.Create(self);
|
|
|
+ FNodeNotifyEvents.OnBlocksChanged := OnNodeBlocksChanged;
|
|
|
+ FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.UpdateVisualGridUI();
|
|
|
-var
|
|
|
- LNode: TNode;
|
|
|
- LStart, LEnd: int64;
|
|
|
-begin
|
|
|
- LNode := FNodeNotifyEvents.Node;
|
|
|
- if FBlockEnd < 0 then
|
|
|
- begin
|
|
|
- if LNode.Bank.BlocksCount > 0 then
|
|
|
- LEnd := LNode.Bank.BlocksCount - 1
|
|
|
- else
|
|
|
- LEnd := 0;
|
|
|
- end
|
|
|
- else
|
|
|
- LEnd := FBlockEnd;
|
|
|
- if FBlockStart < 0 then
|
|
|
- begin
|
|
|
- if (LEnd > MaxBlocks) then
|
|
|
- LStart := LEnd - MaxBlocks
|
|
|
- else
|
|
|
- LStart := 0;
|
|
|
- end
|
|
|
- else
|
|
|
- LStart := FBlockStart;
|
|
|
- if LStart < 0 then
|
|
|
- LStart := 0;
|
|
|
- if LEnd >= LNode.Bank.BlocksCount then
|
|
|
- LEnd := LNode.Bank.BlocksCount;
|
|
|
// fields
|
|
|
FOperationsDataSource := TOperationsDataSource.Create(Self);
|
|
|
|
|
|
- FOperationsDataSource.StartBlock := LStart;
|
|
|
- FOperationsDataSource.EndBlock := LEnd;
|
|
|
-
|
|
|
+ // grids
|
|
|
FOperationsGrid := TVisualGrid.Create(Self);
|
|
|
FOperationsGrid.SortMode := smMultiColumn;
|
|
|
FOperationsGrid.FetchDataInThread := True;
|
|
@@ -166,6 +111,7 @@ begin
|
|
|
FOperationsGrid.DeselectionType := dtDefault;
|
|
|
FOperationsGrid.SelectionType := stRow;
|
|
|
FOperationsGrid.Options := [vgoColAutoFill, vgoColSizing, vgoSortDirectionAllowNone, vgoAutoHidePaging, vgoAutoHideSearchPanel];
|
|
|
+
|
|
|
with FOperationsGrid.AddColumn('Time') do
|
|
|
begin
|
|
|
SortBinding := 'UnixTime';
|
|
@@ -178,7 +124,9 @@ begin
|
|
|
begin
|
|
|
Binding := 'BlockLocation';
|
|
|
SortBinding := 'BlockLocationSortable';
|
|
|
- AutoWidth := True;
|
|
|
+ Width := 100;
|
|
|
+ HeaderAlignment := taRightJustify;
|
|
|
+ DataAlignment := taRightJustify;
|
|
|
Filters := SORTABLE_TEXT_FILTER;
|
|
|
end;
|
|
|
with FOperationsGrid.AddColumn('Account') do
|
|
@@ -186,6 +134,8 @@ begin
|
|
|
Binding := 'AccountNumber';
|
|
|
DisplayBinding := 'Account';
|
|
|
Width := 100;
|
|
|
+ HeaderAlignment := taRightJustify;
|
|
|
+ DataAlignment := taRightJustify;
|
|
|
Filters := SORTABLE_NUMERIC_FILTER;
|
|
|
end;
|
|
|
with FOperationsGrid.AddColumn('Type') do
|
|
@@ -199,8 +149,9 @@ begin
|
|
|
Binding := 'AmountDecimal';
|
|
|
SortBinding := 'Amount';
|
|
|
DisplayBinding := 'Amount';
|
|
|
- Width := 150;
|
|
|
+ Width := 100;
|
|
|
HeaderAlignment := taRightJustify;
|
|
|
+ DataAlignment := taRightJustify;
|
|
|
Renderer := TCellRenderers.PASC_CheckPendingBalance;
|
|
|
Filters := SORTABLE_NUMERIC_FILTER;
|
|
|
end;
|
|
@@ -209,7 +160,7 @@ begin
|
|
|
Binding := 'FeeDecimal';
|
|
|
SortBinding := 'Fee';
|
|
|
DisplayBinding := 'Fee';
|
|
|
- AutoWidth := True;
|
|
|
+ Width := 100;
|
|
|
HeaderAlignment := taRightJustify;
|
|
|
DataAlignment := taRightJustify;
|
|
|
Renderer := TCellRenderers.PASC_CheckPendingBalance;
|
|
@@ -236,13 +187,64 @@ begin
|
|
|
FOperationsGrid.OnSelection := OnOperationSelected;
|
|
|
FOperationsGrid.Caption.Alignment := taCenter;
|
|
|
FOperationsGrid.Caption.Text := 'All Operations';
|
|
|
+ FOperationsGrid.Caption.Text := '';
|
|
|
FOperationsGrid.Caption.Visible := True;
|
|
|
|
|
|
// Add datasources to grid
|
|
|
FOperationsGrid.DataSource := FOperationsDataSource;
|
|
|
|
|
|
// Add grid to panels
|
|
|
- paGrid.AddControlDockCenter(FOperationsGrid);
|
|
|
+ paOperations.AddControlDockCenter(FOperationsGrid);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFRMOperationExplorer.miDecodePayloadClick(Sender: TObject);
|
|
|
+begin
|
|
|
+ TUserInterface.ShowOperationInfoDialog(Self, '');
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFRMOperationExplorer.miFindOperationByHashClick(Sender: TObject);
|
|
|
+var
|
|
|
+ LOpHash: string;
|
|
|
+begin
|
|
|
+ if not InputQuery('Search operation by OpHash', 'Insert Operation Hash value (OpHash)', LOpHash) then
|
|
|
+ Exit;
|
|
|
+
|
|
|
+ TUserInterface.ShowOperationInfoDialog(Self, LOpHash);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFRMOperationExplorer.RefreshOperationsGrid;
|
|
|
+var
|
|
|
+ LNode: TNode;
|
|
|
+ LStart, LEnd: int64;
|
|
|
+begin
|
|
|
+ LNode := FNodeNotifyEvents.Node;
|
|
|
+ if FBlockEnd < 0 then
|
|
|
+ begin
|
|
|
+ if LNode.Bank.BlocksCount > 0 then
|
|
|
+ LEnd := LNode.Bank.BlocksCount - 1
|
|
|
+ else
|
|
|
+ LEnd := 0;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ LEnd := FBlockEnd;
|
|
|
+ if FBlockStart < 0 then
|
|
|
+ begin
|
|
|
+ if (LEnd > MaxBlocks) then
|
|
|
+ LStart := LEnd - MaxBlocks
|
|
|
+ else
|
|
|
+ LStart := 0;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ LStart := FBlockStart;
|
|
|
+ if LStart < 0 then
|
|
|
+ LStart := 0;
|
|
|
+ if LEnd >= LNode.Bank.BlocksCount then
|
|
|
+ LEnd := LNode.Bank.BlocksCount;
|
|
|
+
|
|
|
+ FOperationsDataSource.StartBlock := LStart;
|
|
|
+ FOperationsDataSource.EndBlock := LEnd;
|
|
|
+
|
|
|
+ FOperationsGrid.RefreshGrid;
|
|
|
end;
|
|
|
|
|
|
procedure TFRMOperationExplorer.SetBlocks(AStart, AEnd: int64);
|
|
@@ -253,7 +255,7 @@ begin
|
|
|
FBlockEnd := AEnd;
|
|
|
if (FBlockEnd > 0) and (FBlockStart > FBlockEnd) then
|
|
|
FBlockStart := -1;
|
|
|
- UpdateVisualGridUI();
|
|
|
+ RefreshOperationsGrid;
|
|
|
end;
|
|
|
|
|
|
procedure TFRMOperationExplorer.SetMaxBlocks(AValue: integer);
|
|
@@ -263,36 +265,40 @@ begin
|
|
|
FMaxBlocks := AValue;
|
|
|
if (FMaxBlocks <= 0) or (FMaxBlocks > 500) then
|
|
|
FMaxBlocks := 300;
|
|
|
- UpdateVisualGridUI();
|
|
|
+ RefreshOperationsGrid;
|
|
|
end;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.ebFilterOperationsAccountExit(Sender: TObject);
|
|
|
-var
|
|
|
- LStart, LEnd: int64;
|
|
|
+procedure TFRMOperationExplorer.OnNodeBlocksChanged(Sender: TObject);
|
|
|
begin
|
|
|
- if not FUpdating then
|
|
|
- try
|
|
|
- FUpdating := True;// move to finally
|
|
|
- LStart := StrToInt64Def(ebFilterOperationsStartBlock.Text, -1);
|
|
|
- if LStart >= 0 then
|
|
|
- ebFilterOperationsStartBlock.Text := IntToStr(LStart)
|
|
|
- else
|
|
|
- ebFilterOperationsStartBlock.Text := '';
|
|
|
- LEnd := StrToInt64Def(ebFilterOperationsEndBlock.Text, -1);
|
|
|
- if LEnd >= 0 then
|
|
|
- ebFilterOperationsEndBlock.Text := IntToStr(LEnd)
|
|
|
- else
|
|
|
- ebFilterOperationsEndBlock.Text := '';
|
|
|
- SetBlocks(LStart, LEnd);
|
|
|
- finally
|
|
|
- FUpdating := False;
|
|
|
- end;
|
|
|
+ // TODO: play block sound chime
|
|
|
+ RefreshOperationsGrid;
|
|
|
end;
|
|
|
|
|
|
-procedure TFRMOperationExplorer.ebFilterOperationsAccountKeyPress(Sender: TObject; var Key: char);
|
|
|
+procedure TFRMOperationExplorer.OnNodeNewOperation(Sender: TObject);
|
|
|
begin
|
|
|
- if Key = #13 then
|
|
|
- ebFilterOperationsAccountExit(nil);
|
|
|
+ // TODO: play operation sound tick
|
|
|
+ RefreshOperationsGrid;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFRMOperationExplorer.OnOperationSelected(Sender: TObject; constref ASelection: TVisualGridSelection);
|
|
|
+var
|
|
|
+ row: longint;
|
|
|
+ v: variant;
|
|
|
+ ophash: ansistring;
|
|
|
+begin
|
|
|
+ if ASelection.Page < 0 then
|
|
|
+ exit;
|
|
|
+ row := ASelection.Row;
|
|
|
+ if (row >= 0) and (row < FOperationsGrid.RowCount) then
|
|
|
+ begin
|
|
|
+ v := FOperationsGrid.Rows[row];
|
|
|
+ ophash := FOperationsGrid.Rows[row].OPHASH;
|
|
|
+ if TPCOperation.IsValidOperationHash(ophash) then
|
|
|
+ begin
|
|
|
+ TUserInterface.ShowOperationInfoDialog(self, ophash);
|
|
|
+ FOperationsGrid.ClearSelection(True);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
end;
|
|
|
|
|
|
end.
|