mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-26 11:17:57 +08:00
Enable multi row selection in table editor's column list. Relevant functions adjusted:
* Add to index * Create index * Remove Column(s) (=> makes the "Clear columns" button superfluous)
This commit is contained in:
@ -2217,32 +2217,22 @@ end;
|
|||||||
}
|
}
|
||||||
function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList;
|
function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0; OnlyNodeType: TListNodeType = lntNone ): TWideStringList;
|
||||||
var
|
var
|
||||||
SelectedNodes : TNodeArray;
|
Node: PVirtualNode;
|
||||||
NodeData: PVTreeData;
|
NodeData: PVTreeData;
|
||||||
i: Integer;
|
|
||||||
a : TVTreeDataArray;
|
|
||||||
begin
|
begin
|
||||||
Result := TWideStringList.Create;
|
Result := TWideStringList.Create;
|
||||||
if OnlySelected then
|
if OnlySelected then Node := VT.GetFirstSelected
|
||||||
begin
|
else Node := VT.GetFirst;
|
||||||
// Fetch only selected nodes
|
while Assigned(Node) do begin
|
||||||
SelectedNodes := VT.GetSortedSelection(False);
|
if OnlyNodeType = lntNone then // Add all nodes, regardless of their types
|
||||||
for i := 0 to Length(SelectedNodes) - 1 do
|
Result.Add( VT.Text[Node, Column] )
|
||||||
begin
|
else begin
|
||||||
NodeData := VT.GetNodeData( SelectedNodes[i] );
|
NodeData := VT.GetNodeData(Node);
|
||||||
if (OnlyNodeType = lntNone) // Add all nodes, regardless of their types
|
if (NodeData.NodeType = OnlyNodeType) then // Node in loop is of specified type
|
||||||
or (NodeData.NodeType = OnlyNodeType) then // Node in loop is of specified type
|
Result.Add(NodeData.Captions[Column]);
|
||||||
Result.Add( NodeData.Captions[Column] );
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// Fetch all nodes
|
|
||||||
a := Mainform.GetVTreeDataArray( VT )^;
|
|
||||||
for i := 0 to High(a) do begin
|
|
||||||
if (OnlyNodeType = lntNone)
|
|
||||||
or (a[i].NodeType = OnlyNodeType) then
|
|
||||||
Result.Add( a[i].Captions[ Column ] );
|
|
||||||
end;
|
end;
|
||||||
|
if OnlySelected then Node := VT.GetNextSelected(Node)
|
||||||
|
else Node := VT.GetNext(Node);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -80,8 +80,8 @@ object frmTableEditor: TfrmTableEditor
|
|||||||
PopupMenu = popupColumns
|
PopupMenu = popupColumns
|
||||||
TabOrder = 2
|
TabOrder = 2
|
||||||
TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toEditable, toFullRepaintOnResize, toGridExtensions, toInitOnSave, toToggleOnDblClick, toWheelPanning, toFullRowDrag, toEditOnClick]
|
TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toEditable, toFullRepaintOnResize, toGridExtensions, toInitOnSave, toToggleOnDblClick, toWheelPanning, toFullRowDrag, toEditOnClick]
|
||||||
TreeOptions.PaintOptions = [toHideFocusRect, toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed]
|
TreeOptions.PaintOptions = [toHotTrack, toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages, toUseExplorerTheme, toHideTreeLinesIfThemed]
|
||||||
TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toRightClickSelect]
|
TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toMultiSelect, toRightClickSelect]
|
||||||
WantTabs = True
|
WantTabs = True
|
||||||
OnAfterCellPaint = listColumnsAfterCellPaint
|
OnAfterCellPaint = listColumnsAfterCellPaint
|
||||||
OnBeforeCellPaint = listColumnsBeforeCellPaint
|
OnBeforeCellPaint = listColumnsBeforeCellPaint
|
||||||
@ -606,16 +606,8 @@ object frmTableEditor: TfrmTableEditor
|
|||||||
ImageIndex = 46
|
ImageIndex = 46
|
||||||
OnClick = btnRemoveColumnClick
|
OnClick = btnRemoveColumnClick
|
||||||
end
|
end
|
||||||
object btnClearColumns: TToolButton
|
|
||||||
Left = 132
|
|
||||||
Top = 0
|
|
||||||
Hint = 'Remove all columns'
|
|
||||||
Caption = 'Clear'
|
|
||||||
ImageIndex = 26
|
|
||||||
OnClick = btnClearColumnsClick
|
|
||||||
end
|
|
||||||
object btnMoveUpColumn: TToolButton
|
object btnMoveUpColumn: TToolButton
|
||||||
Left = 198
|
Left = 132
|
||||||
Top = 0
|
Top = 0
|
||||||
Hint = 'Move up'
|
Hint = 'Move up'
|
||||||
Caption = 'Up'
|
Caption = 'Up'
|
||||||
@ -623,7 +615,7 @@ object frmTableEditor: TfrmTableEditor
|
|||||||
OnClick = btnMoveUpColumnClick
|
OnClick = btnMoveUpColumnClick
|
||||||
end
|
end
|
||||||
object btnMoveDownColumn: TToolButton
|
object btnMoveDownColumn: TToolButton
|
||||||
Left = 264
|
Left = 198
|
||||||
Top = 0
|
Top = 0
|
||||||
Hint = 'Move down'
|
Hint = 'Move down'
|
||||||
Caption = 'Down'
|
Caption = 'Down'
|
||||||
@ -690,12 +682,6 @@ object frmTableEditor: TfrmTableEditor
|
|||||||
ShortCut = 16430
|
ShortCut = 16430
|
||||||
OnClick = btnRemoveColumnClick
|
OnClick = btnRemoveColumnClick
|
||||||
end
|
end
|
||||||
object menuClearColumns: TMenuItem
|
|
||||||
Caption = 'Clear all columns'
|
|
||||||
ImageIndex = 26
|
|
||||||
ShortCut = 24622
|
|
||||||
OnClick = btnClearColumnsClick
|
|
||||||
end
|
|
||||||
object menuMoveUpColumn: TMenuItem
|
object menuMoveUpColumn: TMenuItem
|
||||||
Caption = 'Move up'
|
Caption = 'Move up'
|
||||||
ImageIndex = 74
|
ImageIndex = 74
|
||||||
|
@ -50,7 +50,6 @@ type
|
|||||||
tlbColumns: TToolBar;
|
tlbColumns: TToolBar;
|
||||||
btnAddColumn: TToolButton;
|
btnAddColumn: TToolButton;
|
||||||
btnRemoveColumn: TToolButton;
|
btnRemoveColumn: TToolButton;
|
||||||
btnClearColumns: TToolButton;
|
|
||||||
btnMoveUpColumn: TToolButton;
|
btnMoveUpColumn: TToolButton;
|
||||||
btnMoveDownColumn: TToolButton;
|
btnMoveDownColumn: TToolButton;
|
||||||
SplitterTopBottom: TSplitter;
|
SplitterTopBottom: TSplitter;
|
||||||
@ -68,7 +67,6 @@ type
|
|||||||
popupColumns: TPopupMenu;
|
popupColumns: TPopupMenu;
|
||||||
menuAddColumn: TMenuItem;
|
menuAddColumn: TMenuItem;
|
||||||
menuRemoveColumn: TMenuItem;
|
menuRemoveColumn: TMenuItem;
|
||||||
menuClearColumns: TMenuItem;
|
|
||||||
menuMoveUpColumn: TMenuItem;
|
menuMoveUpColumn: TMenuItem;
|
||||||
menuMoveDownColumn: TMenuItem;
|
menuMoveDownColumn: TMenuItem;
|
||||||
chkCharsetConvert: TCheckBox;
|
chkCharsetConvert: TCheckBox;
|
||||||
@ -79,7 +77,6 @@ type
|
|||||||
procedure Modification(Sender: TObject);
|
procedure Modification(Sender: TObject);
|
||||||
procedure btnAddColumnClick(Sender: TObject);
|
procedure btnAddColumnClick(Sender: TObject);
|
||||||
procedure btnRemoveColumnClick(Sender: TObject);
|
procedure btnRemoveColumnClick(Sender: TObject);
|
||||||
procedure btnClearColumnsClick(Sender: TObject);
|
|
||||||
procedure listColumnsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
|
procedure listColumnsBeforePaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas);
|
||||||
procedure listColumnsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
procedure listColumnsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
|
||||||
procedure btnHelpClick(Sender: TObject);
|
procedure btnHelpClick(Sender: TObject);
|
||||||
@ -253,7 +250,7 @@ begin
|
|||||||
comboCollation.Items.Clear;
|
comboCollation.Items.Clear;
|
||||||
Mainform.GetCollations(comboCollation.Items);
|
Mainform.GetCollations(comboCollation.Items);
|
||||||
FAlterTableName := AlterTableName;
|
FAlterTableName := AlterTableName;
|
||||||
btnClearColumnsClick(Self);
|
Columns.Clear;
|
||||||
btnClearIndexesClick(Self);
|
btnClearIndexesClick(Self);
|
||||||
tabALTERcode.TabVisible := FAlterTableName <> '';
|
tabALTERcode.TabVisible := FAlterTableName <> '';
|
||||||
|
|
||||||
@ -833,37 +830,29 @@ end;
|
|||||||
|
|
||||||
procedure TfrmTableEditor.btnRemoveColumnClick(Sender: TObject);
|
procedure TfrmTableEditor.btnRemoveColumnClick(Sender: TObject);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, FocusIndex: Integer;
|
||||||
n: PVirtualNode;
|
SelCols: TWideStringList;
|
||||||
begin
|
begin
|
||||||
// Remove selected column
|
// Remove selected column(s)
|
||||||
n := listColumns.FocusedNode;
|
SelCols := GetVTCaptions(listColumns, true, 1);
|
||||||
|
// Remember focused node index
|
||||||
|
if Assigned(listColumns.FocusedNode) then
|
||||||
|
FocusIndex := listColumns.FocusedNode.Index
|
||||||
|
else
|
||||||
|
FocusIndex := listColumns.GetFirstSelected.Index;
|
||||||
|
|
||||||
|
// Set empty value for name=val column name pairs
|
||||||
for i:=0 to ColumnNames.Count-1 do begin
|
for i:=0 to ColumnNames.Count-1 do begin
|
||||||
if ColumnNames.ValueFromIndex[i] = Columns[n.Index] then begin
|
if SelCols.IndexOf(ColumnNames.ValueFromIndex[i]) > -1 then begin
|
||||||
ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator;
|
ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator;
|
||||||
break;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Columns.Delete(n.Index);
|
for i:=0 to SelCols.Count-1 do begin
|
||||||
if (not Assigned(n)) and (Columns.Count > 0) then
|
Columns.Delete(Columns.IndexOf(SelCols[i]));
|
||||||
SelectNode(listColumns, Columns.Count-1);
|
end;
|
||||||
end;
|
if Columns.Count > 0 then
|
||||||
|
SelectNode(listColumns, Min(FocusIndex, Columns.Count-1));
|
||||||
|
ValidateColumnControls;
|
||||||
procedure TfrmTableEditor.btnClearColumnsClick(Sender: TObject);
|
|
||||||
var i: Integer;
|
|
||||||
begin
|
|
||||||
// Set empty values in changelist
|
|
||||||
for i:=0 to ColumnNames.Count - 1 do
|
|
||||||
ColumnNames[i] := ColumnNames.Names[i] + ColumnNames.NameValueSeparator;
|
|
||||||
// Column data gets freed below - end any editor which could cause AV's
|
|
||||||
if listColumns.IsEditing then
|
|
||||||
listColumns.CancelEditNode;
|
|
||||||
// I suspect Columns.Clear to be silly enough and leave its objects in memory,
|
|
||||||
// so we'll free them explicitely
|
|
||||||
for i := 0 to Columns.Count - 1 do
|
|
||||||
Columns.Objects[i].Free;
|
|
||||||
Columns.Clear;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -965,13 +954,11 @@ procedure TfrmTableEditor.ValidateColumnControls;
|
|||||||
var Node: PVirtualNode;
|
var Node: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
Node := listColumns.FocusedNode;
|
Node := listColumns.FocusedNode;
|
||||||
btnRemoveColumn.Enabled := Assigned(Node);
|
btnRemoveColumn.Enabled := listColumns.SelectedCount > 0;
|
||||||
btnClearColumns.Enabled := Columns.Count > 0;
|
|
||||||
btnMoveUpColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetFirst);
|
btnMoveUpColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetFirst);
|
||||||
btnMoveDownColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetLast);
|
btnMoveDownColumn.Enabled := Assigned(Node) and (Node <> listColumns.GetLast);
|
||||||
|
|
||||||
menuRemoveColumn.Enabled := btnRemoveColumn.Enabled;
|
menuRemoveColumn.Enabled := btnRemoveColumn.Enabled;
|
||||||
menuClearColumns.Enabled := btnClearColumns.Enabled;
|
|
||||||
menuMoveUpColumn.Enabled := btnMoveUpColumn.Enabled;
|
menuMoveUpColumn.Enabled := btnMoveUpColumn.Enabled;
|
||||||
menuMoveDownColumn.Enabled := btnMoveDownColumn.Enabled;
|
menuMoveDownColumn.Enabled := btnMoveDownColumn.Enabled;
|
||||||
end;
|
end;
|
||||||
@ -1208,8 +1195,8 @@ begin
|
|||||||
if Node.Index = idx then begin
|
if Node.Index = idx then begin
|
||||||
VT.FocusedNode := Node;
|
VT.FocusedNode := Node;
|
||||||
VT.Selected[Node] := True;
|
VT.Selected[Node] := True;
|
||||||
break;
|
end else
|
||||||
end;
|
VT.Selected[Node] := False;
|
||||||
Node := VT.GetNextSibling(Node);
|
Node := VT.GetNextSibling(Node);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1689,15 +1676,16 @@ var
|
|||||||
IndexName, IndexType: WideString;
|
IndexName, IndexType: WideString;
|
||||||
Item: TMenuItem;
|
Item: TMenuItem;
|
||||||
PrimaryKeyExists,
|
PrimaryKeyExists,
|
||||||
ColumnFocused: Boolean;
|
ColumnsSelected: Boolean;
|
||||||
IndexParts: TWideStringList;
|
IndexParts: TWideStringList;
|
||||||
|
Node: PVirtualNode;
|
||||||
begin
|
begin
|
||||||
ColumnFocused := Assigned(ListColumns.FocusedNode);
|
ColumnsSelected := ListColumns.SelectedCount > 0;
|
||||||
menuAddToIndex.Clear;
|
menuAddToIndex.Clear;
|
||||||
menuCreateIndex.Clear;
|
menuCreateIndex.Clear;
|
||||||
menuAddToIndex.Enabled := ColumnFocused;
|
menuAddToIndex.Enabled := ColumnsSelected;
|
||||||
menuCreateIndex.Enabled := ColumnFocused;
|
menuCreateIndex.Enabled := ColumnsSelected;
|
||||||
if not ColumnFocused then
|
if not ColumnsSelected then
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
// Auto create submenu items for "Add to index" ...
|
// Auto create submenu items for "Add to index" ...
|
||||||
@ -1709,9 +1697,18 @@ begin
|
|||||||
else
|
else
|
||||||
IndexName := IndexName + ' ('+IndexType+')';
|
IndexName := IndexName + ' ('+IndexType+')';
|
||||||
Item := AddItem(menuAddToIndex, IndexName, GetIndexIcon(i));
|
Item := AddItem(menuAddToIndex, IndexName, GetIndexIcon(i));
|
||||||
// Disable menuitem if column is already part of index
|
// Disable menuitem if all selected columns are already part of this index,
|
||||||
|
// enable it if one or more selected columns are not.
|
||||||
|
Item.Enabled := False;
|
||||||
IndexParts := TWideStringList(Indexes.Objects[i]);
|
IndexParts := TWideStringList(Indexes.Objects[i]);
|
||||||
Item.Enabled := IndexParts.IndexOf(Columns[ListColumns.FocusedNode.Index]) = -1;
|
Node := listColumns.GetFirstSelected;
|
||||||
|
while Assigned(Node) do begin
|
||||||
|
if IndexParts.IndexOf(Columns[Node.Index]) = -1 then begin
|
||||||
|
Item.Enabled := True;
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
Node := listColumns.GetNextSelected(Node);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
menuAddToIndex.Enabled := menuAddToIndex.Count > 0;
|
menuAddToIndex.Enabled := menuAddToIndex.Count > 0;
|
||||||
|
|
||||||
@ -1730,40 +1727,41 @@ var
|
|||||||
Item: TMenuItem;
|
Item: TMenuItem;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
IndexName, IndexType,
|
IndexName, IndexType,
|
||||||
NewName, NewType, NewPart: WideString;
|
NewName, NewType: WideString;
|
||||||
IndexParts: TWideStringlist;
|
IndexParts, NewParts: TWideStringlist;
|
||||||
begin
|
begin
|
||||||
// Auto create index or add column to existing one by rightclicking a column
|
// Auto create index or add columns to existing one by rightclicking a column
|
||||||
Item := (Sender as TMenuItem);
|
Item := (Sender as TMenuItem);
|
||||||
NewPart := Columns[ListColumns.FocusedNode.Index];
|
NewParts := GetVTCaptions(listColumns, True, 1);
|
||||||
if Item.Parent = menuCreateIndex then begin
|
if Item.Parent = menuCreateIndex then begin
|
||||||
NewName := 'Index '+IntToStr(Indexes.Count+1);
|
NewName := 'Index '+IntToStr(Indexes.Count+1);
|
||||||
// Remove auto hotkeys
|
// Remove auto hotkeys
|
||||||
NewType := StringReplace(Item.Caption, '&', '', [rfReplaceAll]);
|
NewType := StringReplace(Item.Caption, '&', '', [rfReplaceAll]);
|
||||||
// Avoid creating a second key with the same column
|
// Avoid creating a second key with the same columns
|
||||||
for i:=0 to Indexes.Count-1 do begin
|
for i:=0 to Indexes.Count-1 do begin
|
||||||
IndexParts := TWideStringList(Indexes.Objects[i]);
|
IndexParts := TWideStringList(Indexes.Objects[i]);
|
||||||
GetIndexInfo(i, IndexName, IndexType);
|
GetIndexInfo(i, IndexName, IndexType);
|
||||||
if (IndexType = NewType) and (IndexParts.Count = 1) and (IndexParts[0] = NewPart) then begin
|
if (IndexType = NewType) and (IndexParts.Text = NewParts.Text) then begin
|
||||||
if MessageDlg('Key already exists. Really create a second identical key? This will slow down queries on this table.',
|
if MessageDlg('Key already exists. Really create another identical one?'+CRLF+CRLF+
|
||||||
|
'This will increase disk usage and probably slow down queries on this table.',
|
||||||
mtConfirmation, [mbYes, mbNo], 0) = mrNo then
|
mtConfirmation, [mbYes, mbNo], 0) = mrNo then
|
||||||
Exit;
|
Exit;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
IndexParts := TWideStringlist.Create;
|
NewParts.OnChange := IndexesChange;
|
||||||
IndexParts.OnChange := IndexesChange;
|
Indexes.AddObject(NewName+REGDELIM+NewType, NewParts);
|
||||||
// TODO: Enable multiselection in ListColumns so one can create a multicolumn key in two clicks
|
|
||||||
IndexParts.Add(NewPart);
|
|
||||||
Indexes.AddObject(NewName+REGDELIM+NewType, IndexParts);
|
|
||||||
PageControlMain.ActivePage := tabIndexes;
|
PageControlMain.ActivePage := tabIndexes;
|
||||||
treeIndexes.Repaint;
|
treeIndexes.Repaint;
|
||||||
SelectNode(treeIndexes, Indexes.Count-1);
|
SelectNode(treeIndexes, Indexes.Count-1);
|
||||||
SelectNode(treeIndexes, 0, treeIndexes.FocusedNode);
|
SelectNode(treeIndexes, 0, treeIndexes.FocusedNode);
|
||||||
end else begin
|
end else begin
|
||||||
IndexParts := TWideStringlist(Indexes.Objects[Item.MenuIndex]);
|
|
||||||
PageControlMain.ActivePage := tabIndexes;
|
PageControlMain.ActivePage := tabIndexes;
|
||||||
IndexParts.Add(NewPart);
|
IndexParts := TWideStringlist(Indexes.Objects[Item.MenuIndex]);
|
||||||
|
for i:=0 to NewParts.Count-1 do begin
|
||||||
|
if IndexParts.IndexOf(NewParts[i]) = -1 then
|
||||||
|
IndexParts.Add(NewParts[i]);
|
||||||
|
end;
|
||||||
SelectNode(treeIndexes, Item.MenuIndex);
|
SelectNode(treeIndexes, Item.MenuIndex);
|
||||||
treeIndexes.ReinitChildren(treeIndexes.FocusedNode, False);
|
treeIndexes.ReinitChildren(treeIndexes.FocusedNode, False);
|
||||||
SelectNode(treeIndexes, IndexParts.Count-1, treeIndexes.FocusedNode);
|
SelectNode(treeIndexes, IndexParts.Count-1, treeIndexes.FocusedNode);
|
||||||
|
Reference in New Issue
Block a user