Browse Source

Improve gui-classic User Accounts Visualization

Allow to update user accounts with a separated thread to avoid freeze on wallet when updating info
PascalCoin 6 years ago
parent
commit
5cb116394e
3 changed files with 271 additions and 111 deletions
  1. 2 2
      src/gui-classic/UFRMAccountSelect.pas
  2. 47 82
      src/gui-classic/UFRMWallet.pas
  3. 222 27
      src/gui-classic/UGridUtils.pas

+ 2 - 2
src/gui-classic/UFRMAccountSelect.pas

@@ -506,11 +506,11 @@ begin
   If (searchValues.inAccountKey.EC_OpenSSL_NID=0) AND (searchValues.inWalletKeys=Nil) And (searchValues.maxBal<0) And (searchValues.minBal<=0) And
   If (searchValues.inAccountKey.EC_OpenSSL_NID=0) AND (searchValues.inWalletKeys=Nil) And (searchValues.maxBal<0) And (searchValues.minBal<=0) And
      (Not searchValues.onlyForPrivateSaleToMe) And (Not searchValues.onlyForPublicSale) And (Not searchValues.onlyForSale) And
      (Not searchValues.onlyForPrivateSaleToMe) And (Not searchValues.onlyForPublicSale) And (Not searchValues.onlyForSale) And
      (Length(searchValues.searchName)=0) then begin
      (Length(searchValues.searchName)=0) then begin
-    FAccountsGrid.ShowAllAccounts:=True;
+    FAccountsGrid.AccountsGridDatasource := acds_Node;
     lblAccountsCount.Caption := IntToStr(FAccountsGrid.Node.Bank.SafeBox.AccountsCount);
     lblAccountsCount.Caption := IntToStr(FAccountsGrid.Node.Bank.SafeBox.AccountsCount);
     lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
     lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
   end else begin
   end else begin
-    FAccountsGrid.ShowAllAccounts:=False;
+    FAccountsGrid.AccountsGridDatasource := acds_InternalList;
     FSearchThread.DoSearch(searchValues);
     FSearchThread.DoSearch(searchValues);
   end;
   end;
 end;
 end;

+ 47 - 82
src/gui-classic/UFRMWallet.pas

@@ -246,6 +246,7 @@ type
     {$ENDIF}
     {$ENDIF}
     {$ENDIF}
     {$ENDIF}
     Procedure Test_ShowPublicKeys(Sender: TObject);
     Procedure Test_ShowPublicKeys(Sender: TObject);
+    procedure OnAccountsGridUpdatedData(Sender : TObject);
   protected
   protected
     { Private declarations }
     { Private declarations }
     FNode : TNode;
     FNode : TNode;
@@ -258,7 +259,6 @@ type
     FSelectedAccountsGrid : TAccountsGrid;
     FSelectedAccountsGrid : TAccountsGrid;
     FOperationsAccountGrid : TOperationsGrid;
     FOperationsAccountGrid : TOperationsGrid;
     FPendingOperationsGrid : TOperationsGrid;
     FPendingOperationsGrid : TOperationsGrid;
-    FOrderedAccountsKeyList : TOrderedAccountKeysList;
     FOperationsExplorerGrid : TOperationsGrid;
     FOperationsExplorerGrid : TOperationsGrid;
     FBlockChainGrid : TBlockChainGrid;
     FBlockChainGrid : TBlockChainGrid;
     FMinerPrivateKeyType : TMinerPrivateKey;
     FMinerPrivateKeyType : TMinerPrivateKey;
@@ -1090,7 +1090,6 @@ begin
   memoMessages.Lines.Clear;
   memoMessages.Lines.Clear;
   memoMessageToSend.Lines.Clear;
   memoMessageToSend.Lines.Clear;
   FUpdating := false;
   FUpdating := false;
-  FOrderedAccountsKeyList := Nil;
   TimerUpdateStatus.Enabled := false;
   TimerUpdateStatus.Enabled := false;
   FIsActivated := false;
   FIsActivated := false;
   FWalletKeys := TWalletKeysExt.Create(Self);
   FWalletKeys := TWalletKeysExt.Create(Self);
@@ -1110,7 +1109,10 @@ begin
   FAccountsGrid := TAccountsGrid.Create(Self);
   FAccountsGrid := TAccountsGrid.Create(Self);
   FAccountsGrid.DrawGrid := dgAccounts;
   FAccountsGrid.DrawGrid := dgAccounts;
   FAccountsGrid.AllowMultiSelect := True;
   FAccountsGrid.AllowMultiSelect := True;
+  FAccountsGrid.OnAccountsGridUpdatedData := OnAccountsGridUpdatedData;
+  FAccountsGrid.AccountsGridDatasource := acds_Node;
   FSelectedAccountsGrid := TAccountsGrid.Create(Self);
   FSelectedAccountsGrid := TAccountsGrid.Create(Self);
+  FSelectedAccountsGrid.AccountsGridDatasource := acds_InternalList;
   FSelectedAccountsGrid.DrawGrid := dgSelectedAccounts;
   FSelectedAccountsGrid.DrawGrid := dgSelectedAccounts;
   FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
   FSelectedAccountsGrid.OnUpdated := OnSelectedAccountsGridUpdated;
   FOperationsAccountGrid := TOperationsGrid.Create(Self);
   FOperationsAccountGrid := TOperationsGrid.Create(Self);
@@ -1256,9 +1258,6 @@ begin
   FreeAndNil(FOperationsExplorerGrid);
   FreeAndNil(FOperationsExplorerGrid);
   FreeAndNil(FBlockChainGrid);
   FreeAndNil(FBlockChainGrid);
 
 
-  step := 'Ordered Accounts Key list';
-  FreeAndNil(FOrderedAccountsKeyList);
-
   step := 'Desactivating Node';
   step := 'Desactivating Node';
   TNode.Node.NetServer.Active := false;
   TNode.Node.NetServer.Active := false;
   FNode := Nil;
   FNode := Nil;
@@ -1628,6 +1627,17 @@ begin
   sbSelectedAccountsDelClick(Sender);
   sbSelectedAccountsDelClick(Sender);
 end;
 end;
 
 
+procedure TFRMWallet.OnAccountsGridUpdatedData(Sender: TObject);
+begin
+  if FAccountsGrid.IsUpdatingData then begin
+    lblAccountsCount.Caption := '(Calculating)';
+    lblAccountsBalance.Caption := '(Calculating)';
+  end else begin
+    lblAccountsCount.Caption := IntToStr(FAccountsGrid.AccountsCount);
+    lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
+  end;
+end;
+
 procedure TFRMWallet.OnMiningServerNewBlockFound(Sender: TObject);
 procedure TFRMWallet.OnMiningServerNewBlockFound(Sender: TObject);
 begin
 begin
   FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
   FPoolMiningServer.MinerAccountKey := GetAccountKeyForMiner;
@@ -1846,11 +1856,11 @@ procedure TFRMWallet.PageControlChange(Sender: TObject);
 begin
 begin
   MiDecodePayload.Enabled := false;
   MiDecodePayload.Enabled := false;
   if PageControl.ActivePage=tsMyAccounts then begin
   if PageControl.ActivePage=tsMyAccounts then begin
-    //FAccountsGrid.Node := FNode;
+    FAccountsGrid.Node := FNode;
     MiDecodePayload.Enabled := true;
     MiDecodePayload.Enabled := true;
     FSelectedAccountsGrid.Node := FNode;
     FSelectedAccountsGrid.Node := FNode;
   end else begin
   end else begin
-    //FAccountsGrid.Node := Nil;
+    FAccountsGrid.Node := Nil;
     FSelectedAccountsGrid.Node := Nil;
     FSelectedAccountsGrid.Node := Nil;
   end;
   end;
   if PageControl.ActivePage=tsPendingOperations then begin
   if PageControl.ActivePage=tsPendingOperations then begin
@@ -1981,80 +1991,47 @@ Var accl : TOrderedCardinalList;
   l : TOrderedCardinalList;
   l : TOrderedCardinalList;
   i,j,k : Integer;
   i,j,k : Integer;
   c  : Cardinal;
   c  : Cardinal;
-  applyfilter : Boolean;
+  LApplyfilter : Boolean;
   acc : TAccount;
   acc : TAccount;
+  LFilters : TAccountsGridFilter;
 begin
 begin
-  If Not Assigned(FOrderedAccountsKeyList) Then exit;
+  If Not Assigned(FWalletKeys) Then exit;
+  if Not Assigned(FNode) then Exit;
+
   if Not RefreshData then begin
   if Not RefreshData then begin
     dgAccounts.Invalidate;
     dgAccounts.Invalidate;
     exit;
     exit;
   end;
   end;
-  applyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or (FMaxAccountBalance<CT_MaxWalletAmount));
-  FAccountsGrid.ShowAllAccounts := (Not cbExploreMyAccounts.Checked) And (not applyfilter);
-  if Not FAccountsGrid.ShowAllAccounts then begin
-    accl := FAccountsGrid.LockAccountsList;
-    Try
-      accl.Clear;
-      if cbExploreMyAccounts.Checked then begin
-        if cbMyPrivateKeys.ItemIndex<0 then exit;
-        if cbMyPrivateKeys.ItemIndex=0 then begin
-          // All keys in the wallet
-          for i := 0 to FWalletKeys.Count - 1 do begin
-            FOrderedAccountsKeyList.Lock; // Protection v4
-            Try
-              j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
-              if (j>=0) then begin
-                l := FOrderedAccountsKeyList.AccountKeyList[j];
-                for k := 0 to l.Count - 1 do begin
-                  if applyfilter then begin
-                    acc := FNode.Bank.SafeBox.Account(l.Get(k));
-                    if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-                  end else accl.Add(l.Get(k));
-                end;
-              end;
-            finally
-              FOrderedAccountsKeyList.Unlock;
-            end;
-          end;
-        end else begin
+  LApplyfilter := (cbFilterAccounts.Checked) and ((FMinAccountBalance>0) Or ((FMaxAccountBalance<CT_MaxWalletAmount) and (FMaxAccountBalance>=0)));
+  if (Not cbExploreMyAccounts.Checked) And (not LApplyfilter) then
+    FAccountsGrid.AccountsGridDatasource := acds_Node
+  else begin
+    LFilters := FAccountsGrid.AccountsGridFilter;
+    LFilters.MinBalance := FMinAccountBalance;
+    LFilters.MaxBalance := FMaxAccountBalance;
+    if cbExploreMyAccounts.Checked then begin
+      FNode.Bank.SafeBox.StartThreadSafe;
+      try
+        LFilters.OrderedAccountsKeyList := FWalletKeys.AccountsKeyList;
+        if cbMyPrivateKeys.ItemIndex>0 then begin
           i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
           i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex]);
           if (i>=0) And (i<FWalletKeys.Count) then begin
           if (i>=0) And (i<FWalletKeys.Count) then begin
-            FOrderedAccountsKeyList.Lock; // Protection v4
-            Try
-              j := FOrderedAccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
-              if (j>=0) then begin
-                l := FOrderedAccountsKeyList.AccountKeyList[j];
-                for k := 0 to l.Count - 1 do begin
-                  if applyfilter then begin
-                    acc := FNode.Bank.SafeBox.Account(l.Get(k));
-                    if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-                  end else accl.Add(l.Get(k));
-                end;
-              end;
-            finally
-              FOrderedAccountsKeyList.Unlock;
-            end;
+            LFilters.indexAccountsKeyList := FWalletKeys.AccountsKeyList.IndexOfAccountKey(FWalletKeys[i].AccountKey);
           end;
           end;
-        end;
-      end else begin
-        // There is a filter... check every account...
-        c := 0;
-        while (c<FNode.Bank.SafeBox.AccountsCount) do begin
-          acc := FNode.Bank.SafeBox.Account(c);
-          if (acc.balance>=FMinAccountBalance) And (acc.balance<=FMaxAccountBalance) then accl.Add(acc.account);
-          inc(c);
-        end;
+        end else LFilters.indexAccountsKeyList := -1;
+      finally
+        FNode.Bank.SafeBox.EndThreadSave;
       end;
       end;
-    Finally
-      FAccountsGrid.UnlockAccountsList;
-    End;
-    lblAccountsCount.Caption := inttostr(accl.Count);
-  end else begin
-    lblAccountsCount.Caption := inttostr(FNode.Bank.AccountsCount);
+    end else begin
+      LFilters.OrderedAccountsKeyList := Nil;
+      LFilters.indexAccountsKeyList := -1;
+    end;
+    FAccountsGrid.AccountsGridFilter := LFilters;
+    FAccountsGrid.AccountsGridDatasource := acds_NodeFiltered;
   end;
   end;
+
   bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
   bbChangeKeyName.Enabled := cbExploreMyAccounts.Checked;
-  // Show Totals:
-  lblAccountsBalance.Caption := TAccountComp.FormatMoney(FAccountsGrid.AccountsBalance);
+  OnAccountsGridUpdatedData(Nil);
   UpdateOperations;
   UpdateOperations;
 end;
 end;
 
 
@@ -2276,22 +2253,14 @@ Var i,last_i : Integer;
   wk : TWalletKey;
   wk : TWalletKey;
   s : AnsiString;
   s : AnsiString;
 begin
 begin
-  If (Not Assigned(FOrderedAccountsKeyList)) And (Assigned(FNode)) Then begin
-    FOrderedAccountsKeyList := TOrderedAccountKeysList.Create(FNode.Bank.SafeBox,false);
-    FNodeNotifyEvents.WatchKeys := FOrderedAccountsKeyList;
-  end;
+  FNodeNotifyEvents.WatchKeys := FWalletKeys.AccountsKeyList;
   if (cbMyPrivateKeys.ItemIndex>=0) then last_i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex])
   if (cbMyPrivateKeys.ItemIndex>=0) then last_i := PtrInt(cbMyPrivateKeys.Items.Objects[cbMyPrivateKeys.ItemIndex])
   else last_i := -1;
   else last_i := -1;
   cbMyPrivateKeys.items.BeginUpdate;
   cbMyPrivateKeys.items.BeginUpdate;
   Try
   Try
     cbMyPrivateKeys.Items.Clear;
     cbMyPrivateKeys.Items.Clear;
-    if assigned(FOrderedAccountsKeyList) then FOrderedAccountsKeyList.SafeBox.StartThreadSafe;
-    Try
     For i:=0 to FWalletKeys.Count-1 do begin
     For i:=0 to FWalletKeys.Count-1 do begin
       wk := FWalletKeys.Key[i];
       wk := FWalletKeys.Key[i];
-      if assigned(FOrderedAccountsKeyList) then begin
-        FOrderedAccountsKeyList.AddAccountKey(wk.AccountKey);
-      end;
       if (wk.Name='') then begin
       if (wk.Name='') then begin
         s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
         s := 'Sha256='+TCrypto.ToHexaString( TCrypto.DoSha256( TAccountComp.AccountKey2RawString(wk.AccountKey) ) );
       end else begin
       end else begin
@@ -2303,10 +2272,6 @@ begin
       end;
       end;
       cbMyPrivateKeys.Items.AddObject(s,TObject(i));
       cbMyPrivateKeys.Items.AddObject(s,TObject(i));
     end;
     end;
-
-    finally
-      if assigned(FOrderedAccountsKeyList) then FOrderedAccountsKeyList.SafeBox.EndThreadSave;
-    end;
     cbMyPrivateKeys.Sorted := true;
     cbMyPrivateKeys.Sorted := true;
     cbMyPrivateKeys.Sorted := false;
     cbMyPrivateKeys.Sorted := false;
     cbMyPrivateKeys.Items.InsertObject(0,'(All my private keys)',TObject(-1));
     cbMyPrivateKeys.Items.InsertObject(0,'(All my private keys)',TObject(-1));

+ 222 - 27
src/gui-classic/UGridUtils.pas

@@ -43,6 +43,31 @@ Type
     width : Integer;
     width : Integer;
   End;
   End;
 
 
+  TAccountsGrid = Class;
+
+  TAccountsGridFilter = Record
+    MinBalance,
+    MaxBalance : Int64;
+    OrderedAccountsKeyList : TOrderedAccountKeysList;
+    indexAccountsKeyList : Integer;
+  end;
+
+  TAccountsGridUpdateThread = Class(TPCThread)
+    FAccountsGrid : TAccountsGrid;
+    FAccountsGridFilter : TAccountsGridFilter;
+    FBalance : Int64;
+    FIsProcessing : Boolean;
+  protected
+    procedure SynchronizedOnTerminated;
+    procedure BCExecute; override;
+  public
+    constructor Create(AAccountsGrid : TAccountsGrid; AAccountsGridFilter : TAccountsGridFilter);
+    destructor Destroy; override;
+    property IsProcessing : Boolean read FisProcessing;
+  End;
+
+  TAccountsGridDatasource = (acds_Node, acds_InternalList, acds_NodeFiltered);
+
   TAccountsGrid = Class(TComponent)
   TAccountsGrid = Class(TComponent)
   private
   private
     FAccountsBalance : Int64;
     FAccountsBalance : Int64;
@@ -50,18 +75,24 @@ Type
     FColumns : Array of TAccountColumn;
     FColumns : Array of TAccountColumn;
     FDrawGrid : TDrawGrid;
     FDrawGrid : TDrawGrid;
     FNodeNotifyEvents : TNodeNotifyEvents;
     FNodeNotifyEvents : TNodeNotifyEvents;
-    FShowAllAccounts: Boolean;
     FOnUpdated: TNotifyEvent;
     FOnUpdated: TNotifyEvent;
-    FAccountsCount: Integer;
     FAllowMultiSelect: Boolean;
     FAllowMultiSelect: Boolean;
+    FAccountsGridUpdateThread : TAccountsGridUpdateThread;
+    FAccountsGridFilter: TAccountsGridFilter;
+    FOnAccountsGridUpdatedData: TNotifyEvent;
+    FAccountsGridDatasource: TAccountsGridDatasource;
     procedure SetDrawGrid(const Value: TDrawGrid);
     procedure SetDrawGrid(const Value: TDrawGrid);
     Procedure InitGrid;
     Procedure InitGrid;
     Procedure OnNodeNewOperation(Sender : TObject);
     Procedure OnNodeNewOperation(Sender : TObject);
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
     procedure OnGridDrawCell(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
     procedure SetNode(const Value: TNode);
     procedure SetNode(const Value: TNode);
     function GetNode: TNode;
     function GetNode: TNode;
-    procedure SetShowAllAccounts(const Value: Boolean);
     procedure SetAllowMultiSelect(const Value: Boolean);
     procedure SetAllowMultiSelect(const Value: Boolean);
+    procedure TerminateAccountGridUpdateThread;
+    procedure SetAccountsGridFilter(const Value: TAccountsGridFilter);
+    function GetAccountsCount: Integer;
+    procedure SetAccountsGridDatasource(const Value: TAccountsGridDatasource);
+    procedure UpdateAccountsBalance;
   protected
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
     procedure Notification(AComponent: TComponent; Operation: TOperation); Override;
   public
   public
@@ -74,13 +105,17 @@ Type
     Function AccountNumber(GridRow : Integer) : Int64;
     Function AccountNumber(GridRow : Integer) : Int64;
     Procedure SaveToStream(Stream : TStream);
     Procedure SaveToStream(Stream : TStream);
     Procedure LoadFromStream(Stream : TStream);
     Procedure LoadFromStream(Stream : TStream);
-    Property ShowAllAccounts : Boolean read FShowAllAccounts write SetShowAllAccounts;
     Property AccountsBalance : Int64 read FAccountsBalance;
     Property AccountsBalance : Int64 read FAccountsBalance;
-    Property AccountsCount : Integer read FAccountsCount;
+    Property AccountsCount : Integer read GetAccountsCount;
     Function MoveRowToAccount(nAccount : Cardinal) : Boolean;
     Function MoveRowToAccount(nAccount : Cardinal) : Boolean;
     Property OnUpdated : TNotifyEvent read FOnUpdated write FOnUpdated;
     Property OnUpdated : TNotifyEvent read FOnUpdated write FOnUpdated;
     Property AllowMultiSelect : Boolean read FAllowMultiSelect write SetAllowMultiSelect;
     Property AllowMultiSelect : Boolean read FAllowMultiSelect write SetAllowMultiSelect;
     Function SelectedAccounts(accounts : TOrderedCardinalList) : Integer;
     Function SelectedAccounts(accounts : TOrderedCardinalList) : Integer;
+    property AccountsGridFilter : TAccountsGridFilter read FAccountsGridFilter write SetAccountsGridFilter;
+    procedure UpdateData;
+    function IsUpdatingData : Boolean;
+    property OnAccountsGridUpdatedData : TNotifyEvent read FOnAccountsGridUpdatedData write FOnAccountsGridUpdatedData;
+    property AccountsGridDatasource : TAccountsGridDatasource read FAccountsGridDatasource write SetAccountsGridDatasource;
   End;
   End;
 
 
   TOperationsGrid = Class;
   TOperationsGrid = Class;
@@ -225,7 +260,7 @@ Type
 
 
 Const
 Const
   CT_TBlockChainData_NUL : TBlockChainData = (Block:0;Timestamp:0;BlockProtocolVersion:0;BlockProtocolAvailable:0;OperationsCount:-1;Volume:-1;Reward:0;Fee:0;Target:0;HashRateTargetHs:0;HashRateHs:0;HashRateTargetKhs:0;HashRateKhs:0;MinerPayload:Nil;PoW:Nil;SafeBoxHash:Nil;AccumulatedWork:0;TimeAverage200:0;TimeAverage150:0;TimeAverage100:0;TimeAverage75:0;TimeAverage50:0;TimeAverage25:0;TimeAverage10:0);
   CT_TBlockChainData_NUL : TBlockChainData = (Block:0;Timestamp:0;BlockProtocolVersion:0;BlockProtocolAvailable:0;OperationsCount:-1;Volume:-1;Reward:0;Fee:0;Target:0;HashRateTargetHs:0;HashRateHs:0;HashRateTargetKhs:0;HashRateKhs:0;MinerPayload:Nil;PoW:Nil;SafeBoxHash:Nil;AccumulatedWork:0;TimeAverage200:0;TimeAverage150:0;TimeAverage100:0;TimeAverage75:0;TimeAverage50:0;TimeAverage25:0;TimeAverage10:0);
-
+  CT_TAccountsGridFilter_NUL : TAccountsGridFilter = (MinBalance:-1;MaxBalance:-1;OrderedAccountsKeyList:Nil;indexAccountsKeyList:-1);
 
 
 implementation
 implementation
 
 
@@ -233,6 +268,106 @@ uses
   Graphics, SysUtils, UTime, UOpTransaction, UConst,
   Graphics, SysUtils, UTime, UOpTransaction, UConst,
   UFRMPayloadDecoder, ULog;
   UFRMPayloadDecoder, ULog;
 
 
+{ TAccountsGridUpdateThread }
+
+procedure TAccountsGridUpdateThread.BCExecute;
+Var Laccl, LacclTemp : TOrderedCardinalList;
+  l : TOrderedCardinalList;
+  i,j : Integer;
+  c  : Cardinal;
+  LApplyfilter : Boolean;
+  LAccount : TAccount;
+  LNode : TNode;
+begin
+  LApplyfilter := ((FAccountsGridFilter.MinBalance>0) Or ((FAccountsGridFilter.MaxBalance>=0) And (FAccountsGridFilter.MaxBalance<CT_MaxWalletAmount)));
+  FBalance := 0;
+  LNode := FAccountsGrid.Node;
+  try
+    Laccl := TOrderedCardinalList.Create;
+    Try
+      Laccl.Clear;
+
+      if (Assigned(FAccountsGridFilter.OrderedAccountsKeyList)) then begin
+        if (FAccountsGridFilter.indexAccountsKeyList<0) then i := 0
+        else i := FAccountsGridFilter.indexAccountsKeyList;
+
+        while (Not Terminated) and (i<FAccountsGridFilter.OrderedAccountsKeyList.Count)
+          and ((FAccountsGridFilter.indexAccountsKeyList<0) or (FAccountsGridFilter.indexAccountsKeyList=i)) do begin
+
+          FAccountsGridFilter.OrderedAccountsKeyList.Lock; // Protection v4
+          Try
+            l := FAccountsGridFilter.OrderedAccountsKeyList.AccountKeyList[i];
+            for j := 0 to l.Count - 1 do begin
+              LAccount := LNode.Bank.SafeBox.Account(l.Get(j));
+              if LApplyfilter then begin
+                if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
+                  Laccl.Add(LAccount.account);
+                  FBalance := FBalance + LAccount.balance;
+                end;
+              end else begin
+                Laccl.Add(LAccount.account);
+                FBalance := FBalance + LAccount.balance;
+              end;
+              if Terminated then Exit;
+            end;
+          finally
+            FAccountsGridFilter.OrderedAccountsKeyList.Unlock;
+          end;
+          inc(i);
+        end;
+      end else begin
+        c := 0;
+        while (c<LNode.Bank.SafeBox.AccountsCount) and (Not Terminated) do begin
+          LAccount := LNode.Bank.SafeBox.Account(c);
+          if (LAccount.balance>=FAccountsGridFilter.MinBalance) And ((FAccountsGridFilter.MaxBalance<0) Or (LAccount.balance<=FAccountsGridFilter.MaxBalance)) then begin
+            Laccl.Add(LAccount.account);
+            FBalance := FBalance + LAccount.balance;
+          end;
+          inc(c);
+        end;
+      end;
+    Finally
+      try
+        if Not Terminated then begin
+          LacclTemp := FAccountsGrid.LockAccountsList;
+          try
+            LacclTemp.CopyFrom(Laccl);
+          finally
+            FAccountsGrid.UnlockAccountsList;
+          end;
+        end;
+      finally
+        Laccl.Free;
+      end;
+    End;
+  Finally
+    FisProcessing := False;
+    if Not Terminated then
+      Synchronize(SynchronizedOnTerminated);
+  End;
+end;
+
+constructor TAccountsGridUpdateThread.Create(AAccountsGrid: TAccountsGrid; AAccountsGridFilter: TAccountsGridFilter);
+begin
+  inherited Create(True);
+  FreeOnTerminate := False;
+  FAccountsGrid := AAccountsGrid;
+  FAccountsGridFilter := AAccountsGridFilter;
+  FisProcessing := True;
+  Suspended := False;
+end;
+
+destructor TAccountsGridUpdateThread.Destroy;
+begin
+  inherited;
+end;
+
+procedure TAccountsGridUpdateThread.SynchronizedOnTerminated;
+begin
+  FAccountsGrid.FAccountsBalance := FBalance;
+  if Assigned(FAccountsGrid.FOnAccountsGridUpdatedData) then  FAccountsGrid.FOnAccountsGridUpdatedData(FAccountsGrid);
+end;
+
 { TAccountsGrid }
 { TAccountsGrid }
 
 
 Const CT_ColumnHeader : Array[TAccountColumnType] Of String =
 Const CT_ColumnHeader : Array[TAccountColumnType] Of String =
@@ -241,7 +376,7 @@ Const CT_ColumnHeader : Array[TAccountColumnType] Of String =
 function TAccountsGrid.AccountNumber(GridRow: Integer): Int64;
 function TAccountsGrid.AccountNumber(GridRow: Integer): Int64;
 begin
 begin
   if GridRow<1 then Result := -1
   if GridRow<1 then Result := -1
-  else if FShowAllAccounts then begin
+  else if (FAccountsGridDatasource=acds_Node) then begin
     if Assigned(Node) then begin
     if Assigned(Node) then begin
       Result := GridRow-1;
       Result := GridRow-1;
     end else Result := -1;
     end else Result := -1;
@@ -257,8 +392,6 @@ begin
   FAllowMultiSelect := false;
   FAllowMultiSelect := false;
   FOnUpdated := Nil;
   FOnUpdated := Nil;
   FAccountsBalance := 0;
   FAccountsBalance := 0;
-  FAccountsCount := 0;
-  FShowAllAccounts := false;
   FAccountsList := TOrderedCardinalList.Create;
   FAccountsList := TOrderedCardinalList.Create;
   FDrawGrid := Nil;
   FDrawGrid := Nil;
   SetLength(FColumns,7);
   SetLength(FColumns,7);
@@ -278,15 +411,31 @@ begin
   FColumns[6].width := 25;
   FColumns[6].width := 25;
   FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
   FNodeNotifyEvents := TNodeNotifyEvents.Create(Self);
   FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
   FNodeNotifyEvents.OnOperationsChanged := OnNodeNewOperation;
+  FAccountsGridUpdateThread := Nil;
+  FOnAccountsGridUpdatedData := Nil;
+  FAccountsGridFilter := CT_TAccountsGridFilter_NUL;
+  FAccountsGridDatasource := acds_Node;
 end;
 end;
 
 
 destructor TAccountsGrid.Destroy;
 destructor TAccountsGrid.Destroy;
 begin
 begin
+  TerminateAccountGridUpdateThread;
   FNodeNotifyEvents.Free;
   FNodeNotifyEvents.Free;
   FAccountsList.Free;
   FAccountsList.Free;
   inherited;
   inherited;
 end;
 end;
 
 
+function TAccountsGrid.GetAccountsCount: Integer;
+begin
+  if Not Assigned(Node) then Exit(0);
+  
+  case FAccountsGridDatasource of
+    acds_Node: Result := Node.Bank.AccountsCount;
+  else
+    Result := FAccountsList.Count;
+  end;
+end;
+
 function TAccountsGrid.GetNode: TNode;
 function TAccountsGrid.GetNode: TNode;
 begin
 begin
   Result := FNodeNotifyEvents.Node;
   Result := FNodeNotifyEvents.Node;
@@ -294,26 +443,16 @@ end;
 
 
 procedure TAccountsGrid.InitGrid;
 procedure TAccountsGrid.InitGrid;
 Var i : Integer;
 Var i : Integer;
-  acc : TAccount;
 begin
 begin
-  FAccountsBalance := 0;
-  FAccountsCount := FAccountsList.Count;
   if Not assigned(DrawGrid) then exit;
   if Not assigned(DrawGrid) then exit;
-  if FShowAllAccounts then begin
+  if FAccountsGridDatasource=acds_Node then begin
     if Assigned(Node) then begin
     if Assigned(Node) then begin
       if Node.Bank.AccountsCount<1 then DrawGrid.RowCount := 2
       if Node.Bank.AccountsCount<1 then DrawGrid.RowCount := 2
       else DrawGrid.RowCount := Node.Bank.AccountsCount+1;
       else DrawGrid.RowCount := Node.Bank.AccountsCount+1;
-      FAccountsBalance := Node.Bank.SafeBox.TotalBalance;
     end else DrawGrid.RowCount := 2;
     end else DrawGrid.RowCount := 2;
   end else begin
   end else begin
     if FAccountsList.Count<1 then DrawGrid.RowCount := 2
     if FAccountsList.Count<1 then DrawGrid.RowCount := 2
     else DrawGrid.RowCount := FAccountsList.Count+1;
     else DrawGrid.RowCount := FAccountsList.Count+1;
-    if Assigned(Node) then begin
-      for i := 0 to FAccountsList.Count - 1 do begin
-        acc := Node.Bank.SafeBox.Account( FAccountsList.Get(i) );
-        inc(FAccountsBalance, acc.balance);
-      end;
-    end;
   end;
   end;
   DrawGrid.FixedRows := 1;
   DrawGrid.FixedRows := 1;
   if Length(FColumns)=0 then DrawGrid.ColCount := 1
   if Length(FColumns)=0 then DrawGrid.ColCount := 1
@@ -332,6 +471,12 @@ begin
   if Assigned(FOnUpdated) then FOnUpdated(Self);
   if Assigned(FOnUpdated) then FOnUpdated(Self);
 end;
 end;
 
 
+function TAccountsGrid.IsUpdatingData: Boolean;
+begin
+  if Assigned(FAccountsGridUpdateThread) then Result := FAccountsGridUpdateThread.IsProcessing
+  else Result := False;
+end;
+
 procedure TAccountsGrid.LoadFromStream(Stream: TStream);
 procedure TAccountsGrid.LoadFromStream(Stream: TStream);
 Var c,i,j : Integer;
 Var c,i,j : Integer;
 begin
 begin
@@ -364,7 +509,7 @@ begin
   if Not Assigned(FDrawGrid) then exit;
   if Not Assigned(FDrawGrid) then exit;
   if Not Assigned(Node) then exit;
   if Not Assigned(Node) then exit;
   if FDrawGrid.RowCount<=1 then exit;
   if FDrawGrid.RowCount<=1 then exit;
-  if FShowAllAccounts then begin
+  if FAccountsGridDatasource=acds_Node then begin
     If (FDrawGrid.RowCount>nAccount+1) And (nAccount>=0) And (nAccount<Node.Bank.AccountsCount) then begin
     If (FDrawGrid.RowCount>nAccount+1) And (nAccount>=0) And (nAccount<Node.Bank.AccountsCount) then begin
       FDrawGrid.Row := nAccount+1;
       FDrawGrid.Row := nAccount+1;
       Result := true;
       Result := true;
@@ -608,6 +753,19 @@ begin
   Result := accounts.Count;
   Result := accounts.Count;
 end;
 end;
 
 
+procedure TAccountsGrid.SetAccountsGridDatasource(const Value: TAccountsGridDatasource);
+begin
+  if FAccountsGridDatasource=Value then Exit;
+  FAccountsGridDatasource := Value;
+  UpdateData;
+end;
+
+procedure TAccountsGrid.SetAccountsGridFilter(const Value: TAccountsGridFilter);
+begin
+  FAccountsGridFilter := Value;
+  UpdateData;
+end;
+
 procedure TAccountsGrid.SetAllowMultiSelect(const Value: Boolean);
 procedure TAccountsGrid.SetAllowMultiSelect(const Value: Boolean);
 begin
 begin
   FAllowMultiSelect := Value;
   FAllowMultiSelect := Value;
@@ -621,7 +779,7 @@ begin
   if Assigned(Value) then begin
   if Assigned(Value) then begin
     Value.FreeNotification(self);
     Value.FreeNotification(self);
     FDrawGrid.OnDrawCell := OnGridDrawCell;
     FDrawGrid.OnDrawCell := OnGridDrawCell;
-    InitGrid;
+    UpdateData;
   end;
   end;
 end;
 end;
 
 
@@ -629,19 +787,56 @@ procedure TAccountsGrid.SetNode(const Value: TNode);
 begin
 begin
   if GetNode=Value then exit;
   if GetNode=Value then exit;
   FNodeNotifyEvents.Node := Value;
   FNodeNotifyEvents.Node := Value;
-  InitGrid;
+  UpdateData;
 end;
 end;
 
 
-procedure TAccountsGrid.SetShowAllAccounts(const Value: Boolean);
+procedure TAccountsGrid.TerminateAccountGridUpdateThread;
 begin
 begin
-  if FShowAllAccounts=Value then exit;
-  FShowAllAccounts := Value;
-  InitGrid;
+  if Assigned(FAccountsGridUpdateThread) then begin
+    FAccountsGridUpdateThread.Terminate;
+    FAccountsGridUpdateThread.WaitFor;
+    FreeAndNil(FAccountsGridUpdateThread);
+  end;
 end;
 end;
 
 
 procedure TAccountsGrid.UnlockAccountsList;
 procedure TAccountsGrid.UnlockAccountsList;
 begin
 begin
+  UpdateAccountsBalance;
+  InitGrid;
+end;
+
+procedure TAccountsGrid.UpdateAccountsBalance;
+var i : Integer;
+  LAcc : TAccount;
+begin
+  if Assigned(Node) and (AccountsGridDatasource=acds_InternalList) then begin
+    FAccountsBalance := 0;
+    case FAccountsGridDatasource of
+      acds_Node: FAccountsBalance := Node.Bank.SafeBox.TotalBalance;
+      acds_InternalList: begin
+        for i := 0 to FAccountsList.Count - 1 do begin
+          LAcc := Node.Bank.SafeBox.Account( FAccountsList.Get(i) );
+          inc(FAccountsBalance, LAcc.balance);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TAccountsGrid.UpdateData;
+begin
+  UpdateAccountsBalance;
+  if Assigned(Node) then begin
+    case FAccountsGridDatasource of
+      acds_NodeFiltered: begin
+        TerminateAccountGridUpdateThread;
+        FAccountsBalance := 0;
+        FAccountsGridUpdateThread := TAccountsGridUpdateThread.Create(Self,AccountsGridFilter);
+      end;
+    end;
+  end;
   InitGrid;
   InitGrid;
+  if Assigned(FOnAccountsGridUpdatedData) then FOnAccountsGridUpdatedData(Self);
 end;
 end;
 
 
 { TOperationsGridUpdateThread }
 { TOperationsGridUpdateThread }