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