mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Refactor internal structures for grid/table sorting, prefer TObjectList over Array
This commit is contained in:
@ -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 }
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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';
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user