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

* Don't try to access a passed tree if it has been destroyed by some earlier event. * Don't try to access registry in DoDisconnect after key has been closed. * Now that DoDisconnect lives in FormDestroy it is save to call it slightly earlier, before registry has been closed. There should be no later paint events which will trigger random database queries.
356 lines
9.4 KiB
ObjectPascal
356 lines
9.4 KiB
ObjectPascal
unit data_sorting;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, SysUtils, Classes, Controls, Forms, StdCtrls, ExtCtrls, ComCtrls, Buttons,
|
|
Contnrs,
|
|
helpers;
|
|
|
|
|
|
type
|
|
TDataSortingForm = class(TForm)
|
|
pnlBevel: TPanel;
|
|
btnOK: TButton;
|
|
btnCancel: TButton;
|
|
btnAddCol: TButton;
|
|
btnReset: TButton;
|
|
procedure btnAddColClick(Sender: TObject);
|
|
procedure btnCancelClick(Sender: TObject);
|
|
procedure btnOKClick(Sender: TObject);
|
|
procedure FormClose(Sender: TObject; var Action: TCloseAction);
|
|
procedure FormDeactivate(Sender: TObject);
|
|
procedure FormShow(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure btnResetClick(Sender: TObject);
|
|
private
|
|
{ Private declarations }
|
|
ColumnNames : TStringList;
|
|
OrderColumns : TOrderColArray;
|
|
OldOrderClause : String;
|
|
procedure DisplaySortingControls;
|
|
procedure dropdownColsChange( Sender: TObject );
|
|
procedure buttonOrderClick( Sender: TObject );
|
|
procedure buttonDeleteClick( Sender: TObject );
|
|
procedure Modified;
|
|
public
|
|
{ Public declarations }
|
|
end;
|
|
|
|
|
|
const
|
|
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}
|
|
|
|
|
|
procedure TDataSortingForm.FormCreate(Sender: TObject);
|
|
begin
|
|
InheritFont(Font);
|
|
ColumnNames := TStringList.Create;
|
|
end;
|
|
|
|
|
|
{**
|
|
Initialization
|
|
}
|
|
procedure TDataSortingForm.FormShow(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
// Take column names from listColumns and add here
|
|
ColumnNames.Clear;
|
|
for i:=0 to Mainform.SelectedTableColumns.Count-1 do
|
|
ColumnNames.Add(Mainform.SelectedTableColumns[i].Name);
|
|
|
|
OrderColumns := Mainform.DataGridSortColumns;
|
|
OldOrderClause := ComposeOrderClause(OrderColumns);
|
|
|
|
// 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.Text := ColumnNames.Text;
|
|
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 + btnReset.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;
|
|
btnReset.Left := btnCancel.Left;
|
|
btnReset.Width := 2*btnWidth + MARGIN;
|
|
btnReset.Enabled := Mainform.actDataResetSorting.Enabled;
|
|
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;
|
|
OrderColumns[new] := TOrderCol.Create;
|
|
|
|
// 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 if ORDER options have changed
|
|
}
|
|
procedure TDataSortingForm.Modified;
|
|
begin
|
|
btnOk.Enabled := ComposeOrderClause(OrderColumns) <> OldOrderClause;
|
|
end;
|
|
|
|
|
|
{**
|
|
OK clicked: Write ORDER clause to registry
|
|
}
|
|
procedure TDataSortingForm.btnOKClick(Sender: TObject);
|
|
begin
|
|
// TODO: apply ordering
|
|
Mainform.DataGridSortColumns := OrderColumns;
|
|
InvalidateVT(Mainform.DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
|
|
btnCancel.OnClick(Sender);
|
|
end;
|
|
|
|
|
|
procedure TDataSortingForm.btnCancelClick(Sender: TObject);
|
|
begin
|
|
Mainform.tbtnDataSorting.Down := False;
|
|
Close;
|
|
end;
|
|
|
|
|
|
{**
|
|
Be sure the form is destroyed after closing.
|
|
}
|
|
procedure TDataSortingForm.FormClose(Sender: TObject; var Action: TCloseAction);
|
|
begin
|
|
Action := caFree;
|
|
end;
|
|
|
|
|
|
{**
|
|
Cancel this dialog if the user clicks elsewhere on mainform
|
|
}
|
|
procedure TDataSortingForm.FormDeactivate(Sender: TObject);
|
|
begin
|
|
btnCancel.OnClick(Sender);
|
|
end;
|
|
|
|
|
|
procedure TDataSortingForm.btnResetClick(Sender: TObject);
|
|
begin
|
|
Mainform.actDataResetSortingExecute(Sender);
|
|
btnCancel.OnClick(Sender);
|
|
end;
|
|
|
|
|
|
end.
|