26 |
32 |
27 class GitStashBrowserDialog(QWidget, Ui_GitStashBrowserDialog): |
33 class GitStashBrowserDialog(QWidget, Ui_GitStashBrowserDialog): |
28 """ |
34 """ |
29 Class implementing a dialog to show the stashes. |
35 Class implementing a dialog to show the stashes. |
30 """ |
36 """ |
|
37 |
31 NameColumn = 0 |
38 NameColumn = 0 |
32 DateColumn = 1 |
39 DateColumn = 1 |
33 MessageColumn = 2 |
40 MessageColumn = 2 |
34 |
41 |
35 Separator = "@@||@@" |
42 Separator = "@@||@@" |
36 |
43 |
37 TotalStatisticsRole = Qt.ItemDataRole.UserRole |
44 TotalStatisticsRole = Qt.ItemDataRole.UserRole |
38 FileStatisticsRole = Qt.ItemDataRole.UserRole + 1 |
45 FileStatisticsRole = Qt.ItemDataRole.UserRole + 1 |
39 |
46 |
40 def __init__(self, vcs, parent=None): |
47 def __init__(self, vcs, parent=None): |
41 """ |
48 """ |
42 Constructor |
49 Constructor |
43 |
50 |
44 @param vcs reference to the vcs object |
51 @param vcs reference to the vcs object |
45 @param parent reference to the parent widget (QWidget) |
52 @param parent reference to the parent widget (QWidget) |
46 """ |
53 """ |
47 super().__init__(parent) |
54 super().__init__(parent) |
48 self.setupUi(self) |
55 self.setupUi(self) |
49 |
56 |
50 self.buttonBox.button( |
57 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
51 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
58 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
52 self.buttonBox.button( |
59 |
53 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
|
54 |
|
55 self.__position = QPoint() |
60 self.__position = QPoint() |
56 |
61 |
57 self.__fileStatisticsRole = Qt.ItemDataRole.UserRole |
62 self.__fileStatisticsRole = Qt.ItemDataRole.UserRole |
58 self.__totalStatisticsRole = Qt.ItemDataRole.UserRole + 1 |
63 self.__totalStatisticsRole = Qt.ItemDataRole.UserRole + 1 |
59 |
64 |
60 self.stashList.header().setSortIndicator( |
65 self.stashList.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder) |
61 0, Qt.SortOrder.AscendingOrder) |
66 |
62 |
|
63 self.refreshButton = self.buttonBox.addButton( |
67 self.refreshButton = self.buttonBox.addButton( |
64 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole) |
68 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole |
65 self.refreshButton.setToolTip( |
69 ) |
66 self.tr("Press to refresh the list of stashes")) |
70 self.refreshButton.setToolTip(self.tr("Press to refresh the list of stashes")) |
67 self.refreshButton.setEnabled(False) |
71 self.refreshButton.setEnabled(False) |
68 |
72 |
69 self.vcs = vcs |
73 self.vcs = vcs |
70 self.__resetUI() |
74 self.__resetUI() |
71 |
75 |
72 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
76 self.__ioEncoding = Preferences.getSystem("IOEncoding") |
73 |
77 |
74 self.__process = EricOverrideCursorProcess() |
78 self.__process = EricOverrideCursorProcess() |
75 self.__process.finished.connect(self.__procFinished) |
79 self.__process.finished.connect(self.__procFinished) |
76 self.__process.readyReadStandardOutput.connect(self.__readStdout) |
80 self.__process.readyReadStandardOutput.connect(self.__readStdout) |
77 self.__process.readyReadStandardError.connect(self.__readStderr) |
81 self.__process.readyReadStandardError.connect(self.__readStderr) |
78 |
82 |
79 self.__contextMenu = QMenu() |
83 self.__contextMenu = QMenu() |
80 self.__differencesAct = self.__contextMenu.addAction( |
84 self.__differencesAct = self.__contextMenu.addAction( |
81 self.tr("Show"), self.__showPatch) |
85 self.tr("Show"), self.__showPatch |
|
86 ) |
82 self.__contextMenu.addSeparator() |
87 self.__contextMenu.addSeparator() |
83 self.__applyAct = self.__contextMenu.addAction( |
88 self.__applyAct = self.__contextMenu.addAction( |
84 self.tr("Restore && Keep"), self.__apply) |
89 self.tr("Restore && Keep"), self.__apply |
|
90 ) |
85 self.__popAct = self.__contextMenu.addAction( |
91 self.__popAct = self.__contextMenu.addAction( |
86 self.tr("Restore && Delete"), self.__pop) |
92 self.tr("Restore && Delete"), self.__pop |
|
93 ) |
87 self.__contextMenu.addSeparator() |
94 self.__contextMenu.addSeparator() |
88 self.__branchAct = self.__contextMenu.addAction( |
95 self.__branchAct = self.__contextMenu.addAction( |
89 self.tr("Create Branch"), self.__branch) |
96 self.tr("Create Branch"), self.__branch |
|
97 ) |
90 self.__contextMenu.addSeparator() |
98 self.__contextMenu.addSeparator() |
91 self.__dropAct = self.__contextMenu.addAction( |
99 self.__dropAct = self.__contextMenu.addAction(self.tr("Delete"), self.__drop) |
92 self.tr("Delete"), self.__drop) |
|
93 self.__clearAct = self.__contextMenu.addAction( |
100 self.__clearAct = self.__contextMenu.addAction( |
94 self.tr("Delete All"), self.__clear) |
101 self.tr("Delete All"), self.__clear |
95 |
102 ) |
|
103 |
96 def closeEvent(self, e): |
104 def closeEvent(self, e): |
97 """ |
105 """ |
98 Protected slot implementing a close event handler. |
106 Protected slot implementing a close event handler. |
99 |
107 |
100 @param e close event (QCloseEvent) |
108 @param e close event (QCloseEvent) |
101 """ |
109 """ |
102 if ( |
110 if ( |
103 self.__process is not None and |
111 self.__process is not None |
104 self.__process.state() != QProcess.ProcessState.NotRunning |
112 and self.__process.state() != QProcess.ProcessState.NotRunning |
105 ): |
113 ): |
106 self.__process.terminate() |
114 self.__process.terminate() |
107 QTimer.singleShot(2000, self.__process.kill) |
115 QTimer.singleShot(2000, self.__process.kill) |
108 self.__process.waitForFinished(3000) |
116 self.__process.waitForFinished(3000) |
109 |
117 |
110 self.__position = self.pos() |
118 self.__position = self.pos() |
111 |
119 |
112 e.accept() |
120 e.accept() |
113 |
121 |
114 def show(self): |
122 def show(self): |
115 """ |
123 """ |
116 Public slot to show the dialog. |
124 Public slot to show the dialog. |
117 """ |
125 """ |
118 if not self.__position.isNull(): |
126 if not self.__position.isNull(): |
119 self.move(self.__position) |
127 self.move(self.__position) |
120 self.__resetUI() |
128 self.__resetUI() |
121 |
129 |
122 super().show() |
130 super().show() |
123 |
131 |
124 def __resetUI(self): |
132 def __resetUI(self): |
125 """ |
133 """ |
126 Private method to reset the user interface. |
134 Private method to reset the user interface. |
127 """ |
135 """ |
128 self.stashList.clear() |
136 self.stashList.clear() |
129 |
137 |
130 def __resizeColumnsStashes(self): |
138 def __resizeColumnsStashes(self): |
131 """ |
139 """ |
132 Private method to resize the shelve list columns. |
140 Private method to resize the shelve list columns. |
133 """ |
141 """ |
134 self.stashList.header().resizeSections( |
142 self.stashList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents) |
135 QHeaderView.ResizeMode.ResizeToContents) |
|
136 self.stashList.header().setStretchLastSection(True) |
143 self.stashList.header().setStretchLastSection(True) |
137 |
144 |
138 def __generateStashEntry(self, name, date, message): |
145 def __generateStashEntry(self, name, date, message): |
139 """ |
146 """ |
140 Private method to generate the stash items. |
147 Private method to generate the stash items. |
141 |
148 |
142 @param name name of the stash (string) |
149 @param name name of the stash (string) |
143 @param date date the stash was created (string) |
150 @param date date the stash was created (string) |
144 @param message stash message (string) |
151 @param message stash message (string) |
145 """ |
152 """ |
146 QTreeWidgetItem(self.stashList, [name, date, message]) |
153 QTreeWidgetItem(self.stashList, [name, date, message]) |
147 |
154 |
148 def __getStashEntries(self): |
155 def __getStashEntries(self): |
149 """ |
156 """ |
150 Private method to retrieve the list of stashes. |
157 Private method to retrieve the list of stashes. |
151 """ |
158 """ |
152 self.buttonBox.button( |
159 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False) |
153 QDialogButtonBox.StandardButton.Close).setEnabled(False) |
160 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
154 self.buttonBox.button( |
161 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
155 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) |
162 |
156 self.buttonBox.button( |
|
157 QDialogButtonBox.StandardButton.Cancel).setDefault(True) |
|
158 |
|
159 self.inputGroup.setEnabled(True) |
163 self.inputGroup.setEnabled(True) |
160 self.inputGroup.show() |
164 self.inputGroup.show() |
161 self.refreshButton.setEnabled(False) |
165 self.refreshButton.setEnabled(False) |
162 |
166 |
163 self.buf = [] |
167 self.buf = [] |
164 self.errors.clear() |
168 self.errors.clear() |
165 self.intercept = False |
169 self.intercept = False |
166 |
170 |
167 args = self.vcs.initCommand("stash") |
171 args = self.vcs.initCommand("stash") |
168 args.append("list") |
172 args.append("list") |
169 args.append("--format=format:%gd{0}%ai{0}%gs%n".format(self.Separator)) |
173 args.append("--format=format:%gd{0}%ai{0}%gs%n".format(self.Separator)) |
170 |
174 |
171 self.__process.kill() |
175 self.__process.kill() |
172 |
176 |
173 self.__process.setWorkingDirectory(self.repodir) |
177 self.__process.setWorkingDirectory(self.repodir) |
174 |
178 |
175 self.inputGroup.setEnabled(True) |
179 self.inputGroup.setEnabled(True) |
176 self.inputGroup.show() |
180 self.inputGroup.show() |
177 |
181 |
178 self.__process.start('git', args) |
182 self.__process.start("git", args) |
179 procStarted = self.__process.waitForStarted(5000) |
183 procStarted = self.__process.waitForStarted(5000) |
180 if not procStarted: |
184 if not procStarted: |
181 self.inputGroup.setEnabled(False) |
185 self.inputGroup.setEnabled(False) |
182 self.inputGroup.hide() |
186 self.inputGroup.hide() |
183 EricMessageBox.critical( |
187 EricMessageBox.critical( |
184 self, |
188 self, |
185 self.tr('Process Generation Error'), |
189 self.tr("Process Generation Error"), |
186 self.tr( |
190 self.tr( |
187 'The process {0} could not be started. ' |
191 "The process {0} could not be started. " |
188 'Ensure, that it is in the search path.' |
192 "Ensure, that it is in the search path." |
189 ).format('git')) |
193 ).format("git"), |
190 |
194 ) |
|
195 |
191 def start(self, projectDir): |
196 def start(self, projectDir): |
192 """ |
197 """ |
193 Public slot to start the git stash command. |
198 Public slot to start the git stash command. |
194 |
199 |
195 @param projectDir name of the project directory (string) |
200 @param projectDir name of the project directory (string) |
196 """ |
201 """ |
197 self.errorGroup.hide() |
202 self.errorGroup.hide() |
198 QApplication.processEvents() |
203 QApplication.processEvents() |
199 |
204 |
200 self.__projectDir = projectDir |
205 self.__projectDir = projectDir |
201 |
206 |
202 # find the root of the repo |
207 # find the root of the repo |
203 self.repodir = self.__projectDir |
208 self.repodir = self.__projectDir |
204 while not os.path.isdir(os.path.join(self.repodir, self.vcs.adminDir)): |
209 while not os.path.isdir(os.path.join(self.repodir, self.vcs.adminDir)): |
205 self.repodir = os.path.dirname(self.repodir) |
210 self.repodir = os.path.dirname(self.repodir) |
206 if os.path.splitdrive(self.repodir)[1] == os.sep: |
211 if os.path.splitdrive(self.repodir)[1] == os.sep: |
207 return |
212 return |
208 |
213 |
209 self.activateWindow() |
214 self.activateWindow() |
210 self.raise_() |
215 self.raise_() |
211 |
216 |
212 self.stashList.clear() |
217 self.stashList.clear() |
213 self.__started = True |
218 self.__started = True |
214 self.__getStashEntries() |
219 self.__getStashEntries() |
215 |
220 |
216 def __procFinished(self, exitCode, exitStatus): |
221 def __procFinished(self, exitCode, exitStatus): |
217 """ |
222 """ |
218 Private slot connected to the finished signal. |
223 Private slot connected to the finished signal. |
219 |
224 |
220 @param exitCode exit code of the process (integer) |
225 @param exitCode exit code of the process (integer) |
221 @param exitStatus exit status of the process (QProcess.ExitStatus) |
226 @param exitStatus exit status of the process (QProcess.ExitStatus) |
222 """ |
227 """ |
223 self.__processBuffer() |
228 self.__processBuffer() |
224 self.__finish() |
229 self.__finish() |
225 |
230 |
226 def __finish(self): |
231 def __finish(self): |
227 """ |
232 """ |
228 Private slot called when the process finished or the user pressed |
233 Private slot called when the process finished or the user pressed |
229 the button. |
234 the button. |
230 """ |
235 """ |
231 if ( |
236 if ( |
232 self.__process is not None and |
237 self.__process is not None |
233 self.__process.state() != QProcess.ProcessState.NotRunning |
238 and self.__process.state() != QProcess.ProcessState.NotRunning |
234 ): |
239 ): |
235 self.__process.terminate() |
240 self.__process.terminate() |
236 QTimer.singleShot(2000, self.__process.kill) |
241 QTimer.singleShot(2000, self.__process.kill) |
237 self.__process.waitForFinished(3000) |
242 self.__process.waitForFinished(3000) |
238 |
243 |
239 self.buttonBox.button( |
244 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True) |
240 QDialogButtonBox.StandardButton.Close).setEnabled(True) |
245 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
241 self.buttonBox.button( |
246 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True) |
242 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) |
247 |
243 self.buttonBox.button( |
|
244 QDialogButtonBox.StandardButton.Close).setDefault(True) |
|
245 |
|
246 self.inputGroup.setEnabled(False) |
248 self.inputGroup.setEnabled(False) |
247 self.inputGroup.hide() |
249 self.inputGroup.hide() |
248 self.refreshButton.setEnabled(True) |
250 self.refreshButton.setEnabled(True) |
249 |
251 |
250 def __processBuffer(self): |
252 def __processBuffer(self): |
251 """ |
253 """ |
252 Private method to process the buffered output of the git stash command. |
254 Private method to process the buffered output of the git stash command. |
253 """ |
255 """ |
254 for line in self.buf: |
256 for line in self.buf: |
255 name, date, message = line.split(self.Separator) |
257 name, date, message = line.split(self.Separator) |
256 date = date.strip().rsplit(":", 1)[0] |
258 date = date.strip().rsplit(":", 1)[0] |
257 self.__generateStashEntry(name, date, message.strip()) |
259 self.__generateStashEntry(name, date, message.strip()) |
258 |
260 |
259 self.__resizeColumnsStashes() |
261 self.__resizeColumnsStashes() |
260 |
262 |
261 if self.__started: |
263 if self.__started: |
262 self.stashList.setCurrentItem(self.stashList.topLevelItem(0)) |
264 self.stashList.setCurrentItem(self.stashList.topLevelItem(0)) |
263 self.__started = False |
265 self.__started = False |
264 |
266 |
265 def __readStdout(self): |
267 def __readStdout(self): |
266 """ |
268 """ |
267 Private slot to handle the readyReadStandardOutput signal. |
269 Private slot to handle the readyReadStandardOutput signal. |
268 |
270 |
269 It reads the output of the process and inserts it into a buffer. |
271 It reads the output of the process and inserts it into a buffer. |
270 """ |
272 """ |
271 self.__process.setReadChannel(QProcess.ProcessChannel.StandardOutput) |
273 self.__process.setReadChannel(QProcess.ProcessChannel.StandardOutput) |
272 |
274 |
273 while self.__process.canReadLine(): |
275 while self.__process.canReadLine(): |
274 line = str(self.__process.readLine(), self.__ioEncoding, |
276 line = str(self.__process.readLine(), self.__ioEncoding, "replace").strip() |
275 'replace').strip() |
|
276 if line: |
277 if line: |
277 self.buf.append(line) |
278 self.buf.append(line) |
278 |
279 |
279 def __readStderr(self): |
280 def __readStderr(self): |
280 """ |
281 """ |
281 Private slot to handle the readyReadStandardError signal. |
282 Private slot to handle the readyReadStandardError signal. |
282 |
283 |
283 It reads the error output of the process and inserts it into the |
284 It reads the error output of the process and inserts it into the |
284 error pane. |
285 error pane. |
285 """ |
286 """ |
286 if self.__process is not None: |
287 if self.__process is not None: |
287 s = str(self.__process.readAllStandardError(), |
288 s = str(self.__process.readAllStandardError(), self.__ioEncoding, "replace") |
288 self.__ioEncoding, 'replace') |
|
289 self.errorGroup.show() |
289 self.errorGroup.show() |
290 self.errors.insertPlainText(s) |
290 self.errors.insertPlainText(s) |
291 self.errors.ensureCursorVisible() |
291 self.errors.ensureCursorVisible() |
292 |
292 |
293 @pyqtSlot(QAbstractButton) |
293 @pyqtSlot(QAbstractButton) |
294 def on_buttonBox_clicked(self, button): |
294 def on_buttonBox_clicked(self, button): |
295 """ |
295 """ |
296 Private slot called by a button of the button box clicked. |
296 Private slot called by a button of the button box clicked. |
297 |
297 |
298 @param button button that was clicked (QAbstractButton) |
298 @param button button that was clicked (QAbstractButton) |
299 """ |
299 """ |
300 if button == self.buttonBox.button( |
300 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close): |
301 QDialogButtonBox.StandardButton.Close |
|
302 ): |
|
303 self.close() |
301 self.close() |
304 elif button == self.buttonBox.button( |
302 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel): |
305 QDialogButtonBox.StandardButton.Cancel |
|
306 ): |
|
307 self.cancelled = True |
303 self.cancelled = True |
308 self.__finish() |
304 self.__finish() |
309 elif button == self.refreshButton: |
305 elif button == self.refreshButton: |
310 self.on_refreshButton_clicked() |
306 self.on_refreshButton_clicked() |
311 |
307 |
312 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
308 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
313 def on_stashList_currentItemChanged(self, current, previous): |
309 def on_stashList_currentItemChanged(self, current, previous): |
314 """ |
310 """ |
315 Private slot called, when the current item of the stash list changes. |
311 Private slot called, when the current item of the stash list changes. |
316 |
312 |
317 @param current reference to the new current item (QTreeWidgetItem) |
313 @param current reference to the new current item (QTreeWidgetItem) |
318 @param previous reference to the old current item (QTreeWidgetItem) |
314 @param previous reference to the old current item (QTreeWidgetItem) |
319 """ |
315 """ |
320 self.statisticsList.clear() |
316 self.statisticsList.clear() |
321 self.filesLabel.setText("") |
317 self.filesLabel.setText("") |
322 self.insertionsLabel.setText("") |
318 self.insertionsLabel.setText("") |
323 self.deletionsLabel.setText("") |
319 self.deletionsLabel.setText("") |
324 |
320 |
325 if current: |
321 if current: |
326 if current.data(0, self.TotalStatisticsRole) is None: |
322 if current.data(0, self.TotalStatisticsRole) is None: |
327 args = self.vcs.initCommand("stash") |
323 args = self.vcs.initCommand("stash") |
328 args.append("show") |
324 args.append("show") |
329 args.append('--numstat') |
325 args.append("--numstat") |
330 args.append(current.text(self.NameColumn)) |
326 args.append(current.text(self.NameColumn)) |
331 |
327 |
332 output = "" |
328 output = "" |
333 process = QProcess() |
329 process = QProcess() |
334 process.setWorkingDirectory(self.repodir) |
330 process.setWorkingDirectory(self.repodir) |
335 process.start('git', args) |
331 process.start("git", args) |
336 procStarted = process.waitForStarted(5000) |
332 procStarted = process.waitForStarted(5000) |
337 if procStarted: |
333 if procStarted: |
338 finished = process.waitForFinished(30000) |
334 finished = process.waitForFinished(30000) |
339 if finished and process.exitCode() == 0: |
335 if finished and process.exitCode() == 0: |
340 output = str(process.readAllStandardOutput(), |
336 output = str( |
341 Preferences.getSystem("IOEncoding"), |
337 process.readAllStandardOutput(), |
342 'replace') |
338 Preferences.getSystem("IOEncoding"), |
343 |
339 "replace", |
|
340 ) |
|
341 |
344 if output: |
342 if output: |
345 totals = {"files": 0, "additions": 0, "deletions": 0} |
343 totals = {"files": 0, "additions": 0, "deletions": 0} |
346 fileData = [] |
344 fileData = [] |
347 for line in output.splitlines(): |
345 for line in output.splitlines(): |
348 additions, deletions, name = ( |
346 additions, deletions, name = line.strip().split(None, 2) |
349 line.strip().split(None, 2) |
|
350 ) |
|
351 totals["files"] += 1 |
347 totals["files"] += 1 |
352 if additions != "-": |
348 if additions != "-": |
353 totals["additions"] += int(additions) |
349 totals["additions"] += int(additions) |
354 if deletions != "-": |
350 if deletions != "-": |
355 totals["deletions"] += int(deletions) |
351 totals["deletions"] += int(deletions) |
356 fileData.append({ |
352 fileData.append( |
357 "file": name, |
353 { |
358 "total": ("-" if additions == "-" else |
354 "file": name, |
359 str(int(additions) + int(deletions))), |
355 "total": ( |
360 "added": additions, |
356 "-" |
361 "deleted": deletions |
357 if additions == "-" |
362 }) |
358 else str(int(additions) + int(deletions)) |
|
359 ), |
|
360 "added": additions, |
|
361 "deleted": deletions, |
|
362 } |
|
363 ) |
363 current.setData(0, self.TotalStatisticsRole, totals) |
364 current.setData(0, self.TotalStatisticsRole, totals) |
364 current.setData(0, self.FileStatisticsRole, fileData) |
365 current.setData(0, self.FileStatisticsRole, fileData) |
365 else: |
366 else: |
366 return |
367 return |
367 |
368 |
368 for dataDict in current.data(0, self.FileStatisticsRole): |
369 for dataDict in current.data(0, self.FileStatisticsRole): |
369 QTreeWidgetItem(self.statisticsList, [ |
370 QTreeWidgetItem( |
370 dataDict["file"], dataDict["total"], |
371 self.statisticsList, |
371 dataDict["added"], dataDict["deleted"]]) |
372 [ |
|
373 dataDict["file"], |
|
374 dataDict["total"], |
|
375 dataDict["added"], |
|
376 dataDict["deleted"], |
|
377 ], |
|
378 ) |
372 self.statisticsList.header().resizeSections( |
379 self.statisticsList.header().resizeSections( |
373 QHeaderView.ResizeMode.ResizeToContents) |
380 QHeaderView.ResizeMode.ResizeToContents |
|
381 ) |
374 self.statisticsList.header().setStretchLastSection(True) |
382 self.statisticsList.header().setStretchLastSection(True) |
375 |
383 |
376 totals = current.data(0, self.TotalStatisticsRole) |
384 totals = current.data(0, self.TotalStatisticsRole) |
377 self.filesLabel.setText( |
385 self.filesLabel.setText( |
378 self.tr("%n file(s) changed", None, totals["files"])) |
386 self.tr("%n file(s) changed", None, totals["files"]) |
|
387 ) |
379 self.insertionsLabel.setText( |
388 self.insertionsLabel.setText( |
380 self.tr("%n line(s) inserted", None, int(totals["additions"]))) |
389 self.tr("%n line(s) inserted", None, int(totals["additions"])) |
|
390 ) |
381 self.deletionsLabel.setText( |
391 self.deletionsLabel.setText( |
382 self.tr("%n line(s) deleted", None, int(totals["deletions"]))) |
392 self.tr("%n line(s) deleted", None, int(totals["deletions"])) |
383 |
393 ) |
|
394 |
384 @pyqtSlot(QPoint) |
395 @pyqtSlot(QPoint) |
385 def on_stashList_customContextMenuRequested(self, pos): |
396 def on_stashList_customContextMenuRequested(self, pos): |
386 """ |
397 """ |
387 Private slot to show the context menu of the stash list. |
398 Private slot to show the context menu of the stash list. |
388 |
399 |
389 @param pos position of the mouse pointer (QPoint) |
400 @param pos position of the mouse pointer (QPoint) |
390 """ |
401 """ |
391 enable = len(self.stashList.selectedItems()) == 1 |
402 enable = len(self.stashList.selectedItems()) == 1 |
392 self.__differencesAct.setEnabled(enable) |
403 self.__differencesAct.setEnabled(enable) |
393 self.__applyAct.setEnabled(enable) |
404 self.__applyAct.setEnabled(enable) |
394 self.__popAct.setEnabled(enable) |
405 self.__popAct.setEnabled(enable) |
395 self.__branchAct.setEnabled(enable) |
406 self.__branchAct.setEnabled(enable) |
396 self.__dropAct.setEnabled(enable) |
407 self.__dropAct.setEnabled(enable) |
397 self.__clearAct.setEnabled(self.stashList.topLevelItemCount() > 0) |
408 self.__clearAct.setEnabled(self.stashList.topLevelItemCount() > 0) |
398 |
409 |
399 self.__contextMenu.popup(self.mapToGlobal(pos)) |
410 self.__contextMenu.popup(self.mapToGlobal(pos)) |
400 |
411 |
401 @pyqtSlot() |
412 @pyqtSlot() |
402 def on_refreshButton_clicked(self): |
413 def on_refreshButton_clicked(self): |
403 """ |
414 """ |
404 Private slot to refresh the list of shelves. |
415 Private slot to refresh the list of shelves. |
405 """ |
416 """ |
406 self.start(self.__projectDir) |
417 self.start(self.__projectDir) |
407 |
418 |
408 @pyqtSlot() |
419 @pyqtSlot() |
409 def on_sendButton_clicked(self): |
420 def on_sendButton_clicked(self): |
410 """ |
421 """ |
411 Private slot to send the input to the git process. |
422 Private slot to send the input to the git process. |
412 """ |
423 """ |
413 inputTxt = self.input.text() |
424 inputTxt = self.input.text() |
414 inputTxt += os.linesep |
425 inputTxt += os.linesep |
415 |
426 |
416 if self.passwordCheckBox.isChecked(): |
427 if self.passwordCheckBox.isChecked(): |
417 self.errors.insertPlainText(os.linesep) |
428 self.errors.insertPlainText(os.linesep) |
418 self.errors.ensureCursorVisible() |
429 self.errors.ensureCursorVisible() |
419 else: |
430 else: |
420 self.errors.insertPlainText(inputTxt) |
431 self.errors.insertPlainText(inputTxt) |
421 self.errors.ensureCursorVisible() |
432 self.errors.ensureCursorVisible() |
422 self.errorGroup.show() |
433 self.errorGroup.show() |
423 |
434 |
424 self.__process.write(strToQByteArray(inputTxt)) |
435 self.__process.write(strToQByteArray(inputTxt)) |
425 |
436 |
426 self.passwordCheckBox.setChecked(False) |
437 self.passwordCheckBox.setChecked(False) |
427 self.input.clear() |
438 self.input.clear() |
428 |
439 |
429 @pyqtSlot() |
440 @pyqtSlot() |
430 def on_input_returnPressed(self): |
441 def on_input_returnPressed(self): |
431 """ |
442 """ |
432 Private slot to handle the press of the return key in the input field. |
443 Private slot to handle the press of the return key in the input field. |
433 """ |
444 """ |
434 self.intercept = True |
445 self.intercept = True |
435 self.on_sendButton_clicked() |
446 self.on_sendButton_clicked() |
436 |
447 |
437 @pyqtSlot(bool) |
448 @pyqtSlot(bool) |
438 def on_passwordCheckBox_toggled(self, checked): |
449 def on_passwordCheckBox_toggled(self, checked): |
439 """ |
450 """ |
440 Private slot to handle the password checkbox toggled. |
451 Private slot to handle the password checkbox toggled. |
441 |
452 |
442 @param checked flag indicating the status of the check box (boolean) |
453 @param checked flag indicating the status of the check box (boolean) |
443 """ |
454 """ |
444 if checked: |
455 if checked: |
445 self.input.setEchoMode(QLineEdit.EchoMode.Password) |
456 self.input.setEchoMode(QLineEdit.EchoMode.Password) |
446 else: |
457 else: |
447 self.input.setEchoMode(QLineEdit.EchoMode.Normal) |
458 self.input.setEchoMode(QLineEdit.EchoMode.Normal) |
448 |
459 |
449 def keyPressEvent(self, evt): |
460 def keyPressEvent(self, evt): |
450 """ |
461 """ |
451 Protected slot to handle a key press event. |
462 Protected slot to handle a key press event. |
452 |
463 |
453 @param evt the key press event (QKeyEvent) |
464 @param evt the key press event (QKeyEvent) |
454 """ |
465 """ |
455 if self.intercept: |
466 if self.intercept: |
456 self.intercept = False |
467 self.intercept = False |
457 evt.accept() |
468 evt.accept() |
458 return |
469 return |
459 super().keyPressEvent(evt) |
470 super().keyPressEvent(evt) |
460 |
471 |
461 def __showPatch(self): |
472 def __showPatch(self): |
462 """ |
473 """ |
463 Private slot to show the contents of the selected stash. |
474 Private slot to show the contents of the selected stash. |
464 """ |
475 """ |
465 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
476 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
466 self.vcs.gitStashShowPatch(self.__projectDir, stashName) |
477 self.vcs.gitStashShowPatch(self.__projectDir, stashName) |
467 |
478 |
468 def __apply(self): |
479 def __apply(self): |
469 """ |
480 """ |
470 Private slot to apply the selected stash but keep it. |
481 Private slot to apply the selected stash but keep it. |
471 """ |
482 """ |
472 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
483 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
473 self.vcs.gitStashApply(self.__projectDir, stashName) |
484 self.vcs.gitStashApply(self.__projectDir, stashName) |
474 |
485 |
475 def __pop(self): |
486 def __pop(self): |
476 """ |
487 """ |
477 Private slot to apply the selected stash and delete it. |
488 Private slot to apply the selected stash and delete it. |
478 """ |
489 """ |
479 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
490 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
480 self.vcs.gitStashPop(self.__projectDir, stashName) |
491 self.vcs.gitStashPop(self.__projectDir, stashName) |
481 self.on_refreshButton_clicked() |
492 self.on_refreshButton_clicked() |
482 |
493 |
483 def __branch(self): |
494 def __branch(self): |
484 """ |
495 """ |
485 Private slot to create a branch from the selected stash. |
496 Private slot to create a branch from the selected stash. |
486 """ |
497 """ |
487 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
498 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
488 self.vcs.gitStashBranch(self.__projectDir, stashName) |
499 self.vcs.gitStashBranch(self.__projectDir, stashName) |
489 self.on_refreshButton_clicked() |
500 self.on_refreshButton_clicked() |
490 |
501 |
491 def __drop(self): |
502 def __drop(self): |
492 """ |
503 """ |
493 Private slot to delete the selected stash. |
504 Private slot to delete the selected stash. |
494 """ |
505 """ |
495 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
506 stashName = self.stashList.selectedItems()[0].text(self.NameColumn) |
496 res = self.vcs.gitStashDrop(self.__projectDir, stashName) |
507 res = self.vcs.gitStashDrop(self.__projectDir, stashName) |
497 if res: |
508 if res: |
498 self.on_refreshButton_clicked() |
509 self.on_refreshButton_clicked() |
499 |
510 |
500 def __clear(self): |
511 def __clear(self): |
501 """ |
512 """ |
502 Private slot to delete all stashes. |
513 Private slot to delete all stashes. |
503 """ |
514 """ |
504 res = self.vcs.gitStashClear(self.__projectDir) |
515 res = self.vcs.gitStashClear(self.__projectDir) |