mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00

This has one positive side effect: ViewData no longer re-saves an ORDERCLAUSE to registry after it has been read. At the same time the ORDERCLAUSE is read everytime when grid is filled, not only the first time. Those changes were needed to be able to apply an ORDERCLAUSE which was generated and saved by the new dialog. Left for later: Moving order-columns up and down. Tested that with a TUpDown which seems to ignore clicks sometimes and then doesn't fire OnClick.
351 lines
9.6 KiB
ObjectPascal
351 lines
9.6 KiB
ObjectPascal
unit data_sorting;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
|
Dialogs, StdCtrls, ExtCtrls, ComCtrls, Buttons, Registry, smdbgrid;
|
|
|
|
type
|
|
TOrderCol = record
|
|
ColumnName: String;
|
|
SortDirection: Byte;
|
|
end;
|
|
|
|
|
|
type
|
|
TDataSortingForm = class(TForm)
|
|
pnlBevel: TPanel;
|
|
btnOK: TButton;
|
|
btnCancel: TButton;
|
|
btnAddCol: TButton;
|
|
procedure btnAddColClick(Sender: TObject);
|
|
procedure btnOKClick(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
private
|
|
{ Private declarations }
|
|
ColumnNames : TStringList;
|
|
OrderColumns : Array of TOrderCol;
|
|
procedure DisplaySortingControls;
|
|
procedure dropdownColsChange( Sender: TObject );
|
|
procedure buttonOrderClick( Sender: TObject );
|
|
procedure buttonDeleteClick( Sender: TObject );
|
|
procedure Modified;
|
|
public
|
|
{ Public declarations }
|
|
end;
|
|
|
|
|
|
const
|
|
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
|
|
LINE_HEIGHT = 20; // Height of automatically created controls
|
|
MARGIN = 2; // Space between controls
|
|
MARGIN_BIG = 3 * MARGIN; // Space above the very first and last controls, used to separate stuff
|
|
|
|
implementation
|
|
|
|
uses main;
|
|
|
|
{$R *.dfm}
|
|
|
|
|
|
{**
|
|
Initialization
|
|
}
|
|
procedure TDataSortingForm.FormShow(Sender: TObject);
|
|
var
|
|
i : Cardinal;
|
|
grid: TSMDBGrid;
|
|
begin
|
|
// Take column names from listColumns and add here
|
|
ColumnNames := TStringList.Create;
|
|
for i := 0 to Mainform.Childwin.listColumns.Items.Count-1 do
|
|
begin
|
|
ColumnNames.Add( Mainform.Childwin.listColumns.Items[i].Caption );
|
|
end;
|
|
|
|
// Create one OrderColumns record for each grid.SortColumn
|
|
grid := Mainform.Childwin.gridData;
|
|
if grid.SortColumns.Count > 0 then // Avoids AV when accessing SortColumn[0] ... ??
|
|
begin
|
|
for i := 0 to grid.SortColumns.Count - 1 do
|
|
begin
|
|
SetLength( OrderColumns, i+1 );
|
|
OrderColumns[i].ColumnName := grid.SortColumns[i].FieldName;
|
|
if grid.SortColumns[i].SortType = stDescending then
|
|
OrderColumns[i].SortDirection := ORDER_ASC
|
|
else
|
|
OrderColumns[i].SortDirection := ORDER_DESC; // Also applies for SortType = stNone
|
|
end;
|
|
end;
|
|
|
|
// First creation of controls
|
|
DisplaySortingControls;
|
|
|
|
end;
|
|
|
|
|
|
{**
|
|
Create controls for order columns
|
|
}
|
|
procedure TDataSortingForm.DisplaySortingControls;
|
|
var
|
|
labelNumber: TLabel;
|
|
buttonDelete: TButton;
|
|
dropdownCols: TComboBox;
|
|
buttonOrder: TSpeedButton;
|
|
i, xPosition, topPosition, btnWidth : Integer;
|
|
begin
|
|
|
|
// Remove previously created components
|
|
for i := ComponentCount - 1 downto 0 do
|
|
begin
|
|
if Components[i].Tag > 0 then
|
|
Components[i].Free;
|
|
end;
|
|
|
|
// Set initial width to avoid resizing form to 0
|
|
xPosition := pnlBevel.Width;
|
|
|
|
|
|
// Create line with controls for each order column
|
|
for i:=0 to Length(OrderColumns)-1 do
|
|
begin
|
|
xPosition := pnlBevel.BorderWidth;
|
|
topPosition := pnlBevel.BorderWidth + MARGIN_BIG + (i * (LINE_HEIGHT + MARGIN));
|
|
|
|
// 1. Label with number
|
|
labelNumber := TLabel.Create(self);
|
|
labelNumber.Parent := pnlBevel;
|
|
labelNumber.AutoSize := False; // Avoids automatic changes to width + height
|
|
labelNumber.Left := xPosition;
|
|
labelNumber.Top := topPosition;
|
|
labelNumber.Width := 15;
|
|
labelNumber.Height := LINE_HEIGHT;
|
|
labelNumber.Alignment := taRightJustify;
|
|
labelNumber.Layout := tlCenter;
|
|
labelNumber.Caption := IntToStr(i+1) + '.';
|
|
labelNumber.Tag := i+1;
|
|
Inc( xPosition, labelNumber.Width + MARGIN );
|
|
|
|
// 2. Dropdown with columnnames
|
|
dropdownCols := TComboBox.Create(self);
|
|
dropdownCols.Parent := pnlBevel;
|
|
dropdownCols.Width := 120;
|
|
dropdownCols.Height := LINE_HEIGHT;
|
|
dropdownCols.Left := xPosition;
|
|
dropdownCols.Top := topPosition;
|
|
dropdownCols.Items := ColumnNames;
|
|
dropdownCols.Style := csDropDownList; // Not editable
|
|
dropdownCols.ItemIndex := ColumnNames.IndexOf(OrderColumns[i].ColumnName);
|
|
dropdownCols.Tag := i+1;
|
|
dropdownCols.OnChange := dropdownColsChange;
|
|
Inc( xPosition, dropdownCols.Width + MARGIN );
|
|
|
|
// 3. A button for selecting ASC/DESC
|
|
buttonOrder := TSpeedButton.Create(self);
|
|
buttonOrder.Parent := pnlBevel;
|
|
buttonOrder.Width := 35;
|
|
buttonOrder.Height := LINE_HEIGHT;
|
|
buttonOrder.Left := xPosition;
|
|
buttonOrder.Top := topPosition;
|
|
buttonOrder.AllowAllUp := True; // Enables Down = False
|
|
buttonOrder.GroupIndex := i+1; // if > 0 enables Down = True
|
|
buttonOrder.Caption := TXT_ASC;
|
|
if OrderColumns[i].SortDirection = ORDER_DESC then
|
|
begin
|
|
buttonOrder.Caption := TXT_DESC;
|
|
buttonOrder.Down := True;
|
|
end;
|
|
buttonOrder.Hint := 'Toggle the sort direction for this column.';
|
|
buttonOrder.Tag := i+1;
|
|
buttonOrder.OnClick := buttonOrderClick;
|
|
Inc( xPosition, buttonOrder.Width + MARGIN );
|
|
|
|
// 4. Button for deleting
|
|
buttonDelete := TButton.Create(self);
|
|
buttonDelete.Parent := pnlBevel;
|
|
buttonDelete.Width := 20;
|
|
buttonDelete.Height := LINE_HEIGHT;
|
|
buttonDelete.Left := xPosition;
|
|
buttonDelete.Top := topPosition;
|
|
buttonDelete.Caption := 'X';
|
|
buttonDelete.Hint := 'Drops sorting by this column.';
|
|
buttonDelete.Tag := i+1;
|
|
buttonDelete.OnClick := buttonDeleteClick;
|
|
Inc( xPosition, buttonDelete.Width + MARGIN );
|
|
|
|
end;
|
|
|
|
// Auto-adjust size of form
|
|
Height := (pnlBevel.BorderWidth * 2) + // Top + Bottom border
|
|
(MARGIN_BIG * 2) + // Separator spaces
|
|
(Length(OrderColumns) * (LINE_HEIGHT + MARGIN)) + // Height of created controls
|
|
(btnOK.Height + MARGIN); // Height of buttons
|
|
Width := xPosition + pnlBevel.BorderWidth;
|
|
|
|
// Auto-adjust width and position of main buttons at bottom
|
|
btnWidth := (pnlBevel.Width -pnlBevel.BorderWidth*2 - MARGIN) DIV 3 - MARGIN;
|
|
btnOK.Width := btnWidth;
|
|
btnOK.Top := Height - pnlBevel.BorderWidth - MARGIN - btnOK.Height;
|
|
btnOK.Left := pnlBevel.BorderWidth + MARGIN;
|
|
btnCancel.Width := btnWidth;
|
|
btnCancel.Left := btnOK.Left + btnWidth + MARGIN;
|
|
btnAddCol.Width := btnWidth;
|
|
btnAddCol.Left := btnCancel.Left + btnWidth + MARGIN;
|
|
end;
|
|
|
|
|
|
{**
|
|
Dropdown for column selection was changed
|
|
}
|
|
procedure TDataSortingForm.dropdownColsChange( Sender: TObject );
|
|
var
|
|
combo : TComboBox;
|
|
begin
|
|
combo := Sender as TComboBox;
|
|
OrderColumns[combo.Tag-1].ColumnName := combo.Text;
|
|
|
|
// Enables OK button
|
|
Modified;
|
|
end;
|
|
|
|
|
|
{**
|
|
Button for selecting sort-direction was clicked
|
|
}
|
|
procedure TDataSortingForm.buttonOrderClick( Sender: TObject );
|
|
var
|
|
btn : TSpeedButton;
|
|
begin
|
|
btn := Sender as TSpeedButton;
|
|
if btn.Down then
|
|
begin
|
|
btn.Caption := TXT_DESC;
|
|
OrderColumns[btn.Tag-1].SortDirection := ORDER_DESC;
|
|
end
|
|
else
|
|
begin
|
|
btn.Caption := TXT_ASC;
|
|
OrderColumns[btn.Tag-1].SortDirection := ORDER_ASC;
|
|
end;
|
|
|
|
// Enables OK button
|
|
Modified;
|
|
end;
|
|
|
|
|
|
{**
|
|
Delete order column
|
|
}
|
|
procedure TDataSortingForm.buttonDeleteClick( Sender: TObject );
|
|
var
|
|
btn : TButton;
|
|
i : Integer;
|
|
begin
|
|
btn := Sender as TButton;
|
|
|
|
if Length(OrderColumns)>1 then
|
|
begin
|
|
// Move remaining items one up
|
|
for i := btn.Tag-1 to Length(OrderColumns) - 2 do
|
|
begin
|
|
OrderColumns[i] := OrderColumns[i+1];
|
|
end;
|
|
end;
|
|
// Delete last item
|
|
SetLength(OrderColumns, Length(OrderColumns)-1);
|
|
|
|
// Refresh controls
|
|
DisplaySortingControls;
|
|
|
|
// Enables OK button
|
|
Modified;
|
|
end;
|
|
|
|
|
|
{**
|
|
Add a new order column
|
|
}
|
|
procedure TDataSortingForm.btnAddColClick(Sender: TObject);
|
|
var
|
|
i, new : Integer;
|
|
UnusedColumns : TStringList;
|
|
begin
|
|
SetLength( OrderColumns, Length(OrderColumns)+1 );
|
|
new := Length(OrderColumns)-1;
|
|
|
|
// Take first unused column as default for new sort column
|
|
UnusedColumns := TStringList.Create;
|
|
UnusedColumns.AddStrings( ColumnNames );
|
|
for i := 0 to Length(OrderColumns) - 1 do
|
|
begin
|
|
if UnusedColumns.IndexOf(OrderColumns[i].ColumnName) > -1 then
|
|
begin
|
|
UnusedColumns.Delete( UnusedColumns.IndexOf(OrderColumns[i].ColumnName) );
|
|
end;
|
|
end;
|
|
if UnusedColumns.Count > 0 then
|
|
OrderColumns[new].ColumnName := UnusedColumns[0]
|
|
else
|
|
OrderColumns[new].ColumnName := ColumnNames[0];
|
|
|
|
// Sort ASC by default
|
|
OrderColumns[new].SortDirection := ORDER_ASC;
|
|
|
|
// Refresh controls
|
|
DisplaySortingControls;
|
|
|
|
// Enables OK button
|
|
Modified;
|
|
end;
|
|
|
|
|
|
{**
|
|
Gets called when any option has changed. Enables the OK button.
|
|
}
|
|
procedure TDataSortingForm.Modified;
|
|
begin
|
|
btnOk.Enabled := True;
|
|
end;
|
|
|
|
|
|
{**
|
|
OK clicked
|
|
}
|
|
procedure TDataSortingForm.btnOKClick(Sender: TObject);
|
|
var
|
|
reg : TRegistry;
|
|
reg_name, reg_value, sort : String;
|
|
i : Integer;
|
|
begin
|
|
// Concat all sort options to a ORDER clause
|
|
reg_value := '';
|
|
for i := 0 to Length(OrderColumns) - 1 do
|
|
begin
|
|
if reg_value <> '' then
|
|
reg_value := reg_value + ', ';
|
|
if OrderColumns[i].SortDirection = ORDER_ASC then
|
|
sort := TXT_ASC
|
|
else
|
|
sort := TXT_DESC;
|
|
reg_value := reg_value + Mainform.Mask( OrderColumns[i].ColumnName ) + ' ' + sort;
|
|
end;
|
|
|
|
// Write ORDER clause to registry
|
|
reg := TRegistry.Create();
|
|
reg.OpenKey( REGPATH + '\Servers\' + Mainform.Childwin.Description, true );
|
|
reg_name := 'ORDERCLAUSE_' + Mainform.Childwin.ActualDatabase + '.' + Mainform.Childwin.ActualTable;
|
|
reg.WriteString( reg_name, reg_value );
|
|
reg.CloseKey;
|
|
|
|
// Refresh data
|
|
Mainform.Childwin.viewdata(self);
|
|
end;
|
|
|
|
|
|
end.
|