Switch ListColumns from TSortListView to TVirtualStringTree

Additionally/Sideeffects:
- Fix vstFreeNode to delete the item from the array, not only free the item itself
- Change/Rename GetSelectedNodesFromVT to GetVTCaptions and give it the ability to return all captions, not only the selected. This function is very useful now and saves writing much redundant code.

A table with 500 columns needed 3 seconds to display in the TSortListView, now that takes less than a half second.
This commit is contained in:
Ansgar Becker
2007-08-27 00:01:53 +00:00
parent 1fa1837ec8
commit 3f0b70c409
10 changed files with 233 additions and 185 deletions

View File

@ -641,49 +641,70 @@ object MDIChild: TMDIChild
end
end
end
object ListColumns: TSortListView
Tag = -1
object ListColumns: TVirtualStringTree
Left = 28
Top = 17
Width = 468
Height = 203
Align = alClient
EditDelay = 500
Header.AutoSizeIndex = 0
Header.Font.Charset = DEFAULT_CHARSET
Header.Font.Color = clWindowText
Header.Font.Height = -11
Header.Font.Name = 'Tahoma'
Header.Font.Style = []
Header.Height = 20
Header.Options = [hoAutoResize, hoColumnResize, hoDblClickResize, hoHotTrack, hoShowSortGlyphs, hoVisible]
Images = MainForm.ImageList1
IncrementalSearch = isInitializedOnly
PopupMenu = popupTableGrid
TabOrder = 2
TreeOptions.MiscOptions = [toAcceptOLEDrop, toEditable, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning]
TreeOptions.PaintOptions = [toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages]
TreeOptions.SelectionOptions = [toFullRowSelect, toMultiSelect, toRightClickSelect]
OnChange = ListColumnsChange
OnCompareNodes = vstCompareNodes
OnDblClick = UpdateField
OnFreeNode = vstFreeNode
OnGetText = vstGetText
OnGetImageIndex = vstGetImageIndex
OnGetNodeDataSize = vstGetNodeDataSize
OnHeaderClick = vstHeaderClick
OnInitNode = vstInitNode
OnKeyUp = controlsKeyUp
OnNewText = ListColumnsNewText
Columns = <
item
Caption = 'Name'
Width = -1
WidthType = (
-1)
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
Position = 0
Width = 94
WideText = 'Name'
end
item
Caption = 'Type'
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
Position = 1
Width = 100
WideText = 'Type'
end
item
Caption = 'Null'
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
Position = 2
Width = 40
WideText = 'Null'
end
item
Caption = 'Default'
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
Position = 3
Width = 115
WideText = 'Default'
end
item
Caption = 'Extra'
Width = 200
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
Position = 4
Width = 100
WideText = 'Extra'
end>
GridLines = True
MultiSelect = True
RowSelect = True
PopupMenu = popupTableGrid
SmallImages = MainForm.ImageList1
TabOrder = 2
ViewStyle = vsReport
OnDblClick = UpdateField
OnEdited = ListColumnsEdited
OnKeyUp = controlsKeyUp
OnSelectItem = ListColumnsSelectItem
ImageIndexSortAsc = 0
ImageIndexSortDesc = 0
end
end
object tabData: TTabSheet

View File

@ -110,7 +110,7 @@ type
PopupMenuDropTable: TMenuItem;
N17: TMenuItem;
pnlTableToolbar: TPanel;
ListColumns: TSortListView;
ListColumns: TVirtualStringTree;
CopycontentsasHTML1: TMenuItem;
CopycontentsasHTML2: TMenuItem;
Copy3: TMenuItem;
@ -307,8 +307,8 @@ type
tlbTableLeft2: TToolBar;
btnTableInsertRecord: TToolButton;
procedure menuRenameColumnClick(Sender: TObject);
procedure ListColumnsEdited(Sender: TObject; Item: TListItem;
var S: string);
procedure ListColumnsNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; NewText: WideString);
procedure menuclearClick(Sender: TObject);
procedure popupQueryPopup(Sender: TObject);
procedure lboxQueryHelpersClick(Sender: TObject);
@ -321,8 +321,7 @@ type
procedure DBtreeExpanding(Sender: TObject; Node: TTreeNode;
var AllowExpansion: Boolean);
procedure ListTablesClick(Sender: TObject);
procedure ListColumnsSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
procedure ListColumnsChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure DBMemo1Exit(Sender: TObject);
procedure btnUnsafeEditClick(Sender: TObject);
procedure gridMouseDown(Sender: TObject; Button: TMouseButton;
@ -545,7 +544,8 @@ type
VTRowDataListVariables,
VTRowDataListProcesses,
VTRowDataListCommandStats,
VTRowDataListTables : Array of TVTreeData;
VTRowDataListTables,
VTRowDataListColumns : TVTreeDataArray;
FProgressForm : TFrmQueryProgress;
procedure Init(AConn : POpenConnProf; AMysqlConn : TMysqlConn);
@ -1280,8 +1280,6 @@ begin
tabTable.TabVisible := false;
tabData.TabVisible := false;
ListTables.Clear;
ListColumns.Items.Clear();
pnlTableTop.Caption := 'Table-Properties';
Caption := Description + ' - /' + ActualDatabase;
ActualDatabase := db;
@ -1381,7 +1379,7 @@ var
DropDown : TStringList;
i : Integer;
j : Integer;
Columns : TStringList;
ValidColumns : TStringList;
PrimaryKeyColumns : TStringList;
reg : TRegistry;
reg_value : String;
@ -1473,20 +1471,12 @@ begin
begin
orderclauses := explode( ',', reg.ReadString( reg_value ) );
RewriteOrderClause := False;
ValidColumns := GetVTCaptions( ListColumns );
for i := 0 to ( orderclauses.Count - 1 ) do
begin
columnname := Trim( Copy( orderclauses[i], 0, LastPos( ' ', orderclauses[i] ) ) );
columnname := trimc( columnname, '`' );
columnexists := false;
for j := 0 to ( ListColumns.Items.Count - 1 ) do
begin
if ( ListColumns.Items[j].Caption = columnname ) then
begin
columnexists := true;
Break;
end;
end;
columnexists := ValidColumns.IndexOf(columnname) > -1;
if ( not columnexists ) then
begin
@ -1533,7 +1523,6 @@ begin
end;
MenuLimit.Checked := Mainform.CheckBoxLimit.Checked;
Columns := TStringList.Create();
PrimaryKeyColumns := TStringList.Create();
if ( ( ActualTable <> '' ) and ( ActualDatabase <> '' ) ) then
@ -1645,14 +1634,13 @@ begin
MainForm.ShowStatus( STATUS_MSG_READY, 2 );
for i := 0 to ( ListColumns.Items.Count - 1 ) do
for i := 0 to Length(VTRowDataListColumns) - 1 do
begin
Columns.Add( ListColumns.Items[i].Caption );
// give all enum-fields a PickList with its Items
if ( StrCmpBegin( 'enum', ListColumns.Items[i].SubItems[0]) ) then
if ( StrCmpBegin( 'enum', VTRowDataListColumns[i].Captions[1]) ) then
begin
DropDown := explode( ''',''', getEnumValues( ListColumns.Items[i].SubItems[0] ) );
DropDown := explode( ''',''', getEnumValues( VTRowDataListColumns[i].Captions[1] ) );
for j := 0 to ( DropDown.Count - 1 ) do
begin
DropDown[j] := trimc( DropDown[j], '''' );
@ -1660,7 +1648,7 @@ begin
for j := 0 to ( gridData.Columns.Count - 1 ) do
begin
if ( gridData.Columns[j].FieldName = ListColumns.Items[i].Caption ) then
if ( gridData.Columns[j].FieldName = VTRowDataListColumns[i].Captions[0] ) then
begin
gridData.Columns[j].PickList := DropDown;
end;
@ -1671,11 +1659,11 @@ begin
for j := 0 to ( gridData.Columns.Count - 1 ) do
begin
if (
( gridData.Columns[j].FieldName = ListColumns.Items[i].Caption ) and
( ListColumns.Items[i].ImageIndex = 26 )
( gridData.Columns[j].FieldName = VTRowDataListColumns[i].Captions[0] ) and
( VTRowDataListColumns[i].ImageIndex = 26 )
) then
begin
PrimaryKeyColumns.Add( ListColumns.Items[i].Caption );
PrimaryKeyColumns.Add( VTRowDataListColumns[i].Captions[0] );
end;
end;
end;
@ -2145,7 +2133,6 @@ end;
procedure TMDIChild.ShowTableProperties(Sender: TObject);
var
i,j : Integer;
n : TListItem;
tn, tndb : TTreeNode;
isFulltext : Boolean;
ds : TDataSet;
@ -2185,26 +2172,28 @@ begin
end;
MainForm.ShowStatus( 'Reading table properties...', 2, true );
ListColumns.Items.BeginUpdate;
ListColumns.Items.Clear;
ListColumns.BeginUpdate;
ListColumns.Clear;
Try
ds := GetResults( 'SHOW COLUMNS FROM ' + mask(ActualTable), false );
SetLength(VTRowDataListColumns, ds.RecordCount);
for i:=1 to ds.RecordCount do
begin
n := ListColumns.Items.Add;
n.ImageIndex := ICONINDEX_FIELD;
n.Caption := ds.FieldByName('Field').AsString;
n.Subitems.Add( ds.FieldByName('Type').AsString );
VTRowDataListColumns[i-1].ImageIndex := ICONINDEX_FIELD;
VTRowDataListColumns[i-1].Captions := TStringList.Create;
VTRowDataListColumns[i-1].Captions.Add( ds.FieldByName('Field').AsString );
VTRowDataListColumns[i-1].Captions.Add( ds.FieldByName('Type').AsString );
if lowercase( ds.FieldByName('Null').AsString ) = 'yes' then
n.Subitems.Add('Yes')
else n.Subitems.Add('No');
n.Subitems.Add( ds.FieldByName('Default').AsString );
n.Subitems.Add( ds.FieldByName('Extra').AsString );
VTRowDataListColumns[i-1].Captions.Add('Yes')
else VTRowDataListColumns[i-1].Captions.Add('No');
VTRowDataListColumns[i-1].Captions.Add( ds.FieldByName('Default').AsString );
VTRowDataListColumns[i-1].Captions.Add( ds.FieldByName('Extra').AsString );
ds.Next;
end;
ListColumns.RootNodeCount := Length(VTRowDataListColumns);
// Manually invoke OnChange event of tabset to fill helper list with data
if tabsetQueryHelpers.TabIndex = 0 then
tabsetQueryHelpers.OnChange( Sender, tabsetQueryHelpers.TabIndex, dummy);
@ -2232,12 +2221,12 @@ begin
for i:=1 to ds.RecordCount do
begin
// Search for the column name in listColumns
for j:=0 to ListColumns.Items.Count-1 do
for j:=0 to Length(VTRowDataListColumns)-1 do
begin
if ds.FieldByName('Column_name').AsString = ListColumns.Items[j].Caption then
if ds.FieldByName('Column_name').AsString = VTRowDataListColumns[j].Captions[0] then
begin
// Only apply a new icon if it was not already changed
if ListColumns.Items[j].ImageIndex <> ICONINDEX_FIELD then
if VTRowDataListColumns[j].ImageIndex <> ICONINDEX_FIELD then
break;
// Check if column is part of a fulltext key
@ -2248,16 +2237,16 @@ begin
// Primary key
if ds.FieldByName('Key_name').AsString = 'PRIMARY' then
ListColumns.Items[j].ImageIndex := ICONINDEX_PRIMARYKEY
VTRowDataListColumns[j].ImageIndex := ICONINDEX_PRIMARYKEY
// Fulltext index
else if isFullText then
ListColumns.Items[j].ImageIndex := ICONINDEX_FULLTEXTKEY
VTRowDataListColumns[j].ImageIndex := ICONINDEX_FULLTEXTKEY
// Unique index
else if ds.FieldByName('Non_unique').AsString = '0' then
ListColumns.Items[j].ImageIndex := ICONINDEX_UNIQUEKEY
VTRowDataListColumns[j].ImageIndex := ICONINDEX_UNIQUEKEY
// Normal index
else
ListColumns.Items[j].ImageIndex := ICONINDEX_INDEXKEY;
VTRowDataListColumns[j].ImageIndex := ICONINDEX_INDEXKEY;
// Column was found and processed
break;
@ -2265,17 +2254,28 @@ begin
end;
ds.Next;
end;
{
** note, ansgarbecker, 2007-08-26
VT has a pretty autosorting feature, which keeps the sorting even after having
filled it with new data.
But: Don't use this auto-sorting here, neither automatically nor manual
because that would cause big confusion to the user if a just clicked
table displays its fields not in the natural order.
@todo Detect if the list was just refreshed (and then keep sorting)
or if another table get displayed (then don't sort, as below)
}
ListColumns.Header.SortColumn := -1;
ListColumns.Header.SortDirection := sdAscending;
finally
ListColumns.Items.EndUpdate;
// Remove existing column-sort-images
// (TODO: auomatically invoke this method in TSortListView itself)
ListColumns.ClearSortColumnImages;
ListColumns.EndUpdate;
Screen.Cursor := crDefault;
end;
MainForm.ShowStatus( STATUS_MSG_READY, 2, false );
MainForm.showstatus(ActualDatabase + ': '+ ActualTable + ': ' + IntToStr(ListColumns.Items.count) +' field(s)');
MainForm.showstatus(ActualDatabase + ': '+ ActualTable + ': ' + IntToStr(ListColumns.RootNodeCount) +' field(s)');
Screen.Cursor := crDefault;
end;
@ -2478,7 +2478,7 @@ begin
exit;
// Add selected items/tables to helper list
t := GetSelectedNodesFromVT(ListTables);
t := GetVTCaptions(ListTables, True);
if MessageDlg('Empty ' + IntToStr(t.count) + ' Table(s) ?' + crlf + '(' + implodestr(', ', t) + ')', mtConfirmation, [mbok,mbcancel], 0) <> mrok then
exit;
@ -2932,44 +2932,41 @@ begin
end;
procedure TMDIChild.ListColumnsSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
{**
Clicked somewhere in the field-list of the "Table"-tabsheet
}
procedure TMDIChild.ListColumnsChange(Sender: TBaseVirtualTree; Node:
PVirtualNode);
var
SomeSelected: Boolean;
SomeSelected, OneFocused: Boolean;
begin
// Clicked somewhere in the field-list of the "Table"-tabsheet
// some columns selected ?
SomeSelected := ListColumns.Selected <> nil;
OneFocused := Assigned(Sender.FocusedNode);
SomeSelected := Length(Sender.GetSortedSelection(False))>0;
// Toggle state of menuitems and buttons
btnTableDropField.Enabled := SomeSelected;
DropField1.Enabled := SomeSelected;
MenuEditField.Enabled := SomeSelected;
btnTableEditField.enabled := SomeSelected;
menuRenameColumn.Enabled := SomeSelected;
MenuEditField.Enabled := OneFocused;
btnTableEditField.enabled := OneFocused;
menuRenameColumn.Enabled := OneFocused;
end;
procedure TMDIChild.DropField(Sender: TObject);
var
tn : TTreeNode;
i, j: Integer;
i : Integer;
dropCmd : String;
dropList : TStringList;
begin
// Drop Columns
// We allow the user to select and delete multiple listItems
dropList := TStringList.Create;
for i := 0 to ListColumns.Items.Count - 1 do
begin
if ListColumns.Items[i].Selected then
dropList.Add(ListColumns.Items[i].Caption);
end;
dropList := GetVTCaptions( ListColumns, True );
// In case all listItems are selected:
if dropList.Count = ListColumns.Items.Count then
if dropList.Count = Length(VTRowDataListColumns) then
begin
if MessageDlg('Can''t drop all or the last Field - drop Table '+ActualTable+'?', mtConfirmation, [mbok,mbcancel], 0) = mrok then
begin
@ -2999,20 +2996,12 @@ begin
// Rely on the server respective ExecUpdateQuery has raised an exception so the
// following code will be skipped on any error
for i := ListColumns.Items.Count - 1 downto 0 do
begin
for j := 0 to dropList.Count - 1 do
begin
if dropList[j] = ListColumns.Items[i].Caption then
begin
ListColumns.Items[i].Delete;
break;
end;
end;
end;
ListColumns.BeginUpdate;
ListColumns.DeleteSelectedNodes;
ListColumns.EndUpdate;
// Set focus on automatically focused item
ListColumns.Selected := ListColumns.ItemFocused;
// Set focus on first item
ListColumns.FocusedNode := ListColumns.GetFirstVisible;
except
On E : Exception do
begin
@ -3307,8 +3296,8 @@ begin
fn := '';
fem := femFieldAdd;
if ListColumns.Selected<>nil then
fn := ListColumns.Selected.Caption;
if Assigned(ListColumns.FocusedNode) then
fn := ListColumns.Text[ListColumns.FocusedNode, 0];
if fn<>'' then
fem := femFieldUpdate;
@ -3484,7 +3473,7 @@ var
begin
// Optimize tables
Screen.Cursor := crHourGlass;
Selected := GetSelectedNodesFromVT( ListTables );
Selected := GetVTCaptions( ListTables, True );
try
for i:=0 to Selected.Count-1 do
begin
@ -3506,7 +3495,7 @@ begin
// Check tables
Screen.Cursor := crHourGlass;
tables := '';
Selected := GetSelectedNodesFromVT( ListTables );
Selected := GetVTCaptions( ListTables, True );
try
for i:=0 to Selected.Count-1 do
begin
@ -3550,7 +3539,7 @@ begin
// Analyze tables
Screen.Cursor := crHourGlass;
tables := '';
Selected := GetSelectedNodesFromVT( ListTables );
Selected := GetVTCaptions( ListTables, True );
try
for i:=0 to Selected.Count-1 do
begin
@ -3575,7 +3564,7 @@ begin
// Repair tables
Screen.Cursor := crHourGlass;
tables := '';
Selected := GetSelectedNodesFromVT( ListTables );
Selected := GetVTCaptions( ListTables, True );
try
for i:=0 to Selected.Count - 1 do
begin
@ -4192,7 +4181,7 @@ var
begin
tabletype := (Sender as TMenuItem).Caption;
tabletype := StringReplace( tabletype, '&', '', [rfReplaceAll] ); // Remove Auto-Hotkey
Selected := GetSelectedNodesFromVT(ListTables);
Selected := GetVTCaptions(ListTables, True);
for i:=0 to Selected.Count - 1 do
ExecUpdateQuery( 'ALTER TABLE ' + mask(Selected[i]) + ' TYPE = ' + tabletype);
Selected.Free;
@ -4207,7 +4196,7 @@ var
begin
// change table-type:
if inputquery('Change table-type...','New table-type:', strtype) then begin
Selected := GetSelectedNodesFromVT(ListTables);
Selected := GetVTCaptions(ListTables, True);
for i:=0 to Selected.Count - 1 do
ExecUpdateQuery( 'ALTER TABLE ' + mask(Selected[i]) + ' TYPE = ' + strtype );
Selected.Free;
@ -4537,14 +4526,14 @@ begin
// Data-Tab
else if (PageControlMain.ActivePage = tabData)
and (-1 < gridData.Col)
and (gridData.Col <= ListColumns.Items.Count) then
and (gridData.Col <= Length(VTRowDataListColumns)) then
begin
keyword := ListColumns.Items[gridData.Col-1].SubItems[0];
keyword := VTRowDataListColumns[gridData.Col-1].Captions[1];
end
// Table-Tab
else if ListColumns.Focused and (ListColumns.Selected <> nil) then
else if ListColumns.Focused and Assigned(ListColumns.FocusedNode) then
begin
keyword := ListColumns.Selected.SubItems[0];
keyword := ListColumns.Text[ListColumns.FocusedNode, 1];
end
else if lboxQueryHelpers.Focused then
begin
@ -5682,9 +5671,9 @@ begin
begin
// Keep native order of columns
lboxQueryHelpers.Sorted := False;
for i := 0 to ListColumns.Items.Count - 1 do
for i := 0 to High(VTRowDataListColumns) do
begin
lboxQueryHelpers.Items.Add(ListColumns.Items[i].Caption);
lboxQueryHelpers.Items.Add(VTRowDataListColumns[i].Captions[0]);
end;
end;
@ -5793,25 +5782,29 @@ end;
}
procedure TMDIChild.menuRenameColumnClick(Sender: TObject);
begin
listColumns.Selected.EditCaption;
ListColumns.EditNode(ListColumns.FocusedNode, 0);
end;
{**
Rename a column name from within listColumns
}
procedure TMDIChild.ListColumnsEdited(Sender: TObject; Item: TListItem;
var S: string);
procedure TMDIChild.ListColumnsNewText(Sender: TBaseVirtualTree; Node:
PVirtualNode; Column: TColumnIndex; NewText: WideString);
var
def : TDataSet;
sql_update, sql_null, sql_default, sql_extra, DefaultValue : String;
NodeData : PVTreeData;
begin
// Try to rename, on any error abort and don't rename ListItem
try
ensureValidIdentifier( S );
ensureValidIdentifier( NewText );
// Fetch data from listitem
NodeData := ListColumns.GetNodeData(Node);
// Fetch column definition
def := GetResults( 'SHOW COLUMNS FROM ' + mask(ActualTable) + ' LIKE ' + esc(Item.Caption), False, False );
def := GetResults( 'SHOW COLUMNS FROM ' + mask(ActualTable) + ' LIKE ' + esc(NodeData.Captions[0]), False, False );
// Check NOT NULL
sql_null := 'NULL ';
@ -5835,8 +5828,8 @@ begin
// Concat column definition
sql_update := 'ALTER TABLE ' + mask(ActualTable) +
' CHANGE ' + mask(Item.Caption) +
' ' + mask(S) + ' ' +
' CHANGE ' + mask(NodeData.Captions[0]) +
' ' + mask(NewText) + ' ' +
def.FieldByName('Type').AsString + ' ' +
sql_null +
sql_default +
@ -5844,11 +5837,13 @@ begin
// Fire ALTER query
ExecUpdateQuery( sql_update, False, False );
// Update listitem
NodeData.Captions[0] := NewText;
except
On E : Exception do
begin
MessageDlg( E.Message, mtError, [mbOK], 0 );
abort;
end;
end;
end;
@ -5968,6 +5963,11 @@ begin
begin
NodeData.Captions := VTRowDataListTables[Node.Index].Captions;
NodeData.ImageIndex := VTRowDataListTables[Node.Index].ImageIndex;
end
else if Sender = ListColumns then
begin
NodeData.Captions := VTRowDataListColumns[Node.Index].Captions;
NodeData.ImageIndex := VTRowDataListColumns[Node.Index].ImageIndex;
end;
end;
@ -5978,13 +5978,30 @@ end;
procedure TMDIChild.vstFreeNode(Sender: TBaseVirtualTree; Node:
PVirtualNode);
var
NodeData : PVTreeData;
a : TVTreeDataArray;
begin
// Get the pointer to the node data
NodeData := Sender.GetNodeData(Node);
// Free data
NodeData.Captions.Free;
NodeData.ImageIndex := -1;
// Detect which global array should be processed
if Sender = ListVariables then
a := VTRowDataListVariables
else if Sender = ListCommandStats then
a := VTRowDataListCommandStats
else if Sender = ListProcesses then
a := VTRowDataListProcesses
else if Sender = ListTables then
a := VTRowDataListTables
else if Sender = ListColumns then
a := VTRowDataListColumns;
if Node.Index < Cardinal(High(a)-1) then
begin
// Delete node somewhere in the middle of the array
// Taken from http://delphi.about.com/cs/adptips2004/a/bltip0204_2.htm
System.Move( a[Node.Index +1],
a[Node.Index],
(Cardinal(Length(a)) - Node.Index -1) * SizeOf(TVTreeData) + 1
);
end;
SetLength(a, Length(a) - 1)
end;

View File

@ -46,11 +46,7 @@ var
reg_columns : TStringList;
begin
// Take column names from listColumns and add here
chklistColumns.Items.Clear;
for i := 0 to Mainform.Childwin.listColumns.Items.Count-1 do
begin
chklistColumns.Items.Add( Mainform.Childwin.listColumns.Items[i].Caption );
end;
chklistColumns.Items := GetVTCaptions(Mainform.Childwin.ListColumns);
// Set global reg_name (also used in btnOKClick)
reg_name := REGNAME_DISPLAYEDCOLUMNS + '_' + Mainform.Childwin.ActualDatabase + '.' + Mainform.Childwin.ActualTable;
@ -218,10 +214,9 @@ begin
// Add all fieldnames again and check those which are in the checkedfields list
chklistColumns.Items.BeginUpdate;
chklistColumns.Items.Clear;
for i := 0 to Mainform.Childwin.listColumns.Items.Count-1 do
chklistColumns.Items := GetVTCaptions(Mainform.Childwin.ListColumns);
for i := 0 to chklistColumns.Items.Count-1 do
begin
chklistColumns.Items.Add( Mainform.Childwin.listColumns.Items[i].Caption );
if checkedfields.IndexOf( chklistColumns.Items[i] ) > -1 then
chklistColumns.Checked[i] := True;
end;

View File

@ -49,7 +49,7 @@ const
implementation
uses main;
uses main, helpers;
{$R *.dfm}
@ -64,11 +64,7 @@ var
reg : TRegistry;
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;
ColumnNames := GetVTCaptions( Mainform.Childwin.ListColumns );
// Read original ORDER clause from registry
reg := TRegistry.Create();

View File

@ -358,7 +358,7 @@ begin
checkListTables.Items := Mainform.ChildWin.GetCol( 'SHOW TABLES FROM ' + MainForm.mask(comboSelectDatabase.Text) );
// Fetch selected tables in list
Selected := GetSelectedNodesFromVT( Mainform.ChildWin.ListTables );
Selected := GetVTCaptions( Mainform.ChildWin.ListTables, True );
// select all/some:
for i:=0 to checkListTables.Items.Count-1 do

View File

@ -10,7 +10,7 @@ interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ImgList, ToolWin, ExtCtrls, Buttons;
StdCtrls, ComCtrls, ImgList, ToolWin, ExtCtrls, Buttons, VirtualTrees;
type
TFieldEditorMode = (femFieldAdd,femFieldUpdate,femIndexEditor);
@ -130,7 +130,8 @@ procedure TFieldEditForm.InitFieldEditor(Sender: TObject);
var
strtype : String;
i : Integer;
ListColumns : TListView;
ListColumns : TVirtualStringTree;
NodeData : PVTreeData;
begin
// Initiate "Position"-combobox
@ -143,9 +144,9 @@ begin
// get fieldlist
// add fieldnames
for i:=0 to ListColumns.Items.Count-1 do
for i:=0 to High(Mainform.Childwin.VTRowDataListColumns) do
begin
ComboBoxPosition.Items.Add('AFTER ' + mainform.mask(ListColumns.Items[i].Caption));
ComboBoxPosition.Items.Add('AFTER ' + mainform.mask(Mainform.Childwin.VTRowDataListColumns[i].Captions[0]));
end;
// re-fill datatypes-combobox
@ -168,8 +169,8 @@ begin
EditDefault.Text := '';
CheckBoxUnsigned.Checked := true;
if ListColumns.Selected <> nil then
ComboBoxPosition.ItemIndex := ListColumns.Selected.Index+2
if Assigned(ListColumns.FocusedNode) then
ComboBoxPosition.ItemIndex := ListColumns.FocusedNode.Index+2
else
ComboBoxPosition.ItemIndex := 0;
end;
@ -177,12 +178,13 @@ begin
// "Field" tab in Update-mode
femFieldUpdate:
begin
EditFieldname.Text := ListColumns.Selected.Caption;
EditLength.Text := getEnumValues( ListColumns.Selected.Subitems[0] );
EditDefault.Text := ListColumns.Selected.Subitems[2];
NodeData := ListColumns.GetNodeData(ListColumns.FocusedNode);
EditFieldname.Text := FFieldName;
EditLength.Text := getEnumValues( NodeData.Captions[1] );
EditDefault.Text := NodeData.Captions[3];
// extract field type
strtype := UpperCase( ListColumns.Selected.Subitems[0] );
strtype := UpperCase( NodeData.Captions[1] );
if Pos ('(',strtype) > 0 then
strtype := Trim(copy (strtype,0,Pos ('(',strtype)-1));
@ -202,12 +204,12 @@ begin
end;
// set attributes:
strtype := LowerCase( ListColumns.Selected.Subitems[0] );
strtype := LowerCase( NodeData.Captions[1] );
CheckBoxBinary.Checked := pos('binary', strtype) > 0;
CheckBoxZerofill.Checked := pos('zerofill', strtype) > 0;
CheckBoxUnsigned.Checked := pos('unsigned', strtype) > 0;
CheckBoxNotNull.Checked := lowercase(ListColumns.Selected.Subitems[1]) <> 'yes';
CheckBoxAutoIncrement.Checked := lowercase(ListColumns.Selected.Subitems[3]) = 'auto_increment';
CheckBoxNotNull.Checked := lowercase(NodeData.Captions[2]) <> 'yes';
CheckBoxAutoIncrement.Checked := lowercase(NodeData.Captions[4]) = 'auto_increment';
// TODO: Disable 'auto increment' checkbox if field is not part of index or primary key.
end;
@ -252,10 +254,7 @@ begin
ds.Next;
end;
for i:=0 to cwin.ListColumns.Items.Count-1 do begin
if cwin.ListColumns.Items[i] <> nil then
self.listColumnsAvailable.Items.Add(cwin.ListColumns.Items[i].Caption);
end;
listColumnsAvailable.Items := GetVTCaptions(cwin.ListColumns);
showkeys();
end;
@ -431,7 +430,7 @@ begin
end else if (FMode = femFieldUpdate) then begin
cwin.ExecUpdateQuery(
'ALTER TABLE ' + mainform.mask(cwin.ActualTable) + ' ' + // table
'CHANGE ' + mainform.mask(cwin.ListColumns.Selected.Caption) + ' ' + // old name
'CHANGE ' + mainform.mask(FFieldName) + ' ' + // old name
mainform.mask(EditFieldName.Text) + ' ' + // new name
fielddef
);
@ -532,13 +531,16 @@ end;
@todo code cleanup, get rid of WITH statement
}
procedure TFieldEditForm.ComboBoxKeysChange(Sender: TObject);
var i : Integer;
var i, j : Integer;
begin
if ComboBoxKeys.ItemIndex > -1 then begin
listColumnsAvailable.Items.Clear;
for i:=0 to Mainform.ChildWin.ListColumns.Items.Count-1 do
if (Mainform.ChildWin.ListColumns.Items[i] <> nil) and (klist[ComboBoxKeys.ItemIndex].columns.Indexof(Mainform.ChildWin.ListColumns.Items[i].Caption)=-1) then
listColumnsAvailable.Items.Add(Mainform.ChildWin.ListColumns.Items[i].Caption);
listColumnsAvailable.Items := GetVTCaptions(Mainform.ChildWin.ListColumns);
for i:=0 to klist[ComboBoxKeys.ItemIndex].columns.Count-1 do
begin
j := listColumnsAvailable.Items.IndexOf(klist[ComboBoxKeys.ItemIndex].columns[i]);
if j > -1 then
listColumnsAvailable.Items.Delete( j );
end;
with klist[ComboBoxKeys.ItemIndex] do begin
listColumnsUsed.Items := Columns;
CheckBoxUnique.OnClick := nil;

View File

@ -21,6 +21,9 @@ type
end;
PVTreedata = ^TVTreeData;
// Standardize the list with node-data-records to be able to
// use this type as variables in functions/procedures (fx VT.OnFreeNode)
TVTreeDataArray = Array of TVTreeData;
{$I const.inc}
@ -81,7 +84,7 @@ type
function FormatByteNumber( Bytes: Int64; Decimals: Byte = 1 ): String;
function FormatTimeNumber( Seconds: Cardinal ): String;
function TColorToHex( Color : TColor ): string;
function GetSelectedNodesFromVT( VT: TVirtualStringTree; Column: Integer = 0 ): TStringList;
function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0 ): TStringList;
var
MYSQL_KEYWORDS : TStringList;
@ -1996,18 +1999,31 @@ end;
Return a TStringList with captions from all selected nodes in a VirtualTree
Especially helpful when toMultiSelect is True
}
function GetSelectedNodesFromVT( VT: TVirtualStringTree; Column: Integer = 0 ): TStringList;
function GetVTCaptions( VT: TVirtualStringTree; OnlySelected: Boolean = False; Column: Integer = 0 ): TStringList;
var
SelectedNodes : TNodeArray;
NodeData : PVTreeData;
Node : PVirtualNode;
i: Integer;
begin
Result := TStringList.Create;
if OnlySelected then
begin
// Fetch only selected nodes
SelectedNodes := VT.GetSortedSelection(False);
for i := 0 to Length(SelectedNodes) - 1 do
begin
NodeData := VT.GetNodeData(SelectedNodes[i]);
Result.Add(NodeData.Captions[Column]);
Node := SelectedNodes[i];
Result.Add( VT.Text[ Node, Column ] );
end;
end
else begin
// Fetch all nodes
Node := VT.GetFirst;
for i := 0 to VT.RootNodeCount - 1 do
begin
Result.Add( VT.Text[ Node, Column ] );
Node := VT.GetNext(Node);
end;
end;
end;

View File

@ -994,7 +994,7 @@ begin
t.add(mask(DBRightClickSelectedItem.Parent.text) + '.' + mask(DBRightClickSelectedItem.text));
end else if PageControlMain.ActivePage = tabDatabase then begin
// Invoked from one of the various buttons, SheetDatabase is the active page, drop highlighted table(s).
t := GetSelectedNodesFromVT(ListTables);
t := GetVTCaptions(ListTables, True);
for i:=0 to t.count-1 do
begin
t[i] := mask(t[i]);

View File

@ -72,15 +72,16 @@ begin
cwin := Mainform.ChildWin;
// which ListView to print?
case cwin.PageControlMain.ActivePageIndex of
// TODO: Reactivate after switching to VirtualTree!
// case cwin.PageControlMain.ActivePageIndex of
// 0 : case cwin.PageControlHost.ActivePageIndex of
// 0 : begin list := cwin.ListVariables; title := 'Server-Variables for ' + cwin.Conn.MysqlParams.Host; end;
// 1 : begin list := cwin.ListProcesses; title := 'Processlist for ' + cwin.Conn.MysqlParams.Host; end;
// 2 : begin list := cwin.ListCommandStats; title := 'Command-statistics for ' + cwin.Conn.MysqlParams.Host; end;
// end;
// 1 : begin list := cwin.ListTables; title := 'Tables-List for Database ' + cwin.ActualDatabase; end;
2 : begin list := cwin.ListColumns; title := 'Field-List for ' + cwin.ActualDatabase + '/' + cwin.ActualTable; end;
end;
// 2 : begin list := cwin.ListColumns; title := 'Field-List for ' + cwin.ActualDatabase + '/' + cwin.ActualTable; end;
// end;
caption := 'Print ' + title + '...';
// delete all CheckBoxes

View File

@ -95,7 +95,7 @@ begin
end;
// Fetch selected nodes
Selected := GetSelectedNodesFromVT(ListTables);
Selected := GetVTCaptions(ListTables, True);
// for tables found
for t := 0 to (query.RecordCount - 1) do