|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a widget showing the SQL connections. |
|
8 """ |
|
9 |
|
10 from PyQt6.QtCore import pyqtSignal, Qt |
|
11 from PyQt6.QtGui import QAction |
|
12 from PyQt6.QtWidgets import ( |
|
13 QWidget, QHeaderView, QTreeWidget, QVBoxLayout, QTreeWidgetItem |
|
14 ) |
|
15 from PyQt6.QtSql import QSqlDatabase |
|
16 |
|
17 |
|
18 class SqlConnectionWidget(QWidget): |
|
19 """ |
|
20 Class implementing a widget showing the SQL connections. |
|
21 |
|
22 @signal tableActivated(str) emitted after the entry for a table has been |
|
23 activated |
|
24 @signal schemaRequested(str) emitted when the schema display is requested |
|
25 @signal cleared() emitted after the connection tree has been cleared |
|
26 """ |
|
27 tableActivated = pyqtSignal(str) |
|
28 schemaRequested = pyqtSignal(str) |
|
29 cleared = pyqtSignal() |
|
30 |
|
31 def __init__(self, parent=None): |
|
32 """ |
|
33 Constructor |
|
34 |
|
35 @param parent reference to the parent widget (QWidget) |
|
36 """ |
|
37 super().__init__(parent) |
|
38 |
|
39 layout = QVBoxLayout(self) |
|
40 layout.setContentsMargins(0, 0, 0, 0) |
|
41 |
|
42 self.__connectionTree = QTreeWidget(self) |
|
43 self.__connectionTree.setObjectName("connectionTree") |
|
44 self.__connectionTree.setHeaderLabels([self.tr("Database")]) |
|
45 self.__connectionTree.header().setSectionResizeMode( |
|
46 QHeaderView.ResizeMode.Stretch) |
|
47 refreshAction = QAction(self.tr("Refresh"), self.__connectionTree) |
|
48 self.__schemaAction = QAction( |
|
49 self.tr("Show Schema"), self.__connectionTree) |
|
50 |
|
51 refreshAction.triggered.connect(self.refresh) |
|
52 self.__schemaAction.triggered.connect(self.showSchema) |
|
53 |
|
54 self.__connectionTree.addAction(refreshAction) |
|
55 self.__connectionTree.addAction(self.__schemaAction) |
|
56 self.__connectionTree.setContextMenuPolicy( |
|
57 Qt.ContextMenuPolicy.ActionsContextMenu) |
|
58 |
|
59 layout.addWidget(self.__connectionTree) |
|
60 |
|
61 self.__activating = False |
|
62 |
|
63 self.__connectionTree.itemActivated.connect(self.__itemActivated) |
|
64 self.__connectionTree.currentItemChanged.connect( |
|
65 self.__currentItemChanged) |
|
66 |
|
67 self.__activeDb = "" |
|
68 |
|
69 def refresh(self): |
|
70 """ |
|
71 Public slot to refresh the connection tree. |
|
72 """ |
|
73 self.__connectionTree.clear() |
|
74 self.cleared.emit() |
|
75 |
|
76 connectionNames = QSqlDatabase.connectionNames() |
|
77 |
|
78 foundActiveDb = False |
|
79 for name in connectionNames: |
|
80 root = QTreeWidgetItem(self.__connectionTree) |
|
81 db = QSqlDatabase.database(name, False) |
|
82 root.setText(0, self.__dbCaption(db)) |
|
83 if name == self.__activeDb: |
|
84 foundActiveDb = True |
|
85 self.__setActive(root) |
|
86 if db.isOpen(): |
|
87 tables = db.tables() |
|
88 for table in tables: |
|
89 itm = QTreeWidgetItem(root) |
|
90 itm.setText(0, table) |
|
91 |
|
92 if not foundActiveDb and connectionNames: |
|
93 self.__activeDb = connectionNames[0] |
|
94 self.__setActive(self.__connectionTree.topLevelItem(0)) |
|
95 |
|
96 def showSchema(self): |
|
97 """ |
|
98 Public slot to show schema data of a database. |
|
99 """ |
|
100 cItm = self.__connectionTree.currentItem() |
|
101 if cItm is None or cItm.parent() is None: |
|
102 return |
|
103 self.__setActive(cItm.parent()) |
|
104 self.schemaRequested.emit(cItm.text(0)) |
|
105 |
|
106 def __itemActivated(self, itm, column): |
|
107 """ |
|
108 Private slot handling the activation of an item. |
|
109 |
|
110 @param itm reference to the item (QTreeWidgetItem) |
|
111 @param column column that was activated (integer) |
|
112 """ |
|
113 if itm is None: |
|
114 return |
|
115 |
|
116 if not self.__activating: |
|
117 self.__activating = True |
|
118 if itm.parent() is None: |
|
119 self.__setActive(itm) |
|
120 else: |
|
121 self.__setActive(itm.parent()) |
|
122 self.tableActivated.emit(itm.text(0)) |
|
123 self.__activating = False |
|
124 |
|
125 def __currentItemChanged(self, current, previous): |
|
126 """ |
|
127 Private slot handling a change of the current item. |
|
128 |
|
129 @param current reference to the new current item (QTreeWidgetItem) |
|
130 @param previous reference to the previous current item |
|
131 (QTreeWidgetItem) |
|
132 """ |
|
133 self.__schemaAction.setEnabled( |
|
134 current is not None and current.parent() is not None) |
|
135 |
|
136 def __dbCaption(self, db): |
|
137 """ |
|
138 Private method to assemble a string for the caption. |
|
139 |
|
140 @param db reference to the database object (QSqlDatabase) |
|
141 @return caption string (string) |
|
142 """ |
|
143 nm = db.driverName() |
|
144 nm += ":" |
|
145 if db.userName(): |
|
146 nm += db.userName() |
|
147 nm += "@" |
|
148 nm += db.databaseName() |
|
149 return nm |
|
150 |
|
151 def __setBold(self, itm, bold): |
|
152 """ |
|
153 Private slot to set the font to bold. |
|
154 |
|
155 @param itm reference to the item to be changed (QTreeWidgetItem) |
|
156 @param bold flag indicating bold (boolean) |
|
157 """ |
|
158 font = itm.font(0) |
|
159 font.setBold(bold) |
|
160 itm.setFont(0, font) |
|
161 |
|
162 def currentDatabase(self): |
|
163 """ |
|
164 Public method to get the current database. |
|
165 |
|
166 @return reference to the current database (QSqlDatabase) |
|
167 """ |
|
168 return QSqlDatabase.database(self.__activeDb) |
|
169 |
|
170 def __setActive(self, itm): |
|
171 """ |
|
172 Private slot to set an item to active. |
|
173 |
|
174 @param itm reference to the item to set as the active item |
|
175 (QTreeWidgetItem) |
|
176 """ |
|
177 for index in range(self.__connectionTree.topLevelItemCount()): |
|
178 if self.__connectionTree.topLevelItem(index).font(0).bold(): |
|
179 self.__setBold( |
|
180 self.__connectionTree.topLevelItem(index), False) |
|
181 |
|
182 if itm is None: |
|
183 return |
|
184 |
|
185 self.__setBold(itm, True) |
|
186 self.__activeDb = QSqlDatabase.connectionNames()[ |
|
187 self.__connectionTree.indexOfTopLevelItem(itm)] |