src/eric7/Plugins/VcsPlugins/vcsGit/GitDescribeDialog.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, QProcess, Qt, QTimer, QCoreApplication 12 from PyQt6.QtCore import pyqtSlot, QProcess, Qt, QTimer, QCoreApplication
13 from PyQt6.QtWidgets import ( 13 from PyQt6.QtWidgets import (
14 QDialog, QDialogButtonBox, QHeaderView, QTreeWidgetItem, QLineEdit 14 QDialog,
15 QDialogButtonBox,
16 QHeaderView,
17 QTreeWidgetItem,
18 QLineEdit,
15 ) 19 )
16 20
17 from EricWidgets import EricMessageBox 21 from EricWidgets import EricMessageBox
18 22
19 from .Ui_GitDescribeDialog import Ui_GitDescribeDialog 23 from .Ui_GitDescribeDialog import Ui_GitDescribeDialog
24 28
25 class GitDescribeDialog(QDialog, Ui_GitDescribeDialog): 29 class GitDescribeDialog(QDialog, Ui_GitDescribeDialog):
26 """ 30 """
27 Class implementing a dialog to show the results of the git describe action. 31 Class implementing a dialog to show the results of the git describe action.
28 """ 32 """
33
29 def __init__(self, vcs, parent=None): 34 def __init__(self, vcs, parent=None):
30 """ 35 """
31 Constructor 36 Constructor
32 37
33 @param vcs reference to the vcs object 38 @param vcs reference to the vcs object
34 @param parent reference to the parent widget (QWidget) 39 @param parent reference to the parent widget (QWidget)
35 """ 40 """
36 super().__init__(parent) 41 super().__init__(parent)
37 self.setupUi(self) 42 self.setupUi(self)
38 self.setWindowFlags(Qt.WindowType.Window) 43 self.setWindowFlags(Qt.WindowType.Window)
39 44
40 self.buttonBox.button( 45 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
41 QDialogButtonBox.StandardButton.Close).setEnabled(False) 46 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
42 self.buttonBox.button( 47
43 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
44
45 self.process = QProcess() 48 self.process = QProcess()
46 self.vcs = vcs 49 self.vcs = vcs
47 50
48 self.tagList.headerItem().setText(self.tagList.columnCount(), "") 51 self.tagList.headerItem().setText(self.tagList.columnCount(), "")
49 self.tagList.header().setSortIndicator(1, Qt.SortOrder.AscendingOrder) 52 self.tagList.header().setSortIndicator(1, Qt.SortOrder.AscendingOrder)
50 53
51 self.process.finished.connect(self.__procFinished) 54 self.process.finished.connect(self.__procFinished)
52 self.process.readyReadStandardOutput.connect(self.__readStdout) 55 self.process.readyReadStandardOutput.connect(self.__readStdout)
53 self.process.readyReadStandardError.connect(self.__readStderr) 56 self.process.readyReadStandardError.connect(self.__readStderr)
54 57
55 self.show() 58 self.show()
56 QCoreApplication.processEvents() 59 QCoreApplication.processEvents()
57 60
58 def closeEvent(self, e): 61 def closeEvent(self, e):
59 """ 62 """
60 Protected slot implementing a close event handler. 63 Protected slot implementing a close event handler.
61 64
62 @param e close event (QCloseEvent) 65 @param e close event (QCloseEvent)
63 """ 66 """
64 if ( 67 if (
65 self.process is not None and 68 self.process is not None
66 self.process.state() != QProcess.ProcessState.NotRunning 69 and self.process.state() != QProcess.ProcessState.NotRunning
67 ): 70 ):
68 self.process.terminate() 71 self.process.terminate()
69 QTimer.singleShot(2000, self.process.kill) 72 QTimer.singleShot(2000, self.process.kill)
70 self.process.waitForFinished(3000) 73 self.process.waitForFinished(3000)
71 74
72 e.accept() 75 e.accept()
73 76
74 def start(self, path, commits): 77 def start(self, path, commits):
75 """ 78 """
76 Public slot to start the tag/branch list command. 79 Public slot to start the tag/branch list command.
77 80
78 @param path name of directory to be listed (string) 81 @param path name of directory to be listed (string)
79 @param commits list of commits to be described (list of string) 82 @param commits list of commits to be described (list of string)
80 """ 83 """
81 self.tagList.clear() 84 self.tagList.clear()
82 self.errorGroup.hide() 85 self.errorGroup.hide()
83 86
84 self.intercept = False 87 self.intercept = False
85 self.activateWindow() 88 self.activateWindow()
86 89
87 self.__commits = commits[:] 90 self.__commits = commits[:]
88 self.__tagInfoLines = [] 91 self.__tagInfoLines = []
89 92
90 dname, fname = self.vcs.splitPath(path) 93 dname, fname = self.vcs.splitPath(path)
91 94
92 # find the root of the repo 95 # find the root of the repo
93 self.repodir = dname 96 self.repodir = dname
94 while not os.path.isdir(os.path.join(self.repodir, self.vcs.adminDir)): 97 while not os.path.isdir(os.path.join(self.repodir, self.vcs.adminDir)):
95 self.repodir = os.path.dirname(self.repodir) 98 self.repodir = os.path.dirname(self.repodir)
96 if os.path.splitdrive(self.repodir)[1] == os.sep: 99 if os.path.splitdrive(self.repodir)[1] == os.sep:
97 return 100 return
98 101
99 args = self.vcs.initCommand("describe") 102 args = self.vcs.initCommand("describe")
100 args.append('--abbrev={0}'.format( 103 args.append(
101 self.vcs.getPlugin().getPreferences("CommitIdLength"))) 104 "--abbrev={0}".format(self.vcs.getPlugin().getPreferences("CommitIdLength"))
105 )
102 if commits: 106 if commits:
103 args.extend(commits) 107 args.extend(commits)
104 else: 108 else:
105 args.append('--dirty') 109 args.append("--dirty")
106 110
107 self.process.kill() 111 self.process.kill()
108 self.process.setWorkingDirectory(self.repodir) 112 self.process.setWorkingDirectory(self.repodir)
109 113
110 self.process.start('git', args) 114 self.process.start("git", args)
111 procStarted = self.process.waitForStarted(5000) 115 procStarted = self.process.waitForStarted(5000)
112 if not procStarted: 116 if not procStarted:
113 self.inputGroup.setEnabled(False) 117 self.inputGroup.setEnabled(False)
114 self.inputGroup.hide() 118 self.inputGroup.hide()
115 EricMessageBox.critical( 119 EricMessageBox.critical(
116 self, 120 self,
117 self.tr('Process Generation Error'), 121 self.tr("Process Generation Error"),
118 self.tr( 122 self.tr(
119 'The process {0} could not be started. ' 123 "The process {0} could not be started. "
120 'Ensure, that it is in the search path.' 124 "Ensure, that it is in the search path."
121 ).format('git')) 125 ).format("git"),
126 )
122 else: 127 else:
123 self.inputGroup.setEnabled(True) 128 self.inputGroup.setEnabled(True)
124 self.inputGroup.show() 129 self.inputGroup.show()
125 130
126 def __finish(self): 131 def __finish(self):
127 """ 132 """
128 Private slot called when the process finished or the user pressed 133 Private slot called when the process finished or the user pressed
129 the button. 134 the button.
130 """ 135 """
131 if ( 136 if (
132 self.process is not None and 137 self.process is not None
133 self.process.state() != QProcess.ProcessState.NotRunning 138 and self.process.state() != QProcess.ProcessState.NotRunning
134 ): 139 ):
135 self.process.terminate() 140 self.process.terminate()
136 QTimer.singleShot(2000, self.process.kill) 141 QTimer.singleShot(2000, self.process.kill)
137 self.process.waitForFinished(3000) 142 self.process.waitForFinished(3000)
138 143
139 self.inputGroup.setEnabled(False) 144 self.inputGroup.setEnabled(False)
140 self.inputGroup.hide() 145 self.inputGroup.hide()
141 146
142 self.buttonBox.button( 147 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
143 QDialogButtonBox.StandardButton.Close).setEnabled(True) 148 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
144 self.buttonBox.button( 149 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True)
145 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) 150 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setFocus(
146 self.buttonBox.button( 151 Qt.FocusReason.OtherFocusReason
147 QDialogButtonBox.StandardButton.Close).setDefault(True) 152 )
148 self.buttonBox.button( 153
149 QDialogButtonBox.StandardButton.Close).setFocus(
150 Qt.FocusReason.OtherFocusReason)
151
152 self.__resizeColumns() 154 self.__resizeColumns()
153 self.__resort() 155 self.__resort()
154 156
155 def on_buttonBox_clicked(self, button): 157 def on_buttonBox_clicked(self, button):
156 """ 158 """
157 Private slot called by a button of the button box clicked. 159 Private slot called by a button of the button box clicked.
158 160
159 @param button button that was clicked (QAbstractButton) 161 @param button button that was clicked (QAbstractButton)
160 """ 162 """
161 if button == self.buttonBox.button( 163 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
162 QDialogButtonBox.StandardButton.Close
163 ):
164 self.close() 164 self.close()
165 elif button == self.buttonBox.button( 165 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
166 QDialogButtonBox.StandardButton.Cancel
167 ):
168 self.__finish() 166 self.__finish()
169 167
170 def __procFinished(self, exitCode, exitStatus): 168 def __procFinished(self, exitCode, exitStatus):
171 """ 169 """
172 Private slot connected to the finished signal. 170 Private slot connected to the finished signal.
173 171
174 @param exitCode exit code of the process (integer) 172 @param exitCode exit code of the process (integer)
175 @param exitStatus exit status of the process (QProcess.ExitStatus) 173 @param exitStatus exit status of the process (QProcess.ExitStatus)
176 """ 174 """
177 if self.__tagInfoLines: 175 if self.__tagInfoLines:
178 if self.__commits: 176 if self.__commits:
179 for commit, tagInfo in zip(self.__commits, 177 for commit, tagInfo in zip(self.__commits, self.__tagInfoLines):
180 self.__tagInfoLines):
181 QTreeWidgetItem(self.tagList, [commit, tagInfo]) 178 QTreeWidgetItem(self.tagList, [commit, tagInfo])
182 else: 179 else:
183 for tagInfo in self.__tagInfoLines: 180 for tagInfo in self.__tagInfoLines:
184 QTreeWidgetItem(self.tagList, ["", tagInfo]) 181 QTreeWidgetItem(self.tagList, ["", tagInfo])
185 182
186 self.__finish() 183 self.__finish()
187 184
188 def __resort(self): 185 def __resort(self):
189 """ 186 """
190 Private method to resort the tree. 187 Private method to resort the tree.
191 """ 188 """
192 self.tagList.sortItems( 189 self.tagList.sortItems(
193 self.tagList.sortColumn(), 190 self.tagList.sortColumn(), self.tagList.header().sortIndicatorOrder()
194 self.tagList.header().sortIndicatorOrder()) 191 )
195 192
196 def __resizeColumns(self): 193 def __resizeColumns(self):
197 """ 194 """
198 Private method to resize the list columns. 195 Private method to resize the list columns.
199 """ 196 """
200 self.tagList.header().resizeSections( 197 self.tagList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
201 QHeaderView.ResizeMode.ResizeToContents)
202 self.tagList.header().setStretchLastSection(True) 198 self.tagList.header().setStretchLastSection(True)
203 199
204 def __readStdout(self): 200 def __readStdout(self):
205 """ 201 """
206 Private slot to handle the readyReadStdout signal. 202 Private slot to handle the readyReadStdout signal.
207 203
208 It reads the output of the process, formats it and inserts it into 204 It reads the output of the process, formats it and inserts it into
209 the contents pane. 205 the contents pane.
210 """ 206 """
211 self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput) 207 self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput)
212 208
213 while self.process.canReadLine(): 209 while self.process.canReadLine():
214 s = str(self.process.readLine(), 210 s = str(
215 Preferences.getSystem("IOEncoding"), 211 self.process.readLine(), Preferences.getSystem("IOEncoding"), "replace"
216 'replace') 212 )
217 self.__tagInfoLines.append(s.strip()) 213 self.__tagInfoLines.append(s.strip())
218 214
219 def __readStderr(self): 215 def __readStderr(self):
220 """ 216 """
221 Private slot to handle the readyReadStderr signal. 217 Private slot to handle the readyReadStderr signal.
222 218
223 It reads the error output of the process and inserts it into the 219 It reads the error output of the process and inserts it into the
224 error pane. 220 error pane.
225 """ 221 """
226 if self.process is not None: 222 if self.process is not None:
227 s = str(self.process.readAllStandardError(), 223 s = str(
228 Preferences.getSystem("IOEncoding"), 224 self.process.readAllStandardError(),
229 'replace') 225 Preferences.getSystem("IOEncoding"),
226 "replace",
227 )
230 self.errorGroup.show() 228 self.errorGroup.show()
231 self.errors.insertPlainText(s) 229 self.errors.insertPlainText(s)
232 self.errors.ensureCursorVisible() 230 self.errors.ensureCursorVisible()
233 231
234 def on_passwordCheckBox_toggled(self, isOn): 232 def on_passwordCheckBox_toggled(self, isOn):
235 """ 233 """
236 Private slot to handle the password checkbox toggled. 234 Private slot to handle the password checkbox toggled.
237 235
238 @param isOn flag indicating the status of the check box (boolean) 236 @param isOn flag indicating the status of the check box (boolean)
239 """ 237 """
240 if isOn: 238 if isOn:
241 self.input.setEchoMode(QLineEdit.EchoMode.Password) 239 self.input.setEchoMode(QLineEdit.EchoMode.Password)
242 else: 240 else:
243 self.input.setEchoMode(QLineEdit.EchoMode.Normal) 241 self.input.setEchoMode(QLineEdit.EchoMode.Normal)
244 242
245 @pyqtSlot() 243 @pyqtSlot()
246 def on_sendButton_clicked(self): 244 def on_sendButton_clicked(self):
247 """ 245 """
248 Private slot to send the input to the git process. 246 Private slot to send the input to the git process.
249 """ 247 """
250 inputTxt = self.input.text() 248 inputTxt = self.input.text()
251 inputTxt += os.linesep 249 inputTxt += os.linesep
252 250
253 if self.passwordCheckBox.isChecked(): 251 if self.passwordCheckBox.isChecked():
254 self.errors.insertPlainText(os.linesep) 252 self.errors.insertPlainText(os.linesep)
255 self.errors.ensureCursorVisible() 253 self.errors.ensureCursorVisible()
256 else: 254 else:
257 self.errors.insertPlainText(inputTxt) 255 self.errors.insertPlainText(inputTxt)
258 self.errors.ensureCursorVisible() 256 self.errors.ensureCursorVisible()
259 257
260 self.process.write(strToQByteArray(inputTxt)) 258 self.process.write(strToQByteArray(inputTxt))
261 259
262 self.passwordCheckBox.setChecked(False) 260 self.passwordCheckBox.setChecked(False)
263 self.input.clear() 261 self.input.clear()
264 262
265 def on_input_returnPressed(self): 263 def on_input_returnPressed(self):
266 """ 264 """
267 Private slot to handle the press of the return key in the input field. 265 Private slot to handle the press of the return key in the input field.
268 """ 266 """
269 self.intercept = True 267 self.intercept = True
270 self.on_sendButton_clicked() 268 self.on_sendButton_clicked()
271 269
272 def keyPressEvent(self, evt): 270 def keyPressEvent(self, evt):
273 """ 271 """
274 Protected slot to handle a key press event. 272 Protected slot to handle a key press event.
275 273
276 @param evt the key press event (QKeyEvent) 274 @param evt the key press event (QKeyEvent)
277 """ 275 """
278 if self.intercept: 276 if self.intercept:
279 self.intercept = False 277 self.intercept = False
280 evt.accept() 278 evt.accept()
281 return 279 return
282 280
283 super().keyPressEvent(evt) 281 super().keyPressEvent(evt)

eric ide

mercurial