Skip to content

Commit fc222fb

Browse files
committed
feat: show table columns in tree, as child nodes
Refs #2069
1 parent 0014f1b commit fc222fb

8 files changed

Lines changed: 298 additions & 265 deletions

File tree

res/icons/table_column.png

592 Bytes
Loading

res/icons/table_column_add.png

628 Bytes
Loading

res/icons/table_column_delete.png

629 Bytes
Loading

source/dbconnection.pas

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ TTableKeyList = class(TObjectList<TTableKey>)
112112
public
113113
procedure Assign(Source: TTableKeyList);
114114
function MaxSize: Int64;
115+
// Retrieve key icon index for a column, or the normal field icon if it has no key
116+
function ImageIndex(ColumnName: String): Integer;
115117
end;
116118
TKeyCache = TDictionary<String,TTableKeyList>;
117119

@@ -11296,6 +11298,18 @@ function TTableKeyList.MaxSize: Int64;
1129611298
end;
1129711299
end;
1129811300

11301+
function TTableKeyList.ImageIndex(ColumnName: String): Integer;
11302+
var
11303+
Key: TTableKey;
11304+
begin
11305+
Result := ICONINDEX_FIELD;
11306+
for Key in Self do begin
11307+
if Key.Columns.Contains(ColumnName) then begin
11308+
Result := Key.ImageIndex;
11309+
Break;
11310+
end;
11311+
end;
11312+
end;
1129911313

1130011314

1130111315
{ *** TForeignKey }

source/main.dfm

Lines changed: 212 additions & 220 deletions
Large diffs are not rendered by default.

source/main.pas

Lines changed: 67 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6929,9 +6929,7 @@ procedure TMainForm.SynCompletionProposalExecute(Kind: SynCompletionType;
69296929
Columns: TTableColumnList;
69306930
Col: TTableColumn;
69316931
Keys: TTableKeyList;
6932-
Key: TTableKey;
69336932
Obj: TDBObject;
6934-
ColumnIcon: Integer;
69356933
begin
69366934
dbname := '';
69376935
tblname := LeftToken;
@@ -6950,16 +6948,8 @@ procedure TMainForm.SynCompletionProposalExecute(Kind: SynCompletionType;
69506948
Columns := Obj.TableColumns;
69516949
Keys := Obj.TableKeys;
69526950
for Col in Columns do begin
6953-
// Detect index icon, if any
6954-
ColumnIcon := ICONINDEX_FIELD;
6955-
for Key in Keys do begin
6956-
if Key.Columns.Contains(Col.Name) then begin
6957-
ColumnIcon := Key.ImageIndex;
6958-
Break;
6959-
end;
6960-
end;
69616951
// Put formatted text and icon into proposal
6962-
DisplayText := SynCompletionProposalPrettyText(ColumnIcon, LowerCase(Col.DataType.Name), Col.Name, Col.Comment, DatatypeCategories[Col.DataType.Category].NullColor);
6952+
DisplayText := SynCompletionProposalPrettyText(Keys.ImageIndex(Col.Name), LowerCase(Col.DataType.Name), Col.Name, Col.Comment, DatatypeCategories[Col.DataType.Category].NullColor);
69636953
if CurrentInput.StartsWith(Conn.QuoteChar) then
69646954
Proposal.AddItem(DisplayText, Conn.QuoteChar + Col.Name)
69656955
else
@@ -7700,10 +7690,14 @@ procedure TMainForm.SynMemoQueryDragDrop(Sender, Source: TObject; X,
77007690
// Insert table or database name. If a table is dropped and Shift is pressed, prepend the db name.
77017691
case ActiveDbObj.NodeType of
77027692
lntDb: Text := ActiveDbObj.QuotedDatabase(False);
7703-
lntTable..lntEvent: begin
7704-
if ShiftPressed then
7705-
Text := ActiveDbObj.QuotedDatabase(False) + '.';
7706-
Text := Text + ActiveDbObj.Connection.QuoteIdent(ActiveDbObj.Name, False);
7693+
lntTable..lntEvent, lntColumn: begin
7694+
Text := '';
7695+
if ShiftPressed then begin
7696+
Text := Text + ActiveDbObj.QuotedDatabase(False) + '.';
7697+
if ActiveDbObj.NodeType = lntColumn then
7698+
Text := Text + ActiveDbObj.QuotedName(False) + '.';
7699+
end;
7700+
Text := Text + ActiveDbObj.Connection.QuoteIdent(DBtree.Text[DBtree.FocusedNode, DBtree.FocusedColumn], False);
77077701
end;
77087702
end;
77097703
end else if src = Tree then begin
@@ -9806,7 +9800,8 @@ procedure TMainForm.DBtreeGetImageIndex(Sender: TBaseVirtualTree; Node:
98069800
PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted:
98079801
Boolean; var ImageIndex: TImageIndex);
98089802
var
9809-
DBObj: PDBObject;
9803+
DBObj, ParentObj: PDBObject;
9804+
TableKeys: TTableKeyList;
98109805
begin
98119806
if Column > 0 then
98129807
Exit;
@@ -9816,6 +9811,11 @@ procedure TMainForm.DBtreeGetImageIndex(Sender: TBaseVirtualTree; Node:
98169811
case Kind of
98179812
ikNormal, ikSelected: begin
98189813
ImageIndex := DBObj.ImageIndex;
9814+
if DBObj.NodeType = lntColumn then begin // Key/index icon
9815+
ParentObj := Sender.GetNodeData(Node.Parent);
9816+
ImageIndex := ParentObj.TableKeys.ImageIndex(DBObj.Column);
9817+
end;
9818+
98199819
Ghosted := (DBObj.NodeType = lntNone) and (not DBObj.Connection.Active);
98209820
Ghosted := Ghosted or ((DBObj.NodeType = lntDB)
98219821
and (not DBObj.Connection.DbObjectsCached(DBObj.Database))
@@ -9878,8 +9878,7 @@ procedure TMainForm.DBtreeInitChildren(Sender: TBaseVirtualTree; Node: PVirtualN
98789878
DBObjects := DBObj.Connection.GetDBObjects(DBObj.Database, False, DBObj.GroupType);
98799879
ChildCount := DBObjects.Count;
98809880
end;
9881-
lntTable:
9882-
if GetParentFormOrFrame(Sender) is TfrmSelectDBObject then begin
9881+
lntTable: begin
98839882
Columns := DBObj.TableColumns;
98849883
ChildCount := Columns.Count;
98859884
end;
@@ -9929,14 +9928,14 @@ procedure TMainForm.DBtreeInitNode(Sender: TBaseVirtualTree; ParentNode, Node:
99299928
end else begin
99309929
DBObjects := ParentObj.Connection.GetDBObjects(ParentObj.Database);
99319930
Item^ := DBObjects[Node.Index];
9932-
if (GetParentFormOrFrame(Sender) is TfrmSelectDBObject) and (Item.NodeType = lntTable) then
9931+
if Item.NodeType = lntTable then
99339932
Include(InitialStates, ivsHasChildren);
99349933
end;
99359934
end;
99369935
lntGroup: begin
99379936
DBObjects := ParentObj.Connection.GetDBObjects(ParentObj.Database, False, ParentObj.GroupType);
99389937
Item^ := DBObjects[Node.Index];
9939-
if (GetParentFormOrFrame(Sender) is TfrmSelectDBObject) and (Item.NodeType = lntTable) then
9938+
if Item.NodeType = lntTable then
99409939
Include(InitialStates, ivsHasChildren);
99419940
end;
99429941
lntTable: begin
@@ -9958,13 +9957,15 @@ procedure TMainForm.DBtreeInitNode(Sender: TBaseVirtualTree; ParentNode, Node:
99589957
procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex);
99599958
var
99609959
DBObj, PrevDBObj, ParentDBObj: PDBObject;
9960+
TableLevelObj: TDBObject;
99619961
MainTabToActivate: TTabSheet;
99629962
EnteringSession: Boolean;
99639963
begin
99649964
// Set wanted main tab and call SetMainTab later, when all lists have been invalidated
99659965
MainTabToActivate := nil;
99669966
PrevDBObj := nil;
99679967
ParentDBObj := nil;
9968+
TableLevelObj := nil;
99689969

99699970
if Assigned(Node) then begin
99709971
LogSQL('DBtreeFocusChanged, Node level: '+IntToStr(Sender.GetNodeLevel(Node))+', FTreeRefreshInProgress: '+IntToStr(Integer(FTreeRefreshInProgress)), lcDebug);
@@ -9979,6 +9980,10 @@ procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualN
99799980
FActiveDbObj.Assign(DBObj^);
99809981
if Assigned(Node.Parent) and (DBtree.GetNodeLevel(Node) > 0) then
99819982
ParentDBObj := Sender.GetNodeData(Node.Parent);
9983+
if FActiveDbObj.NodeType = lntColumn then
9984+
TableLevelObj := ParentDBObj^
9985+
else
9986+
TableLevelObj := FActiveDbObj;
99829987

99839988
case FActiveDbObj.NodeType of
99849989
lntNone: begin
@@ -10000,7 +10005,7 @@ procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualN
1000010005
MainTabToActivate := tabDatabase;
1000110006
FActiveObjectGroup := FActiveDbObj.GroupType;
1000210007
end;
10003-
lntTable..lntEvent: begin
10008+
lntTable..lntEvent, lntColumn: begin
1000410009
try
1000510010
FActiveDbObj.Connection.Database := FActiveDbObj.Database;
1000610011
except on E:EDbError do begin
@@ -10019,21 +10024,22 @@ procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualN
1001910024
menuQueryExactRowCount.Checked := False;
1002010025
InvalidateVT(DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
1002110026
try
10022-
if FActiveDbObj.NodeType in [lntTable, lntView] then begin
10023-
SelectedTableColumns := FActiveDbObj.TableColumns;
10027+
if TableLevelObj.NodeType in [lntTable, lntView] then begin
10028+
SelectedTableColumns := TableLevelObj.TableColumns;
1002410029
try
10025-
SelectedTableKeys := FActiveDbObj.TableKeys;
10030+
SelectedTableKeys := TableLevelObj.TableKeys;
1002610031
except // No show stopper, happening when a view references a renamed table column, see #1130
1002710032
on E:EDbError do
1002810033
ErrorDialog(_('This view probably contains an error in its code.')+sLineBreak+sLineBreak+E.Message);
1002910034
end;
10030-
SelectedTableForeignKeys := FActiveDbObj.TableForeignKeys;
10035+
SelectedTableForeignKeys := TableLevelObj.TableForeignKeys;
1003110036
end;
10032-
PlaceObjectEditor(FActiveDbObj);
10037+
PlaceObjectEditor(TableLevelObj);
1003310038
// When a table is clicked in the tree, and the current
1003410039
// tab is a Host or Database tab, switch to showing table columns.
1003510040
if (PagecontrolMain.ActivePage = tabHost) or (PagecontrolMain.ActivePage = tabDatabase) then
1003610041
MainTabToActivate := tabEditor;
10042+
// Todo: prevent reload when focus has changed within a table's children only
1003710043
if DataGrid.Tag = VTREE_LOADED then
1003810044
InvalidateVT(DataGrid, VTREE_NOTLOADED_PURGECACHE, False);
1003910045
// Update the list of columns
@@ -10127,8 +10133,8 @@ procedure TMainForm.DBtreeFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualN
1012710133
if not FTreeRefreshInProgress then begin
1012810134
SetMainTab(MainTabToActivate);
1012910135
tabDatabase.TabVisible := (FActiveDbObj <> nil) and (FActiveDbObj.NodeType <> lntNone);
10130-
tabEditor.TabVisible := (FActiveDbObj <> nil) and (FActiveDbObj.NodeType in [lntTable..lntEvent]);
10131-
tabData.TabVisible := (FActiveDbObj <> nil) and (FActiveDbObj.NodeType in [lntTable, lntView]);
10136+
tabEditor.TabVisible := (FActiveDbObj <> nil) and (FActiveDbObj.NodeType in [lntTable..lntEvent, lntColumn]);
10137+
tabData.TabVisible := (FActiveDbObj <> nil) and (FActiveDbObj.NodeType in [lntTable, lntView, lntColumn]);
1013210138
end;
1013310139

1013410140
// Store click history item
@@ -10257,7 +10263,7 @@ procedure TMainForm.DBtreeDblClick(Sender: TObject);
1025710263
// Paste DB or table name into query window on treeview double click.
1025810264
if AppSettings.ReadBool(asDoubleClickInsertsNodeText) and QueryTabs.HasActiveTab and Assigned(DBtree.FocusedNode) then begin
1025910265
DBObj := DBtree.GetNodeData(DBtree.FocusedNode);
10260-
if DBObj.NodeType in [lntDb, lntTable..lntEvent] then begin
10266+
if DBObj.NodeType in [lntDb, lntTable..lntEvent, lntColumn] then begin
1026110267
m := QueryTabs.ActiveMemo;
1026210268
m.DragDrop(Sender, m.CaretX, m.CaretY);
1026310269
end;
@@ -10298,18 +10304,36 @@ procedure TMainForm.DBtreePaintText(Sender: TBaseVirtualTree; const
1029810304
TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType:
1029910305
TVSTTextType);
1030010306
var
10301-
DBObj: PDBObject;
10307+
DBObj, ParentObj: PDBObject;
1030210308
WalkNode: PVirtualNode;
10309+
Columns: TTableColumnList;
10310+
Datatype: TDBDatatype;
1030310311
begin
10304-
// Grey out non-current connection nodes, and rather unimportant "Size" column
10312+
// Grey out non-current connection nodes
1030510313
DBObj := Sender.GetNodeData(Node);
10306-
if DBObj.Connection <> ActiveConnection then
10307-
TargetCanvas.Font.Color := clGrayText
10308-
else if (Column = 1) and (DBObj.NodeType in [lntTable..lntEvent]) then
10314+
if DBObj.Connection <> ActiveConnection then begin
1030910315
TargetCanvas.Font.Color := clGrayText;
10316+
Exit;
10317+
end;
10318+
10319+
// Set text color
10320+
case Column of
10321+
0: begin
10322+
if DBObj.NodeType = lntColumn then begin
10323+
ParentObj := Sender.GetNodeData(Node.Parent);
10324+
Columns := ParentObj.TableColumns;
10325+
Datatype := Columns[Node.Index].DataType;
10326+
TargetCanvas.Font.Color := DatatypeCategories[Datatype.Category].Color;
10327+
end;
10328+
end;
10329+
1: begin // Grey out rather unimportant "Size" column
10330+
if DBObj.NodeType in [lntTable..lntEvent] then
10331+
TargetCanvas.Font.Color := clGrayText;
10332+
end;
10333+
end;
1031010334

1031110335
// Set bold text if painted node is in focused path
10312-
if (Column = Sender.Header.MainColumn) then begin
10336+
if (Column = DBtree.Header.MainColumn) then begin
1031310337
WalkNode := Sender.FocusedNode;
1031410338
while Assigned(WalkNode) do begin
1031510339
if WalkNode = Node then begin
@@ -11613,10 +11637,13 @@ procedure TMainForm.HandleDataGridAttributes(RefreshingData: Boolean);
1161311637

1161411638

1161511639
function TMainForm.GetRegKeyTable: String;
11640+
var
11641+
o: TDBObject;
1161611642
begin
1161711643
// Return the slightly complex registry path to \Servers\CustomFolder\ActiveServer\curdb|curtable
11618-
Result := ActiveDbObj.Connection.Parameters.SessionPath + '\' +
11619-
ActiveDatabase + DELIM + ActiveDbObj.Name;
11644+
o := ActiveDbObj;
11645+
Result := o.Connection.Parameters.SessionPath + '\' +
11646+
ActiveDatabase + DELIM + o.Name;
1162011647
end;
1162111648

1162211649

@@ -13963,7 +13990,7 @@ procedure TMainForm.DBtreeBeforeCellPaint(Sender: TBaseVirtualTree; TargetCanvas
1396313990
TargetCanvas.Brush.Color := DbObj.Connection.Parameters.SessionColor;
1396413991
TargetCanvas.FillRect(CellRect);
1396513992
end;
13966-
if (Column=1) and DBObj.Connection.DbObjectsCached(DBObj.Database) then begin
13993+
if (Column=1) and (DBObj.NodeType in [lntTable..lntEvent]) and DBObj.Connection.DbObjectsCached(DBObj.Database) then begin
1396713994
AllObjects := DBObj.Connection.GetDBObjects(DBObj.Database);
1396813995
PaintColorBar(DBObj.Size, AllObjects.LargestObjectSize, TargetCanvas, CellRect);
1396913996
end;
@@ -14476,13 +14503,13 @@ procedure TMainForm.treeQueryHelpersGetImageIndex(Sender: TBaseVirtualTree; Node
1447614503
TQueryTab.HelperNodeBinding: ImageIndex := 119;
1447714504
end;
1447814505
1: case Node.Parent.Index of
14479-
TQueryTab.HelperNodeColumns: ImageIndex := 42;
14506+
TQueryTab.HelperNodeColumns: ImageIndex := ICONINDEX_FIELD;
1448014507
TQueryTab.HelperNodeFunctions: ImageIndex := 13;
1448114508
TQueryTab.HelperNodeKeywords: ImageIndex := 25;
1448214509
TQueryTab.HelperNodeSnippets: ImageIndex := 68;
1448314510
TQueryTab.HelperNodeHistory: ImageIndex := 80;
1448414511
TQueryTab.HelperNodeProfile: ImageIndex := 145;
14485-
TQueryTab.HelperNodeBinding: ImageIndex := 42;
14512+
TQueryTab.HelperNodeBinding: ImageIndex := ICONINDEX_FIELD;
1448614513
end;
1448714514
end;
1448814515
end;

source/table_editor.dfm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ object frmTableEditor: TfrmTableEditor
783783
Top = 0
784784
Hint = 'Add column'
785785
Caption = 'Add'
786-
ImageIndex = 45
786+
ImageIndex = 91
787787
ImageName = 'icons8-add'
788788
OnClick = btnAddColumnClick
789789
end
@@ -792,7 +792,7 @@ object frmTableEditor: TfrmTableEditor
792792
Top = 0
793793
Hint = 'Remove column'
794794
Caption = 'Remove'
795-
ImageIndex = 46
795+
ImageIndex = 92
796796
ImageName = 'icons8-delete-button'
797797
OnClick = btnRemoveColumnClick
798798
end
@@ -1044,14 +1044,14 @@ object frmTableEditor: TfrmTableEditor
10441044
end
10451045
object menuAddColumn: TMenuItem
10461046
Caption = 'Add column'
1047-
ImageIndex = 45
1047+
ImageIndex = 91
10481048
ImageName = 'icons8-add'
10491049
ShortCut = 16429
10501050
OnClick = btnAddColumnClick
10511051
end
10521052
object menuRemoveColumn: TMenuItem
10531053
Caption = 'Remove column'
1054-
ImageIndex = 46
1054+
ImageIndex = 92
10551055
ImageName = 'icons8-delete-button'
10561056
ShortCut = 16430
10571057
OnClick = btnRemoveColumnClick

source/table_editor.pas

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2137,7 +2137,7 @@ procedure TfrmTableEditor.treeIndexesGetImageIndex(Sender: TBaseVirtualTree;
21372137
if TblKey.IsExpression(Node.Index) then
21382138
ImageIndex := 13
21392139
else
2140-
ImageIndex := 42;
2140+
ImageIndex := ICONINDEX_FIELD;
21412141
end;
21422142
end;
21432143
end;

0 commit comments

Comments
 (0)