Refactor internal structures for grid/table sorting, prefer TObjectList over Array

This commit is contained in:
Ansgar Becker
2023-01-22 12:49:53 +01:00
parent 9d8c8e7628
commit 7ff9b2e9b7
5 changed files with 170 additions and 134 deletions

View File

@ -18,11 +18,21 @@ uses
type type
TOrderCol = class(TObject) TSortItemOrder = (sioAscending, sioDescending);
ColumnName: String; TSortItem = class(TPersistent)
SortDirection: Byte; public
Column: String;
Order: TSortItemOrder;
constructor Create; overload;
constructor Create(lColumn: String; lOrder: TSortItemOrder=sioAscending); overload;
procedure Assign(Source: TPersistent); override;
end;
TSortItems = class(TObjectList<TSortItem>)
public
function ComposeOrderClause: String;
function FindByColumn(Column: String): TSortItem;
procedure Assign(Source: TSortItems);
end; end;
TOrderColArray = Array of TOrderCol;
TLineBreaks = (lbsNone, lbsWindows, lbsUnix, lbsMac, lbsWide, lbsMixed); TLineBreaks = (lbsNone, lbsWindows, lbsUnix, lbsMac, lbsWide, lbsMixed);
@ -335,7 +345,6 @@ type
procedure FixVT(VT: TVirtualStringTree; MultiLineCount: Word=1); procedure FixVT(VT: TVirtualStringTree; MultiLineCount: Word=1);
function GetTextHeight(Font: TFont): Integer; function GetTextHeight(Font: TFont): Integer;
function ColorAdjustBrightness(Col: TColor; Shift: SmallInt): TColor; function ColorAdjustBrightness(Col: TColor; Shift: SmallInt): TColor;
function ComposeOrderClause(Cols: TOrderColArray): String;
procedure DeInitializeVTNodes(Sender: TBaseVirtualTree); procedure DeInitializeVTNodes(Sender: TBaseVirtualTree);
function FindNode(VT: TVirtualStringTree; idx: Int64; ParentNode: PVirtualNode): PVirtualNode; function FindNode(VT: TVirtualStringTree; idx: Int64; ParentNode: PVirtualNode): PVirtualNode;
function SelectNode(VT: TVirtualStringTree; idx: Int64; ParentNode: PVirtualNode=nil): Boolean; overload; function SelectNode(VT: TVirtualStringTree; idx: Int64; ParentNode: PVirtualNode=nil): Boolean; overload;
@ -1425,28 +1434,6 @@ begin
end; end;
{**
Concat all sort options to a ORDER clause
}
function ComposeOrderClause(Cols: TOrderColArray): String;
var
i : Integer;
sort : String;
begin
result := '';
for i := 0 to Length(Cols) - 1 do
begin
if result <> '' then
result := result + ', ';
if Cols[i].SortDirection = ORDER_ASC then
sort := TXT_ASC
else
sort := TXT_DESC;
result := result + MainForm.ActiveConnection.QuoteIdent( Cols[i].ColumnName ) + ' ' + sort;
end;
end;
procedure DeInitializeVTNodes(Sender: TBaseVirtualTree); procedure DeInitializeVTNodes(Sender: TBaseVirtualTree);
var var
Node: PVirtualNode; Node: PVirtualNode;
@ -1817,6 +1804,82 @@ begin
end; end;
{ *** TSortItem }
constructor TSortItem.Create;
begin
inherited;
Column := '';
Order := sioAscending;
end;
constructor TSortItem.Create(lColumn: String; lOrder: TSortItemOrder=sioAscending);
begin
inherited Create;
Column := lColumn;
Order := lOrder;
end;
procedure TSortItem.Assign(Source: TPersistent);
var
SourceItem: TSortItem;
begin
if Source is TSortItem then begin
SourceItem := Source as TSortItem;
Column := SourceItem.Column;
Order := SourceItem.Order;
end
else
Inherited;
end;
{ *** TSortItems }
function TSortItems.ComposeOrderClause: String;
var
SortItem: TSortItem;
Conn: TDBConnection;
begin
// Concat all sort options to an ORDER BY clause
Result := '';
Conn := MainForm.ActiveConnection;
for SortItem in Self do begin
if Result <> '' then
Result := Result + ', ';
Result := Result + Conn.QuoteIdent(SortItem.Column) +
' ' + IfThen(SortItem.Order = sioAscending, Conn.GetSQLSpecifity(spOrderAsc), Conn.GetSQLSpecifity(spOrderDesc));
end;
end;
function TSortItems.FindByColumn(Column: String): TSortItem;
var
SortItem: TSortItem;
begin
Result := nil;
for SortItem in Self do begin
if SortItem.Column = Column then begin
Result := SortItem;
Break;
end;
end;
end;
procedure TSortItems.Assign(Source: TSortItems);
var
Item, ItemCopy: TSortItem;
begin
Clear;
for Item in Source do begin
ItemCopy := TSortItem.Create;
ItemCopy.Assign(Item);
Add(ItemCopy);
end;
end;
{ *** TDBObjectEditor } { *** TDBObjectEditor }

View File

@ -71,12 +71,6 @@ const
{Pebibyte} NAME_PB = ' PiB'; {Pebibyte} NAME_PB = ' PiB';
{Exbibyte} NAME_EB = ' EiB'; {Exbibyte} NAME_EB = ' EiB';
// Used by ListViews and Grids
ORDER_ASC = 0; // Used for tag-value of "Direction"-button
ORDER_DESC = 1; // dito
TXT_ASC = 'ASC'; // Used for caption of "Direction"-button
TXT_DESC = 'DESC'; // dito
// Data grid: How many bytes to fetch from data fields that are potentially large. // Data grid: How many bytes to fetch from data fields that are potentially large.
GRIDMAXDATA: Integer = 256; GRIDMAXDATA: Integer = 256;

View File

@ -24,7 +24,7 @@ type
private private
{ Private declarations } { Private declarations }
FColumnNames: TStringList; FColumnNames: TStringList;
FOrderColumns: TOrderColArray; FSortItems: TSortItems;
FOldOrderClause: String; FOldOrderClause: String;
procedure comboColumnsChange(Sender: TObject); procedure comboColumnsChange(Sender: TObject);
procedure btnOrderClick(Sender: TObject); procedure btnOrderClick(Sender: TObject);
@ -53,8 +53,9 @@ begin
FColumnNames.Add(Mainform.SelectedTableColumns[i].Name); FColumnNames.Add(Mainform.SelectedTableColumns[i].Name);
end; end;
FOrderColumns := Copy(Mainform.DataGridSortColumns, 0, MaxInt); FSortItems := TSortItems.Create(True);
FOldOrderClause := ComposeOrderClause(FOrderColumns); FSortItems.Assign(MainForm.DataGridSortItems);
FOldOrderClause := FSortItems.ComposeOrderClause;
// First creation of controls // First creation of controls
DisplaySortingControls(Sender); DisplaySortingControls(Sender);
@ -66,6 +67,7 @@ end;
} }
procedure TfrmDataSorting.DisplaySortingControls(Sender: TObject); procedure TfrmDataSorting.DisplaySortingControls(Sender: TObject);
var var
SortItem: TSortItem;
lblNumber: TLabel; lblNumber: TLabel;
btnDelete: TButton; btnDelete: TButton;
comboColumns: TComboBox; comboColumns: TComboBox;
@ -94,7 +96,8 @@ begin
// Create line with controls for each order column // Create line with controls for each order column
// TODO: disable repaint on every created control. Sending WM_SETREDRAW=0 message creates artefacts. // TODO: disable repaint on every created control. Sending WM_SETREDRAW=0 message creates artefacts.
LockWindowUpdate(pnlBevel.Handle); LockWindowUpdate(pnlBevel.Handle);
for i:=0 to Length(FOrderColumns)-1 do begin for i:=0 to FSortItems.Count-1 do begin
SortItem := FSortItems[i];
// 1. Label with number // 1. Label with number
lblNumber := TLabel.Create(self); lblNumber := TLabel.Create(self);
lblNumber.Parent := pnlBevel; lblNumber.Parent := pnlBevel;
@ -115,7 +118,7 @@ begin
comboColumns.Top := TopPos; comboColumns.Top := TopPos;
comboColumns.Items.Text := FColumnNames.Text; comboColumns.Items.Text := FColumnNames.Text;
comboColumns.Style := csDropDownList; // Not editable comboColumns.Style := csDropDownList; // Not editable
comboColumns.ItemIndex := FColumnNames.IndexOf(FOrderColumns[i].ColumnName); comboColumns.ItemIndex := FColumnNames.IndexOf(SortItem.Column);
comboColumns.Tag := i+1; comboColumns.Tag := i+1;
comboColumns.OnChange := comboColumnsChange; comboColumns.OnChange := comboColumnsChange;
lblNumber.Height := comboColumns.Height; lblNumber.Height := comboColumns.Height;
@ -131,7 +134,7 @@ begin
btnOrder.GroupIndex := i+1; // if > 0 enables Down = True btnOrder.GroupIndex := i+1; // if > 0 enables Down = True
btnOrder.Glyph.Transparent := True; btnOrder.Glyph.Transparent := True;
btnOrder.Glyph.AlphaFormat := afDefined; btnOrder.Glyph.AlphaFormat := afDefined;
if FOrderColumns[i].SortDirection = ORDER_DESC then begin if SortItem.Order = sioDescending then begin
MainForm.VirtualImageListMain.GetBitmap(110, btnOrder.Glyph); MainForm.VirtualImageListMain.GetBitmap(110, btnOrder.Glyph);
btnOrder.Down := True; btnOrder.Down := True;
end else begin end else begin
@ -200,7 +203,7 @@ var
combo : TComboBox; combo : TComboBox;
begin begin
combo := Sender as TComboBox; combo := Sender as TComboBox;
FOrderColumns[combo.Tag-1].ColumnName := combo.Text; FSortItems[combo.Tag-1].Column := combo.Text;
// Enables OK button // Enables OK button
Modified; Modified;
@ -216,12 +219,12 @@ var
begin begin
btn := Sender as TSpeedButton; btn := Sender as TSpeedButton;
btn.Glyph := nil; btn.Glyph := nil;
if FOrderColumns[btn.Tag-1].SortDirection = ORDER_ASC then begin if FSortItems[btn.Tag-1].Order = sioAscending then begin
MainForm.VirtualImageListMain.GetBitmap(110, btn.Glyph); MainForm.VirtualImageListMain.GetBitmap(110, btn.Glyph);
FOrderColumns[btn.Tag-1].SortDirection := ORDER_DESC; FSortItems[btn.Tag-1].Order := sioDescending;
end else begin end else begin
MainForm.VirtualImageListMain.GetBitmap(109, btn.Glyph); MainForm.VirtualImageListMain.GetBitmap(109, btn.Glyph);
FOrderColumns[btn.Tag-1].SortDirection := ORDER_ASC; FSortItems[btn.Tag-1].Order := sioAscending;
end; end;
// Enables OK button // Enables OK button
@ -235,24 +238,11 @@ end;
procedure TfrmDataSorting.btnDeleteClick(Sender: TObject); procedure TfrmDataSorting.btnDeleteClick(Sender: TObject);
var var
btn: TButton; btn: TButton;
i : Integer;
begin begin
btn := Sender as TButton; btn := Sender as TButton;
FSortItems.Delete(btn.Tag-1);
if Length(FOrderColumns)>1 then
begin
// Move remaining items one up
for i := btn.Tag-1 to Length(FOrderColumns) - 2 do
begin
FOrderColumns[i] := FOrderColumns[i+1];
end;
end;
// Delete last item
SetLength(FOrderColumns, Length(FOrderColumns)-1);
// Refresh controls // Refresh controls
DisplaySortingControls(Sender); DisplaySortingControls(Self);
// Enables OK button // Enables OK button
Modified; Modified;
end; end;
@ -263,30 +253,23 @@ end;
} }
procedure TfrmDataSorting.btnAddColClick(Sender: TObject); procedure TfrmDataSorting.btnAddColClick(Sender: TObject);
var var
i, new : Integer;
UnusedColumns: TStringList; UnusedColumns: TStringList;
NewSortItem, SortItem: TSortItem;
begin begin
SetLength(FOrderColumns, Length(FOrderColumns)+1 ); NewSortItem := TSortItem.Create;
new := Length(FOrderColumns)-1; FSortItems.Add(NewSortItem);
FOrderColumns[new] := TOrderCol.Create;
// Take first unused column as default for new sort column // Take first unused column as default for new sort item
UnusedColumns := TStringList.Create; UnusedColumns := TStringList.Create;
UnusedColumns.AddStrings(FColumnNames); UnusedColumns.AddStrings(FColumnNames);
for i := 0 to Length(FOrderColumns) - 1 do for SortItem in FSortItems do begin
begin if UnusedColumns.IndexOf(SortItem.Column) > -1 then
if UnusedColumns.IndexOf(FOrderColumns[i].ColumnName) > -1 then UnusedColumns.Delete(UnusedColumns.IndexOf(SortItem.Column));
begin
UnusedColumns.Delete( UnusedColumns.IndexOf(FOrderColumns[i].ColumnName) );
end;
end; end;
if UnusedColumns.Count > 0 then if UnusedColumns.Count > 0 then
FOrderColumns[new].ColumnName := UnusedColumns[0] NewSortItem.Column := UnusedColumns[0]
else else
FOrderColumns[new].ColumnName := FColumnNames[0]; NewSortItem.Column := FColumnNames[0];
// Sort ASC by default
FOrderColumns[new].SortDirection := ORDER_ASC;
// Refresh controls // Refresh controls
DisplaySortingControls(Sender); DisplaySortingControls(Sender);
@ -302,7 +285,7 @@ end;
} }
procedure TfrmDataSorting.Modified; procedure TfrmDataSorting.Modified;
begin begin
btnOk.Enabled := ComposeOrderClause(FOrderColumns) <> FOldOrderClause; btnOk.Enabled := FSortItems.ComposeOrderClause <> FOldOrderClause;
end; end;
@ -312,7 +295,7 @@ end;
procedure TfrmDataSorting.btnOKClick(Sender: TObject); procedure TfrmDataSorting.btnOKClick(Sender: TObject);
begin begin
// TODO: apply ordering // TODO: apply ordering
Mainform.DataGridSortColumns := FOrderColumns; MainForm.DataGridSortItems.Assign(FSortItems);
InvalidateVT(Mainform.DataGrid, VTREE_NOTLOADED_PURGECACHE, False); InvalidateVT(Mainform.DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
btnCancel.OnClick(Sender); btnCancel.OnClick(Sender);
end; end;

View File

@ -426,7 +426,8 @@ type
spISSchemaCol, spISSchemaCol,
spUSEQuery, spKillQuery, spKillProcess, spUSEQuery, spKillQuery, spKillProcess,
spFuncLength, spFuncCeil, spFuncLeft, spFuncNow, spFuncLength, spFuncCeil, spFuncLeft, spFuncNow,
spLockedTables, spDisableForeignKeyChecks, spEnableForeignKeyChecks); spLockedTables, spDisableForeignKeyChecks, spEnableForeignKeyChecks,
spOrderAsc, spOrderDesc);
TDBConnection = class(TComponent) TDBConnection = class(TComponent)
private private
@ -3017,6 +3018,9 @@ begin
[FParameters.Hostname, FParameters.NetTypeName(True), FParameters.Username, UsingPass] [FParameters.Hostname, FParameters.NetTypeName(True), FParameters.Username, UsingPass]
)); ));
FSQLSpecifities[spOrderAsc] := 'ASC';
FSQLSpecifities[spOrderDesc] := 'DESC';
case Parameters.NetTypeGroup of case Parameters.NetTypeGroup of
ngMySQL: begin ngMySQL: begin
FSQLSpecifities[spDatabaseDrop] := 'DROP DATABASE %s'; FSQLSpecifities[spDatabaseDrop] := 'DROP DATABASE %s';

View File

@ -1211,6 +1211,7 @@ type
FDataGridColumnWidthsCustomized: Boolean; FDataGridColumnWidthsCustomized: Boolean;
FDataGridLastClickedColumnHeader: Integer; FDataGridLastClickedColumnHeader: Integer;
FDataGridLastClickedColumnLeftPos: Integer; FDataGridLastClickedColumnLeftPos: Integer;
FDataGridSortItems: TSortItems;
FSnippetFilenames: TStringList; FSnippetFilenames: TStringList;
FConnections: TDBConnectionList; FConnections: TDBConnectionList;
FTreeClickHistory: TNodeArray; FTreeClickHistory: TNodeArray;
@ -1292,7 +1293,6 @@ type
// Data grid related stuff // Data grid related stuff
DataGridHiddenColumns: TStringList; DataGridHiddenColumns: TStringList;
DataGridSortColumns: TOrderColArray;
DataGridWantedRowCount: Int64; DataGridWantedRowCount: Int64;
DataGridTable: TDBObject; DataGridTable: TDBObject;
DataGridFocusedCell: TStringList; DataGridFocusedCell: TStringList;
@ -1348,6 +1348,7 @@ type
procedure SetupSynEditor(Editor: TSynMemo); procedure SetupSynEditor(Editor: TSynMemo);
function AnyGridEnsureFullRow(Grid: TVirtualStringTree; Node: PVirtualNode): Boolean; function AnyGridEnsureFullRow(Grid: TVirtualStringTree; Node: PVirtualNode): Boolean;
procedure DataGridEnsureFullRows(Grid: TVirtualStringTree; SelectedOnly: Boolean); procedure DataGridEnsureFullRows(Grid: TVirtualStringTree; SelectedOnly: Boolean);
property DataGridSortItems: TSortItems read FDataGridSortItems write FDataGridSortItems;
function GetEncodingByName(Name: String): TEncoding; function GetEncodingByName(Name: String): TEncoding;
function GetEncodingName(Encoding: TEncoding): String; function GetEncodingName(Encoding: TEncoding): String;
function GetCharsetByEncoding(Encoding: TEncoding): String; function GetCharsetByEncoding(Encoding: TEncoding): String;
@ -2050,6 +2051,8 @@ begin
DatatypeCategories[dtcOther].Color := AppSettings.ReadInt(asFieldColorOther); DatatypeCategories[dtcOther].Color := AppSettings.ReadInt(asFieldColorOther);
CalcNullColors; CalcNullColors;
FDataGridSortItems := TSortItems.Create(True);
DataLocalNumberFormat := AppSettings.ReadBool(asDataLocalNumberFormat); DataLocalNumberFormat := AppSettings.ReadBool(asDataLocalNumberFormat);
DataGridTable := nil; DataGridTable := nil;
FActiveDbObj := nil; FActiveDbObj := nil;
@ -5724,21 +5727,21 @@ const
NumSortChars: Array of Char = ['¹','²','³','⁴','⁵','⁶','⁷','⁸','⁹','⁺']; NumSortChars: Array of Char = ['¹','²','³','⁴','⁵','⁶','⁷','⁸','⁹','⁺'];
procedure GetSortIndex(Column: TVirtualTreeColumn; var SortIndex: Integer; var SortDirection: VirtualTrees.TSortDirection); procedure GetSortIndex(Column: TVirtualTreeColumn; var SortIndex: Integer; var SortDirection: VirtualTrees.TSortDirection);
var i: Integer; var
SortItem: TSortItem;
begin begin
SortIndex := -1; SortIndex := -1;
if Column.Owner.Header.Treeview = DataGrid then begin if Column.Owner.Header.Treeview = DataGrid then begin
// Data grid supports multiple sorted columns // Data grid supports multiple sorted columns
for i:=0 to Length(DataGridSortColumns)-1 do begin SortItem := FDataGridSortItems.FindByColumn(PaintInfo.Column.Text);
if DataGridSortColumns[i].ColumnName = PaintInfo.Column.Text then begin if Assigned(SortItem) then begin
SortIndex := i; SortIndex := FDataGridSortItems.IndexOf(SortItem);
if DataGridSortColumns[i].SortDirection = ORDER_ASC then if SortItem.Order = sioAscending then
SortDirection := sdAscending SortDirection := sdAscending
else else
SortDirection := sdDescending; SortDirection := sdDescending;
Break;
end;
end; end;
end else begin end else begin
// We're in a query grid, supporting a single sorted column // We're in a query grid, supporting a single sorted column
if Column.Owner.Header.SortColumn = Column.Index then begin if Column.Owner.Header.SortColumn = Column.Index then begin
@ -5962,10 +5965,10 @@ begin
SynMemoFilter.OnStatusChange(SynMemoFilter, []); SynMemoFilter.OnStatusChange(SynMemoFilter, []);
// Append ORDER clause // Append ORDER clause
if Length(DataGridSortColumns) > 0 then begin if FDataGridSortItems.Count > 0 then begin
Select := Select + ' ORDER BY ' + ComposeOrderClause(DataGridSortColumns); Select := Select + ' ORDER BY ' + FDataGridSortItems.ComposeOrderClause;
tbtnDataSorting.ImageIndex := 108; tbtnDataSorting.ImageIndex := 108;
tbtnDataSorting.Caption := _('Sorting') + ' ('+IntToStr(Length(DataGridSortColumns))+')'; tbtnDataSorting.Caption := _('Sorting') + ' ('+IntToStr(FDataGridSortItems.Count)+')';
end else begin end else begin
tbtnDataSorting.ImageIndex := 107; tbtnDataSorting.ImageIndex := 107;
tbtnDataSorting.Caption := _('Sorting'); tbtnDataSorting.Caption := _('Sorting');
@ -10287,9 +10290,8 @@ end;
procedure TMainForm.DataGridHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo); procedure TMainForm.DataGridHeaderClick(Sender: TVTHeader; HitInfo: TVTHeaderHitInfo);
var var
frm: TForm; frm: TForm;
i, j: Integer;
columnexists : Boolean;
ColName: String; ColName: String;
SortItem: TSortItem;
begin begin
if HitInfo.Column = NoColumn then if HitInfo.Column = NoColumn then
Exit; Exit;
@ -10300,32 +10302,20 @@ begin
ColName := Sender.Columns[HitInfo.Column].Text; ColName := Sender.Columns[HitInfo.Column].Text;
// Add a new order column after a columns title has been clicked // Add a new order column after a columns title has been clicked
// Check if order column is already existant // Check if order column is already existant
columnexists := False; SortItem := FDataGridSortItems.FindByColumn(ColName);
for i := Low(DataGridSortColumns) to High(DataGridSortColumns) do begin if Assigned(SortItem) then begin
if DataGridSortColumns[i].ColumnName = ColName then begin
// AddOrderCol is already in the list. Switch its direction: // AddOrderCol is already in the list. Switch its direction:
// DESC > ASC > [delete col] // ASC > DESC > [delete col]
columnexists := True; if SortItem.Order = sioAscending then
if DataGridSortColumns[i].SortDirection = ORDER_DESC then SortItem.Order := sioDescending
DataGridSortColumns[i].SortDirection := ORDER_ASC else
FDataGridSortItems.Remove(SortItem);
end
else begin else begin
// Delete order col SortItem := TSortItem.Create(ColName, sioAscending);
for j := i to High(DataGridSortColumns) - 1 do FDataGridSortItems.Add(SortItem);
DataGridSortColumns[j] := DataGridSortColumns[j+1];
SetLength(DataGridSortColumns, Length(DataGridSortColumns)-1);
end;
// We found the matching column, no need to loop further
break;
end;
end; end;
if not columnexists then begin
i := Length(DataGridSortColumns);
SetLength(DataGridSortColumns, i+1);
DataGridSortColumns[i] := TOrderCol.Create;
DataGridSortColumns[i].ColumnName := ColName;
DataGridSortColumns[i].SortDirection := ORDER_DESC;
end;
// Refresh grid, and remember X scroll offset, so the just clicked column is still at the same place. // Refresh grid, and remember X scroll offset, so the just clicked column is still at the same place.
FDataGridLastClickedColumnHeader := HitInfo.Column; FDataGridLastClickedColumnHeader := HitInfo.Column;
FDataGridLastClickedColumnLeftPos := Sender.Columns[HitInfo.Column].Left; FDataGridLastClickedColumnLeftPos := Sender.Columns[HitInfo.Column].Left;
@ -10898,8 +10888,9 @@ end;
procedure TMainForm.HandleDataGridAttributes(RefreshingData: Boolean); procedure TMainForm.HandleDataGridAttributes(RefreshingData: Boolean);
var var
rx: TRegExpr; rx: TRegExpr;
idx, i: Integer; i: Integer;
Sort, KeyName, FocusedCol, CellFocus, Filter: String; Sort, KeyName, FocusedCol, CellFocus, Filter: String;
SortItem: TSortItem;
begin begin
actDataResetSorting.Enabled := False; actDataResetSorting.Enabled := False;
// Clear filter, column names and sort structure if gr // Clear filter, column names and sort structure if gr
@ -10939,7 +10930,7 @@ begin
if not RefreshingData then begin if not RefreshingData then begin
DataGridHiddenColumns.Clear; DataGridHiddenColumns.Clear;
SynMemoFilter.Clear; SynMemoFilter.Clear;
SetLength(DataGridSortColumns, 0); FDataGridSortItems.Clear;
DataGridWantedRowCount := 0; DataGridWantedRowCount := 0;
while DataGridFocusedNodeIndex >= DataGridWantedRowCount do while DataGridFocusedNodeIndex >= DataGridWantedRowCount do
Inc(DataGridWantedRowCount, AppSettings.ReadInt(asDatagridRowsPerStep)); Inc(DataGridWantedRowCount, AppSettings.ReadInt(asDatagridRowsPerStep));
@ -10956,8 +10947,10 @@ begin
else if AppSettings.ValueExists(asFilter) then else if AppSettings.ValueExists(asFilter) then
AppSettings.DeleteValue(asFilter); AppSettings.DeleteValue(asFilter);
for i := 0 to High(DataGridSortColumns) do Sort := '';
Sort := Sort + IntToStr(DataGridSortColumns[i].SortDirection) + '_' + DataGridSortColumns[i].ColumnName + DELIM; for SortItem in FDataGridSortItems do begin
Sort := Sort + IntToStr(Integer(SortItem.Order)) + '_' + SortItem.Column + DELIM;
end;
if Sort <> '' then if Sort <> '' then
AppSettings.WriteString(asSort, Sort) AppSettings.WriteString(asSort, Sort)
else if AppSettings.ValueExists(asSort) then else if AppSettings.ValueExists(asSort) then
@ -10992,26 +10985,25 @@ begin
// Sort // Sort
if AppSettings.ValueExists(asSort) then begin if AppSettings.ValueExists(asSort) then begin
SetLength(DataGridSortColumns, 0); FDataGridSortItems.Clear;
rx := TRegExpr.Create; rx := TRegExpr.Create;
rx.Expression := '\b(\d)_(.+)\'+DELIM; rx.Expression := '\b(\d)_(.+)\'+DELIM;
rx.ModifierG := False; rx.ModifierG := False;
if rx.Exec(AppSettings.ReadString(asSort)) then while true do begin if rx.Exec(AppSettings.ReadString(asSort)) then while true do begin
idx := Length(DataGridSortColumns);
// Check if column exists, could be renamed or deleted // Check if column exists, could be renamed or deleted
for i:=0 to SelectedTableColumns.Count-1 do begin for i:=0 to SelectedTableColumns.Count-1 do begin
if SelectedTableColumns[i].Name = rx.Match[2] then begin if SelectedTableColumns[i].Name = rx.Match[2] then begin
SetLength(DataGridSortColumns, idx+1); SortItem := TSortItem.Create;
DataGridSortColumns[idx] := TOrderCol.Create; SortItem.Column := rx.Match[2];
DataGridSortColumns[idx].ColumnName := rx.Match[2]; SortItem.Order := TSortItemOrder(StrToIntDef(rx.Match[1], 0));
DataGridSortColumns[idx].SortDirection := StrToIntDef(rx.Match[1], ORDER_ASC); FDataGridSortItems.Add(SortItem);
break; Break;
end; end;
end; end;
if not rx.ExecNext then if not rx.ExecNext then
break; break;
end; end;
actDataResetSorting.Enabled := Length(DataGridSortColumns) > 0; actDataResetSorting.Enabled := FDataGridSortItems.Count > 0;
end; end;
AppSettings.ResetPath; AppSettings.ResetPath;
@ -13177,7 +13169,7 @@ end;
procedure TMainForm.actDataResetSortingExecute(Sender: TObject); procedure TMainForm.actDataResetSortingExecute(Sender: TObject);
begin begin
SetLength(DataGridSortColumns, 0); FDataGridSortItems.Clear;
InvalidateVT(DataGrid, VTREE_NOTLOADED_PURGECACHE, False); InvalidateVT(DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
end; end;