mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
Convert ListProcesses from TSortListView to VirtualTree.
- Don't replace "ListProcessesSelectItem" by "ListProcessesClick". Do the menuitem stuff in popupHost.popup() - Avoid potential AV when exceeding the captions-list of a node in GetNodeText.
This commit is contained in:
@ -157,59 +157,83 @@ object MDIChild: TMDIChild
|
|||||||
object tabProcessList: TTabSheet
|
object tabProcessList: TTabSheet
|
||||||
Caption = 'Process-List'
|
Caption = 'Process-List'
|
||||||
ImageIndex = 1
|
ImageIndex = 1
|
||||||
object ListProcesses: TSortListView
|
object ListProcesses: TVirtualStringTree
|
||||||
Tag = -1
|
|
||||||
Left = 0
|
Left = 0
|
||||||
Top = 0
|
Top = 0
|
||||||
Width = 488
|
Width = 488
|
||||||
Height = 175
|
Height = 175
|
||||||
Align = alClient
|
Align = alClient
|
||||||
|
Header.AutoSizeIndex = 7
|
||||||
|
Header.Font.Charset = DEFAULT_CHARSET
|
||||||
|
Header.Font.Color = clWindowText
|
||||||
|
Header.Font.Height = -11
|
||||||
|
Header.Font.Name = 'Tahoma'
|
||||||
|
Header.Font.Style = []
|
||||||
|
Header.Options = [hoAutoResize, hoColumnResize, hoDblClickResize, hoDrag, hoShowSortGlyphs, hoVisible]
|
||||||
|
Header.SortColumn = 0
|
||||||
|
Header.SortDirection = sdDescending
|
||||||
|
Images = MainForm.ImageList1
|
||||||
|
IncrementalSearch = isInitializedOnly
|
||||||
|
PopupMenu = popupHost
|
||||||
|
TabOrder = 0
|
||||||
|
TreeOptions.AutoOptions = [toAutoDropExpand, toAutoScrollOnExpand, toAutoSort, toAutoTristateTracking, toAutoDeleteMovedNodes]
|
||||||
|
TreeOptions.MiscOptions = [toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning]
|
||||||
|
TreeOptions.PaintOptions = [toShowDropmark, toShowHorzGridLines, toShowVertGridLines, toThemeAware, toUseBlendedImages]
|
||||||
|
TreeOptions.SelectionOptions = [toFullRowSelect, toRightClickSelect]
|
||||||
|
OnCompareNodes = vstCompareNodes
|
||||||
|
OnFreeNode = vstFreeNode
|
||||||
|
OnGetText = vstGetText
|
||||||
|
OnGetImageIndex = vstGetImageIndex
|
||||||
|
OnGetNodeDataSize = vstGetNodeDataSize
|
||||||
|
OnHeaderClick = vstHeaderClick
|
||||||
|
OnInitNode = vstInitNode
|
||||||
Columns = <
|
Columns = <
|
||||||
item
|
item
|
||||||
Caption = 'id'
|
Alignment = taRightJustify
|
||||||
Width = -1
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
WidthType = (
|
Position = 0
|
||||||
-1)
|
WideText = 'id'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'User'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
|
Position = 1
|
||||||
Width = 80
|
Width = 80
|
||||||
|
WideText = 'User'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'Host'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
Tag = -1
|
Position = 2
|
||||||
Width = 80
|
Width = 80
|
||||||
|
WideText = 'Host'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'DB'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
Width = -1
|
Position = 3
|
||||||
WidthType = (
|
|
||||||
-1)
|
|
||||||
end
|
|
||||||
item
|
|
||||||
Caption = 'Command'
|
|
||||||
Width = 80
|
Width = 80
|
||||||
|
WideText = 'DB'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'Time'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
|
Position = 4
|
||||||
|
Width = 80
|
||||||
|
WideText = 'Command'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'State'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
|
Position = 5
|
||||||
|
WideText = 'Time'
|
||||||
end
|
end
|
||||||
item
|
item
|
||||||
Caption = 'Info'
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
Width = 126
|
Position = 6
|
||||||
|
WideText = 'State'
|
||||||
|
end
|
||||||
|
item
|
||||||
|
Options = [coAllowClick, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
|
||||||
|
Position = 7
|
||||||
|
Width = 14
|
||||||
|
WideText = 'Info'
|
||||||
end>
|
end>
|
||||||
GridLines = True
|
|
||||||
ReadOnly = True
|
|
||||||
RowSelect = True
|
|
||||||
PopupMenu = popupHost
|
|
||||||
SmallImages = MainForm.ImageList1
|
|
||||||
TabOrder = 0
|
|
||||||
ViewStyle = vsReport
|
|
||||||
OnSelectItem = ListProcessesSelectItem
|
|
||||||
ImageIndexSortAsc = 95
|
|
||||||
ImageIndexSortDesc = 94
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
object tabCommandStats: TTabSheet
|
object tabCommandStats: TTabSheet
|
||||||
|
@ -61,7 +61,7 @@ type
|
|||||||
tabVariables: TTabSheet;
|
tabVariables: TTabSheet;
|
||||||
tabProcessList: TTabSheet;
|
tabProcessList: TTabSheet;
|
||||||
ListVariables: TVirtualStringTree;
|
ListVariables: TVirtualStringTree;
|
||||||
ListProcesses: TSortListView;
|
ListProcesses: TVirtualStringTree;
|
||||||
popupHost: TPopupMenu;
|
popupHost: TPopupMenu;
|
||||||
Kill1: TMenuItem;
|
Kill1: TMenuItem;
|
||||||
NewDatabase1: TMenuItem;
|
NewDatabase1: TMenuItem;
|
||||||
@ -329,8 +329,6 @@ type
|
|||||||
Selected: Boolean);
|
Selected: Boolean);
|
||||||
procedure ListColumnsSelectItem(Sender: TObject; Item: TListItem;
|
procedure ListColumnsSelectItem(Sender: TObject; Item: TListItem;
|
||||||
Selected: Boolean);
|
Selected: Boolean);
|
||||||
procedure ListProcessesSelectItem(Sender: TObject; Item: TListItem;
|
|
||||||
Selected: Boolean);
|
|
||||||
procedure DBMemo1Exit(Sender: TObject);
|
procedure DBMemo1Exit(Sender: TObject);
|
||||||
procedure btnUnsafeEditClick(Sender: TObject);
|
procedure btnUnsafeEditClick(Sender: TObject);
|
||||||
procedure gridMouseDown(Sender: TObject; Button: TMouseButton;
|
procedure gridMouseDown(Sender: TObject; Button: TMouseButton;
|
||||||
@ -538,6 +536,7 @@ type
|
|||||||
CachedTableLists : TStringList;
|
CachedTableLists : TStringList;
|
||||||
QueryHelpersSelectedItems : Array[0..3] of Integer;
|
QueryHelpersSelectedItems : Array[0..3] of Integer;
|
||||||
VTRowDataListVariables,
|
VTRowDataListVariables,
|
||||||
|
VTRowDataListProcesses,
|
||||||
VTRowDataListCommandStats : Array of TVTreeData;
|
VTRowDataListCommandStats : Array of TVTreeData;
|
||||||
|
|
||||||
function GetQueryRunning: Boolean;
|
function GetQueryRunning: Boolean;
|
||||||
@ -1852,7 +1851,7 @@ begin
|
|||||||
ValidateControls;
|
ValidateControls;
|
||||||
|
|
||||||
// Show processlist if it's visible now but empty yet
|
// Show processlist if it's visible now but empty yet
|
||||||
if ListProcesses.Items.Count = 0 then
|
if ListProcesses.RootNodeCount = 0 then
|
||||||
ShowProcessList( self );
|
ShowProcessList( self );
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2669,7 +2668,6 @@ end;
|
|||||||
procedure TMDIChild.ShowProcessList(sender: TObject);
|
procedure TMDIChild.ShowProcessList(sender: TObject);
|
||||||
var
|
var
|
||||||
i,j : Integer;
|
i,j : Integer;
|
||||||
n : TListItem;
|
|
||||||
ds : TDataSet;
|
ds : TDataSet;
|
||||||
begin
|
begin
|
||||||
// No need to update if it's not visible.
|
// No need to update if it's not visible.
|
||||||
@ -2677,57 +2675,49 @@ begin
|
|||||||
if PageControlHost.ActivePage <> tabProcesslist then exit;
|
if PageControlHost.ActivePage <> tabProcesslist then exit;
|
||||||
Screen.Cursor := crSQLWait;
|
Screen.Cursor := crSQLWait;
|
||||||
try
|
try
|
||||||
ListProcesses.Items.BeginUpdate;
|
ListProcesses.BeginUpdate;
|
||||||
ListProcesses.Items.Clear;
|
ListProcesses.Clear;
|
||||||
debug('ShowProcessList()');
|
debug('ShowProcessList()');
|
||||||
ds := GetResults('SHOW FULL PROCESSLIST', false, false);
|
ds := GetResults('SHOW FULL PROCESSLIST', false, false);
|
||||||
|
SetLength(VTRowDataListProcesses, ds.RecordCount);
|
||||||
for i:=1 to ds.RecordCount do
|
for i:=1 to ds.RecordCount do
|
||||||
begin
|
begin
|
||||||
n := ListProcesses.Items.Add;
|
VTRowDataListProcesses[i-1].Captions := TStringList.Create;
|
||||||
n.Caption := ds.Fields[0].AsString;
|
VTRowDataListProcesses[i-1].Captions.Add( ds.Fields[0].AsString );
|
||||||
if CompareText( ds.Fields[4].AsString, 'Killed') = 0 then
|
if CompareText( ds.Fields[4].AsString, 'Killed') = 0 then
|
||||||
n.ImageIndex := 83 // killed
|
VTRowDataListProcesses[i-1].ImageIndex := 83 // killed
|
||||||
else
|
else
|
||||||
n.ImageIndex := 82; // running
|
VTRowDataListProcesses[i-1].ImageIndex := 82; // running
|
||||||
for j := 1 to 7 do
|
for j := 1 to 7 do
|
||||||
n.Subitems.Add(ds.Fields[j].AsString);
|
VTRowDataListProcesses[i-1].Captions.Add(ds.Fields[j].AsString);
|
||||||
ds.Next;
|
ds.Next;
|
||||||
end;
|
end;
|
||||||
ds.Close;
|
ds.Close;
|
||||||
ListProcesses.Items.EndUpdate;
|
tabProcessList.Caption := 'Process-List (' + IntToStr(Length(VTRowDataListProcesses)) + ')';
|
||||||
// Remove existing column-sort-images
|
|
||||||
// (TODO: auomatically invoke this method in TSortListView itself)
|
|
||||||
ListProcesses.ClearSortColumnImages;
|
|
||||||
tabProcessList.Caption := 'Process-List (' + IntToStr(ListProcesses.Items.Count) + ')';
|
|
||||||
except
|
except
|
||||||
on E: Exception do begin
|
on E: Exception do begin
|
||||||
LogSQL('Error loading process list (automatic refresh disabled): ' + e.Message);
|
LogSQL('Error loading process list (automatic refresh disabled): ' + e.Message);
|
||||||
TimerProcesslist.Enabled := false;
|
TimerProcesslist.Enabled := false;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
ListProcesses.Items.EndUpdate;
|
ListProcesses.RootNodeCount := Length(VTRowDataListProcesses);
|
||||||
|
ListProcesses.EndUpdate;
|
||||||
Screen.Cursor := crDefault;
|
Screen.Cursor := crDefault;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TMDIChild.ListProcessesSelectItem(Sender: TObject; Item: TListItem;
|
|
||||||
Selected: Boolean);
|
|
||||||
begin
|
|
||||||
Kill1.Enabled := (ListProcesses.Selected <> nil) and (PageControlHost.ActivePage = tabProcessList);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure TMDIChild.KillProcess(Sender: TObject);
|
procedure TMDIChild.KillProcess(Sender: TObject);
|
||||||
var t : Boolean;
|
var t : Boolean;
|
||||||
|
NodeData : PVTreeData;
|
||||||
begin
|
begin
|
||||||
if ListProcesses.Selected.Caption = IntToStr( MySQLConn.Connection.GetThreadId ) then
|
NodeData := ListProcesses.GetNodeData(ListProcesses.FocusedNode);
|
||||||
|
if NodeData.Captions[0] = IntToStr( MySQLConn.Connection.GetThreadId ) then
|
||||||
MessageDlg('Fatal: Better not kill my own Process...', mtError, [mbok], 0)
|
MessageDlg('Fatal: Better not kill my own Process...', mtError, [mbok], 0)
|
||||||
else begin
|
else begin
|
||||||
t := TimerProcessList.Enabled;
|
t := TimerProcessList.Enabled;
|
||||||
TimerProcessList.Enabled := false; // prevent av (ListProcesses.selected...)
|
TimerProcessList.Enabled := false; // prevent av (ListProcesses.selected...)
|
||||||
if MessageDlg('Kill Process '+ListProcesses.Selected.Caption+'?', mtConfirmation, [mbok,mbcancel], 0) = mrok then
|
if MessageDlg('Kill Process '+NodeData.Captions[0]+'?', mtConfirmation, [mbok,mbcancel], 0) = mrok then
|
||||||
begin
|
begin
|
||||||
ExecUpdateQuery( 'KILL '+ListProcesses.Selected.Caption );
|
ExecUpdateQuery( 'KILL '+NodeData.Captions[0] );
|
||||||
ShowVariablesAndProcesses(self);
|
ShowVariablesAndProcesses(self);
|
||||||
end;
|
end;
|
||||||
TimerProcessList.Enabled := t; // re-enable autorefresh timer
|
TimerProcessList.Enabled := t; // re-enable autorefresh timer
|
||||||
@ -2738,9 +2728,8 @@ end;
|
|||||||
procedure TMDIChild.PageControlHostChange(Sender: TObject);
|
procedure TMDIChild.PageControlHostChange(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
// Show processlist if it's visible now but empty yet
|
// Show processlist if it's visible now but empty yet
|
||||||
if ListProcesses.Items.Count = 0 then
|
if ListProcesses.RootNodeCount = 0 then
|
||||||
ShowProcessList( self );
|
ShowProcessList( self );
|
||||||
ListProcessesSelectItem(self, nil, False);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -4450,6 +4439,7 @@ end;
|
|||||||
procedure TMDIChild.popupHostPopup(Sender: TObject);
|
procedure TMDIChild.popupHostPopup(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
MenuAutoupdate.Enabled := PageControlHost.ActivePage = tabProcessList;
|
MenuAutoupdate.Enabled := PageControlHost.ActivePage = tabProcessList;
|
||||||
|
Kill1.Enabled := (PageControlHost.ActivePage = tabProcessList) and Assigned(ListProcesses.FocusedNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMDIChild.ListTablesEditing(Sender: TObject; Item: TListItem;
|
procedure TMDIChild.ListTablesEditing(Sender: TObject; Item: TListItem;
|
||||||
@ -5989,6 +5979,11 @@ begin
|
|||||||
begin
|
begin
|
||||||
NodeData.Captions := VTRowDataListCommandStats[Node.Index].Captions;
|
NodeData.Captions := VTRowDataListCommandStats[Node.Index].Captions;
|
||||||
NodeData.ImageIndex := VTRowDataListCommandStats[Node.Index].ImageIndex;
|
NodeData.ImageIndex := VTRowDataListCommandStats[Node.Index].ImageIndex;
|
||||||
|
end
|
||||||
|
else if Sender = ListProcesses then
|
||||||
|
begin
|
||||||
|
NodeData.Captions := VTRowDataListProcesses[Node.Index].Captions;
|
||||||
|
NodeData.ImageIndex := VTRowDataListProcesses[Node.Index].ImageIndex;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6017,13 +6012,20 @@ procedure TMDIChild.vstGetText(Sender: TBaseVirtualTree; Node:
|
|||||||
WideString);
|
WideString);
|
||||||
var
|
var
|
||||||
NodeData : PVTreeData;
|
NodeData : PVTreeData;
|
||||||
|
i : Integer;
|
||||||
begin
|
begin
|
||||||
// Get pointer to node which gets displayed
|
// Get pointer to node which gets displayed
|
||||||
NodeData := Sender.GetNodeData(Node);
|
NodeData := Sender.GetNodeData(Node);
|
||||||
case Column of
|
// Column is -1 if no column headers are defined
|
||||||
-1: CellText := NodeData.Captions[0]; // Column is -1 if no column headers are defined
|
if Column = -1 then
|
||||||
else CellText := NodeData.Captions[Column];
|
i := 0
|
||||||
end;
|
else
|
||||||
|
i := Column;
|
||||||
|
// Avoid AV, don't exceed Captions content
|
||||||
|
if NodeData.Captions.Count > i then
|
||||||
|
CellText := NodeData.Captions[i]
|
||||||
|
else
|
||||||
|
CellText := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@ begin
|
|||||||
|
|
||||||
// which ListView to print?
|
// which ListView to print?
|
||||||
case cwin.PageControlMain.ActivePageIndex of
|
case cwin.PageControlMain.ActivePageIndex of
|
||||||
0 : case cwin.PageControlHost.ActivePageIndex of
|
// 0 : case cwin.PageControlHost.ActivePageIndex of
|
||||||
// 0 : begin list := cwin.ListVariables; title := 'Server-Variables for ' + cwin.Conn.MysqlParams.Host; end;
|
// 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;
|
// 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;
|
// 2 : begin list := cwin.ListCommandStats; title := 'Command-statistics for ' + cwin.Conn.MysqlParams.Host; end;
|
||||||
end;
|
// end;
|
||||||
1 : begin list := cwin.ListTables; title := 'Tables-List for Database ' + cwin.ActualDatabase; 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;
|
2 : begin list := cwin.ListColumns; title := 'Field-List for ' + cwin.ActualDatabase + '/' + cwin.ActualTable; end;
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user