37 @param parent reference to the parent widget |
41 @param parent reference to the parent widget |
38 @type QWidget |
42 @type QWidget |
39 """ |
43 """ |
40 super().__init__(parent) |
44 super().__init__(parent) |
41 self.setupUi(self) |
45 self.setupUi(self) |
42 |
46 |
43 self.__refreshButton = self.buttonBox.addButton( |
47 self.__refreshButton = self.buttonBox.addButton( |
44 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole) |
48 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole |
|
49 ) |
45 self.__refreshButton.clicked.connect(self.showSummary) |
50 self.__refreshButton.clicked.connect(self.showSummary) |
46 |
51 |
47 self.__project = project |
52 self.__project = project |
48 self.__migrateProject = migrateProject |
53 self.__migrateProject = migrateProject |
49 self.__migrations = migrations |
54 self.__migrations = migrations |
50 |
55 |
51 self.__process = None |
56 self.__process = None |
52 self.__currentItemIndex = 1000000 |
57 self.__currentItemIndex = 1000000 |
53 self.__currentRevision = "" |
58 self.__currentRevision = "" |
54 |
59 |
55 def showSummary(self): |
60 def showSummary(self): |
56 """ |
61 """ |
57 Public method to show the migrations summary. |
62 Public method to show the migrations summary. |
58 """ |
63 """ |
59 workdir, env = self.__project.prepareRuntimeEnvironment() |
64 workdir, env = self.__project.prepareRuntimeEnvironment() |
60 if env is not None: |
65 if env is not None: |
61 self.show() |
66 self.show() |
62 self.raise_() |
67 self.raise_() |
63 |
68 |
64 self.buttonBox.button( |
69 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( |
65 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
70 False |
66 self.buttonBox.button( |
71 ) |
67 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
72 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault( |
68 self.buttonBox.button( |
73 True |
69 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
74 ) |
70 self.buttonBox.button( |
75 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled( |
71 QDialogButtonBox.StandardButton.Cancel).setFocus( |
76 True |
72 Qt.FocusReason.OtherFocusReason) |
77 ) |
|
78 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setFocus( |
|
79 Qt.FocusReason.OtherFocusReason |
|
80 ) |
73 QGuiApplication.processEvents( |
81 QGuiApplication.processEvents( |
74 QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents) |
82 QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents |
75 |
83 ) |
|
84 |
76 command = self.__project.getFlaskCommand() |
85 command = self.__project.getFlaskCommand() |
77 |
86 |
78 self.__process = QProcess() |
87 self.__process = QProcess() |
79 self.__process.setProcessEnvironment(env) |
88 self.__process.setProcessEnvironment(env) |
80 self.__process.setWorkingDirectory(workdir) |
89 self.__process.setWorkingDirectory(workdir) |
81 |
90 |
82 args = ["db", "history", "--indicate-current"] |
91 args = ["db", "history", "--indicate-current"] |
83 if self.__migrations: |
92 if self.__migrations: |
84 args += ["--directory", self.__migrations] |
93 args += ["--directory", self.__migrations] |
85 |
94 |
86 with EricOverrideCursor(): |
95 with EricOverrideCursor(): |
87 self.__process.start(command, args) |
96 self.__process.start(command, args) |
88 ok = self.__process.waitForStarted(10000) |
97 ok = self.__process.waitForStarted(10000) |
89 if ok: |
98 if ok: |
90 ok = self.__process.waitForFinished(10000) |
99 ok = self.__process.waitForFinished(10000) |
91 if ok: |
100 if ok: |
92 out = str(self.__process.readAllStandardOutput(), |
101 out = str(self.__process.readAllStandardOutput(), "utf-8") |
93 "utf-8") |
|
94 self.__processOutput(out) |
102 self.__processOutput(out) |
95 self.__selectItem(self.__currentRevision) |
103 self.__selectItem(self.__currentRevision) |
96 else: |
104 else: |
97 with EricOverridenCursor(): |
105 with EricOverridenCursor(): |
98 EricMessageBox.critical( |
106 EricMessageBox.critical( |
99 None, |
107 None, |
100 self.tr("Migrations Summary"), |
108 self.tr("Migrations Summary"), |
101 self.tr("""The Flask process did not finish""" |
109 self.tr( |
102 """ within 10 seconds.""")) |
110 """The Flask process did not finish""" |
|
111 """ within 10 seconds.""" |
|
112 ), |
|
113 ) |
103 else: |
114 else: |
104 with EricOverridenCursor(): |
115 with EricOverridenCursor(): |
105 EricMessageBox.critical( |
116 EricMessageBox.critical( |
106 None, |
117 None, |
107 self.tr("Migrations Summary"), |
118 self.tr("Migrations Summary"), |
108 self.tr("""The Flask process could not be""" |
119 self.tr( |
109 """ started.""")) |
120 """The Flask process could not be""" """ started.""" |
|
121 ), |
|
122 ) |
110 for column in range(self.summaryWidget.columnCount()): |
123 for column in range(self.summaryWidget.columnCount()): |
111 self.summaryWidget.resizeColumnToContents(column) |
124 self.summaryWidget.resizeColumnToContents(column) |
112 |
125 |
113 self.buttonBox.button( |
126 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled( |
114 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
127 False |
115 self.buttonBox.button( |
128 ) |
116 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
129 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled( |
117 self.buttonBox.button( |
130 True |
118 QDialogButtonBox.StandardButton.Close).setDefault(True) |
131 ) |
119 self.buttonBox.button( |
132 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault( |
120 QDialogButtonBox.StandardButton.Close).setFocus( |
133 True |
121 Qt.FocusReason.OtherFocusReason) |
134 ) |
122 |
135 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setFocus( |
|
136 Qt.FocusReason.OtherFocusReason |
|
137 ) |
|
138 |
123 def __processOutput(self, output): |
139 def __processOutput(self, output): |
124 """ |
140 """ |
125 Private method to process the flask output and populate the summary |
141 Private method to process the flask output and populate the summary |
126 list. |
142 list. |
127 |
143 |
128 @param output output of the flask process |
144 @param output output of the flask process |
129 @type str |
145 @type str |
130 """ |
146 """ |
131 self.summaryWidget.clear() |
147 self.summaryWidget.clear() |
132 self.upDownButton.setEnabled(False) |
148 self.upDownButton.setEnabled(False) |
133 self.__currentItemIndex = 1000000 |
149 self.__currentItemIndex = 1000000 |
134 self.__currentRevision = "" |
150 self.__currentRevision = "" |
135 |
151 |
136 lines = output.splitlines() |
152 lines = output.splitlines() |
137 for line in lines: |
153 for line in lines: |
138 isCurrent = False |
154 isCurrent = False |
139 oldRev, rest = line.split("->") |
155 oldRev, rest = line.split("->") |
140 rest, message = rest.split(",", 1) |
156 rest, message = rest.split(",", 1) |
141 newRev, *labels = rest.split() |
157 newRev, *labels = rest.split() |
142 if labels: |
158 if labels: |
143 labelList = [ |
159 labelList = [ |
144 label.replace("(", "").replace(")", "") |
160 label.replace("(", "").replace(")", "") for label in labels |
145 for label in labels |
|
146 ] |
161 ] |
147 labelsStr = ", ".join(labelList) |
162 labelsStr = ", ".join(labelList) |
148 if "current" in labelList: |
163 if "current" in labelList: |
149 isCurrent = True |
164 isCurrent = True |
150 else: |
165 else: |
151 labelsStr = "" |
166 labelsStr = "" |
152 |
167 |
153 itm = QTreeWidgetItem(self.summaryWidget, [ |
168 itm = QTreeWidgetItem( |
154 oldRev.strip(), |
169 self.summaryWidget, |
155 newRev.strip(), |
170 [ |
156 message.strip(), |
171 oldRev.strip(), |
157 labelsStr, |
172 newRev.strip(), |
158 ]) |
173 message.strip(), |
|
174 labelsStr, |
|
175 ], |
|
176 ) |
159 if isCurrent: |
177 if isCurrent: |
160 font = itm.font(0) |
178 font = itm.font(0) |
161 font.setBold(True) |
179 font.setBold(True) |
162 for column in range(self.summaryWidget.columnCount()): |
180 for column in range(self.summaryWidget.columnCount()): |
163 itm.setFont(column, font) |
181 itm.setFont(column, font) |
164 |
182 |
165 self.__currentItemIndex = ( |
183 self.__currentItemIndex = self.summaryWidget.indexOfTopLevelItem(itm) |
166 self.summaryWidget.indexOfTopLevelItem(itm) |
|
167 ) |
|
168 self.__currentRevision = newRev.strip() |
184 self.__currentRevision = newRev.strip() |
169 |
185 |
170 @pyqtSlot() |
186 @pyqtSlot() |
171 def on_summaryWidget_itemSelectionChanged(self): |
187 def on_summaryWidget_itemSelectionChanged(self): |
172 """ |
188 """ |
173 Private slot to handle the selection of an entry. |
189 Private slot to handle the selection of an entry. |
174 """ |
190 """ |
193 if self.upDownButton.text() == self.tr("Upgrade"): |
209 if self.upDownButton.text() == self.tr("Upgrade"): |
194 self.__migrateProject.upgradeDatabase(revision=rev) |
210 self.__migrateProject.upgradeDatabase(revision=rev) |
195 else: |
211 else: |
196 self.__migrateProject.downgradeDatabase(revision=rev) |
212 self.__migrateProject.downgradeDatabase(revision=rev) |
197 self.showSummary() |
213 self.showSummary() |
198 |
214 |
199 @pyqtSlot(QAbstractButton) |
215 @pyqtSlot(QAbstractButton) |
200 def on_buttonBox_clicked(self, button): |
216 def on_buttonBox_clicked(self, button): |
201 """ |
217 """ |
202 Private slot handling a button press of the button box. |
218 Private slot handling a button press of the button box. |
203 |
219 |
204 @param button reference to the pressed button |
220 @param button reference to the pressed button |
205 @type QAbstractButton |
221 @type QAbstractButton |
206 """ |
222 """ |
207 if button is self.buttonBox.button( |
223 if button is self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
208 QDialogButtonBox.StandardButton.Cancel |
|
209 ): |
|
210 self.__cancelProcess() |
224 self.__cancelProcess() |
211 |
225 |
212 @pyqtSlot() |
226 @pyqtSlot() |
213 def __cancelProcess(self): |
227 def __cancelProcess(self): |
214 """ |
228 """ |
215 Private slot to terminate the current process. |
229 Private slot to terminate the current process. |
216 """ |
230 """ |
217 if ( |
231 if ( |
218 self.__process is not None and |
232 self.__process is not None |
219 self.__process.state() != QProcess.ProcessState.NotRunning |
233 and self.__process.state() != QProcess.ProcessState.NotRunning |
220 ): |
234 ): |
221 self.__process.terminate() |
235 self.__process.terminate() |
222 QTimer.singleShot(2000, self.__process.kill) |
236 QTimer.singleShot(2000, self.__process.kill) |
223 self.__process.waitForFinished(3000) |
237 self.__process.waitForFinished(3000) |
224 |
238 |
225 self.__process = None |
239 self.__process = None |
226 |
240 |
227 def __selectItem(self, revision): |
241 def __selectItem(self, revision): |
228 """ |
242 """ |
229 Private method to select an item given its revision. |
243 Private method to select an item given its revision. |
230 |
244 |
231 @param revision revision of the item to select |
245 @param revision revision of the item to select |
232 @type str |
246 @type str |
233 """ |
247 """ |
234 if revision: |
248 if revision: |
235 items = self.summaryWidget.findItems( |
249 items = self.summaryWidget.findItems(revision, Qt.MatchFlag.MatchExactly, 1) |
236 revision, Qt.MatchFlag.MatchExactly, 1) |
|
237 if items: |
250 if items: |
238 # select the first item |
251 # select the first item |
239 items[0].setSelected(True) |
252 items[0].setSelected(True) |
240 self.summaryWidget.scrollToItem( |
253 self.summaryWidget.scrollToItem( |
241 items[0], QAbstractItemView.ScrollHint.PositionAtCenter) |
254 items[0], QAbstractItemView.ScrollHint.PositionAtCenter |
|
255 ) |