src/eric7/Plugins/VcsPlugins/vcsGit/GitStashBrowserDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
9 9
10 import os 10 import os
11 11
12 from PyQt6.QtCore import pyqtSlot, Qt, QPoint, QProcess, QTimer 12 from PyQt6.QtCore import pyqtSlot, Qt, QPoint, QProcess, QTimer
13 from PyQt6.QtWidgets import ( 13 from PyQt6.QtWidgets import (
14 QWidget, QDialogButtonBox, QTreeWidgetItem, QAbstractButton, QMenu, 14 QWidget,
15 QHeaderView, QApplication, QLineEdit 15 QDialogButtonBox,
16 QTreeWidgetItem,
17 QAbstractButton,
18 QMenu,
19 QHeaderView,
20 QApplication,
21 QLineEdit,
16 ) 22 )
17 23
18 from EricWidgets import EricMessageBox 24 from EricWidgets import EricMessageBox
19 from EricGui.EricOverrideCursor import EricOverrideCursorProcess 25 from EricGui.EricOverrideCursor import EricOverrideCursorProcess
20 26
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)

eric ide

mercurial