src/eric7/Plugins/VcsPlugins/vcsMercurial/HgSummaryDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9653
e67609152c5e
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
17 class HgSummaryDialog(QDialog, Ui_HgSummaryDialog): 17 class HgSummaryDialog(QDialog, Ui_HgSummaryDialog):
18 """ 18 """
19 Class implementing a dialog to show some summary information of the working 19 Class implementing a dialog to show some summary information of the working
20 directory state. 20 directory state.
21 """ 21 """
22
22 def __init__(self, vcs, parent=None): 23 def __init__(self, vcs, parent=None):
23 """ 24 """
24 Constructor 25 Constructor
25 26
26 @param vcs reference to the vcs object 27 @param vcs reference to the vcs object
27 @param parent parent widget (QWidget) 28 @param parent parent widget (QWidget)
28 """ 29 """
29 super().__init__(parent) 30 super().__init__(parent)
30 self.setupUi(self) 31 self.setupUi(self)
31 32
32 self.refreshButton = self.buttonBox.addButton( 33 self.refreshButton = self.buttonBox.addButton(
33 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole) 34 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole
34 self.refreshButton.setToolTip( 35 )
35 self.tr("Press to refresh the summary display")) 36 self.refreshButton.setToolTip(self.tr("Press to refresh the summary display"))
36 self.refreshButton.setEnabled(False) 37 self.refreshButton.setEnabled(False)
37 38
38 self.vcs = vcs 39 self.vcs = vcs
39 self.vcs.committed.connect(self.__committed) 40 self.vcs.committed.connect(self.__committed)
40 41
41 def start(self, mq=False, largefiles=False): 42 def start(self, mq=False, largefiles=False):
42 """ 43 """
43 Public slot to start the hg summary command. 44 Public slot to start the hg summary command.
44 45
45 @param mq flag indicating to show the queue status as well (boolean) 46 @param mq flag indicating to show the queue status as well (boolean)
46 @param largefiles flag indicating to show the largefiles status as 47 @param largefiles flag indicating to show the largefiles status as
47 well (boolean) 48 well (boolean)
48 """ 49 """
49 self.errorGroup.hide() 50 self.errorGroup.hide()
50 self.refreshButton.setEnabled(False) 51 self.refreshButton.setEnabled(False)
51 self.summary.clear() 52 self.summary.clear()
52 53
53 self.__mq = mq 54 self.__mq = mq
54 self.__largefiles = largefiles 55 self.__largefiles = largefiles
55 56
56 args = self.vcs.initCommand("summary") 57 args = self.vcs.initCommand("summary")
57 if self.vcs.canPull(): 58 if self.vcs.canPull():
58 args.append("--remote") 59 args.append("--remote")
59 if self.__mq: 60 if self.__mq:
60 args.append("--mq") 61 args.append("--mq")
61 if self.__largefiles: 62 if self.__largefiles:
62 args.append("--large") 63 args.append("--large")
63 64
64 client = self.vcs.getClient() 65 client = self.vcs.getClient()
65 output, error = client.runcommand(args) 66 output, error = client.runcommand(args)
66 if error: 67 if error:
67 self.__showError(error) 68 self.__showError(error)
68 else: 69 else:
69 self.__processOutput(output.splitlines()) 70 self.__processOutput(output.splitlines())
70 71
71 self.refreshButton.setEnabled(True) 72 self.refreshButton.setEnabled(True)
72 73
73 def on_buttonBox_clicked(self, button): 74 def on_buttonBox_clicked(self, button):
74 """ 75 """
75 Private slot called by a button of the button box clicked. 76 Private slot called by a button of the button box clicked.
76 77
77 @param button button that was clicked (QAbstractButton) 78 @param button button that was clicked (QAbstractButton)
78 """ 79 """
79 if button == self.buttonBox.button( 80 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
80 QDialogButtonBox.StandardButton.Close
81 ):
82 self.close() 81 self.close()
83 elif button == self.refreshButton: 82 elif button == self.refreshButton:
84 self.on_refreshButton_clicked() 83 self.on_refreshButton_clicked()
85 84
86 @pyqtSlot() 85 @pyqtSlot()
87 def on_refreshButton_clicked(self): 86 def on_refreshButton_clicked(self):
88 """ 87 """
89 Private slot to refresh the status display. 88 Private slot to refresh the status display.
90 """ 89 """
91 self.start(mq=self.__mq) 90 self.start(mq=self.__mq)
92 91
93 def __committed(self): 92 def __committed(self):
94 """ 93 """
95 Private slot called after the commit has finished. 94 Private slot called after the commit has finished.
96 """ 95 """
97 if self.isVisible(): 96 if self.isVisible():
98 self.on_refreshButton_clicked() 97 self.on_refreshButton_clicked()
99 98
100 def __showError(self, out): 99 def __showError(self, out):
101 """ 100 """
102 Private slot to show some error. 101 Private slot to show some error.
103 102
104 @param out error to be shown (string) 103 @param out error to be shown (string)
105 """ 104 """
106 self.errorGroup.show() 105 self.errorGroup.show()
107 self.errors.insertPlainText(out) 106 self.errors.insertPlainText(out)
108 self.errors.ensureCursorVisible() 107 self.errors.ensureCursorVisible()
109 108
110 def __processOutput(self, output): 109 def __processOutput(self, output):
111 """ 110 """
112 Private method to process the output into nice readable text. 111 Private method to process the output into nice readable text.
113 112
114 @param output output from the summary command (string) 113 @param output output from the summary command (string)
115 """ 114 """
116 infoDict = {} 115 infoDict = {}
117 116
118 # step 1: parse the output 117 # step 1: parse the output
119 while output: 118 while output:
120 line = output.pop(0) 119 line = output.pop(0)
121 if ':' not in line: 120 if ":" not in line:
122 continue 121 continue
123 name, value = line.split(": ", 1) 122 name, value = line.split(": ", 1)
124 value = value.strip() 123 value = value.strip()
125 124
126 if name == "parent": 125 if name == "parent":
127 if " " in value: 126 if " " in value:
128 parent, tags = value.split(" ", 1) 127 parent, tags = value.split(" ", 1)
129 else: 128 else:
130 parent = value 129 parent = value
131 tags = "" 130 tags = ""
132 rev, node = parent.split(":") 131 rev, node = parent.split(":")
133 132
134 remarks = [] 133 remarks = []
135 if tags: 134 if tags:
136 if " (empty repository)" in tags: 135 if " (empty repository)" in tags:
137 remarks.append("@EMPTY@") 136 remarks.append("@EMPTY@")
138 tags = tags.replace(" (empty repository)", "") 137 tags = tags.replace(" (empty repository)", "")
139 if " (no revision checked out)" in tags: 138 if " (no revision checked out)" in tags:
140 remarks.append("@NO_REVISION@") 139 remarks.append("@NO_REVISION@")
141 tags = tags.replace(" (no revision checked out)", "") 140 tags = tags.replace(" (no revision checked out)", "")
142 else: 141 else:
143 tags = None 142 tags = None
144 143
145 value = infoDict.get(name, []) 144 value = infoDict.get(name, [])
146 145
147 if rev == "-1": 146 if rev == "-1":
148 value.append((int(rev), node, tags, None, remarks)) 147 value.append((int(rev), node, tags, None, remarks))
149 else: 148 else:
150 message = output.pop(0).strip() 149 message = output.pop(0).strip()
151 value.append((int(rev), node, tags, message, remarks)) 150 value.append((int(rev), node, tags, message, remarks))
174 value = ("@CURRENT@", 0, 0) 173 value = ("@CURRENT@", 0, 0)
175 elif value.endswith("(update)"): 174 elif value.endswith("(update)"):
176 value = ("@UPDATE@", int(value.split(" ", 1)[0]), 0) 175 value = ("@UPDATE@", int(value.split(" ", 1)[0]), 0)
177 elif value.endswith("(merge)"): 176 elif value.endswith("(merge)"):
178 parts = value.split(", ") 177 parts = value.split(", ")
179 value = ("@MERGE@", int(parts[0].split(" ", 1)[0]), 178 value = (
180 int(parts[1].split(" ", 1)[0])) 179 "@MERGE@",
180 int(parts[0].split(" ", 1)[0]),
181 int(parts[1].split(" ", 1)[0]),
182 )
181 else: 183 else:
182 value = ("@UNKNOWN@", 0, 0) 184 value = ("@UNKNOWN@", 0, 0)
183 elif name == "remote": 185 elif name == "remote":
184 if value == "(synced)": 186 if value == "(synced)":
185 value = (0, 0, 0, 0) 187 value = (0, 0, 0, 0)
214 else: 216 else:
215 value = int(value.split(None, 1)[0]) 217 value = int(value.split(None, 1)[0])
216 else: 218 else:
217 # ignore unknown entries 219 # ignore unknown entries
218 continue 220 continue
219 221
220 infoDict[name] = value 222 infoDict[name] = value
221 223
222 # step 2: build the output 224 # step 2: build the output
223 if infoDict: 225 if infoDict:
224 info = ["<table>"] 226 info = ["<table>"]
225 for pindex, (rev, node, tags, message, remarks) in enumerate( 227 for pindex, (rev, node, tags, message, remarks) in enumerate(
226 infoDict["parent"], start=1 228 infoDict["parent"], start=1
227 ): 229 ):
228 changeset = "{0}:{1}".format(rev, node) 230 changeset = "{0}:{1}".format(rev, node)
229 if len(infoDict["parent"]) > 1: 231 if len(infoDict["parent"]) > 1:
230 info.append(self.tr( 232 info.append(
231 "<tr><td><b>Parent #{0}</b></td><td>{1}</td></tr>") 233 self.tr(
232 .format(pindex, changeset)) 234 "<tr><td><b>Parent #{0}</b></td><td>{1}</td></tr>"
233 else: 235 ).format(pindex, changeset)
234 info.append(self.tr( 236 )
235 "<tr><td><b>Parent</b></td><td>{0}</td></tr>") 237 else:
236 .format(changeset)) 238 info.append(
239 self.tr("<tr><td><b>Parent</b></td><td>{0}</td></tr>").format(
240 changeset
241 )
242 )
237 if tags: 243 if tags:
238 info.append(self.tr( 244 info.append(
239 "<tr><td><b>Tags</b></td><td>{0}</td></tr>") 245 self.tr("<tr><td><b>Tags</b></td><td>{0}</td></tr>").format(
240 .format('<br/>'.join(tags.split()))) 246 "<br/>".join(tags.split())
247 )
248 )
241 if message: 249 if message:
242 info.append(self.tr( 250 info.append(
243 "<tr><td><b>Commit Message</b></td><td>{0}</td></tr>") 251 self.tr(
244 .format(message)) 252 "<tr><td><b>Commit Message</b></td><td>{0}</td></tr>"
253 ).format(message)
254 )
245 if remarks: 255 if remarks:
246 rem = [] 256 rem = []
247 if "@EMPTY@" in remarks: 257 if "@EMPTY@" in remarks:
248 rem.append(self.tr("empty repository")) 258 rem.append(self.tr("empty repository"))
249 if "@NO_REVISION@" in remarks: 259 if "@NO_REVISION@" in remarks:
250 rem.append(self.tr("no revision checked out")) 260 rem.append(self.tr("no revision checked out"))
251 info.append(self.tr( 261 info.append(
252 "<tr><td><b>Remarks</b></td><td>{0}</td></tr>") 262 self.tr("<tr><td><b>Remarks</b></td><td>{0}</td></tr>").format(
253 .format(", ".join(rem))) 263 ", ".join(rem)
264 )
265 )
254 if "branch" in infoDict: 266 if "branch" in infoDict:
255 info.append(self.tr( 267 info.append(
256 "<tr><td><b>Branch</b></td><td>{0}</td></tr>") 268 self.tr("<tr><td><b>Branch</b></td><td>{0}</td></tr>").format(
257 .format(infoDict["branch"])) 269 infoDict["branch"]
270 )
271 )
258 if "bookmarks" in infoDict: 272 if "bookmarks" in infoDict:
259 bookmarks = infoDict["bookmarks"].split() 273 bookmarks = infoDict["bookmarks"].split()
260 for i in range(len(bookmarks)): 274 for i in range(len(bookmarks)):
261 if bookmarks[i].startswith("*"): 275 if bookmarks[i].startswith("*"):
262 bookmarks[i] = "<b>{0}</b>".format(bookmarks[i]) 276 bookmarks[i] = "<b>{0}</b>".format(bookmarks[i])
263 info.append(self.tr( 277 info.append(
264 "<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>") 278 self.tr("<tr><td><b>Bookmarks</b></td><td>{0}</td></tr>").format(
265 .format('<br/>'.join(bookmarks))) 279 "<br/>".join(bookmarks)
280 )
281 )
266 if "commit" in infoDict: 282 if "commit" in infoDict:
267 cinfo = [] 283 cinfo = []
268 for category, count in infoDict["commit"][0].items(): 284 for category, count in infoDict["commit"][0].items():
269 if category == "modified": 285 if category == "modified":
270 cinfo.append(self.tr("{0} modified").format(count)) 286 cinfo.append(self.tr("{0} modified").format(count))
281 elif category == "unknown": 297 elif category == "unknown":
282 cinfo.append(self.tr("{0} unknown").format(count)) 298 cinfo.append(self.tr("{0} unknown").format(count))
283 elif category == "ignored": 299 elif category == "ignored":
284 cinfo.append(self.tr("{0} ignored").format(count)) 300 cinfo.append(self.tr("{0} ignored").format(count))
285 elif category == "unresolved": 301 elif category == "unresolved":
286 cinfo.append( 302 cinfo.append(self.tr("{0} unresolved").format(count))
287 self.tr("{0} unresolved").format(count))
288 elif category == "subrepos": 303 elif category == "subrepos":
289 cinfo.append(self.tr("{0} subrepos").format(count)) 304 cinfo.append(self.tr("{0} subrepos").format(count))
290 remark = infoDict["commit"][1] 305 remark = infoDict["commit"][1]
291 if remark == "merge": 306 if remark == "merge":
292 cinfo.append(self.tr("Merge needed")) 307 cinfo.append(self.tr("Merge needed"))
296 cinfo.append(self.tr("Head is closed")) 311 cinfo.append(self.tr("Head is closed"))
297 elif remark == "clean": 312 elif remark == "clean":
298 cinfo.append(self.tr("No commit required")) 313 cinfo.append(self.tr("No commit required"))
299 elif remark == "new branch head": 314 elif remark == "new branch head":
300 cinfo.append(self.tr("New Branch Head")) 315 cinfo.append(self.tr("New Branch Head"))
301 info.append(self.tr( 316 info.append(
302 "<tr><td><b>Commit Status</b></td><td>{0}</td></tr>") 317 self.tr(
303 .format("<br/>".join(cinfo))) 318 "<tr><td><b>Commit Status</b></td><td>{0}</td></tr>"
319 ).format("<br/>".join(cinfo))
320 )
304 if "update" in infoDict: 321 if "update" in infoDict:
305 if infoDict["update"][0] == "@CURRENT@": 322 if infoDict["update"][0] == "@CURRENT@":
306 uinfo = self.tr("current") 323 uinfo = self.tr("current")
307 elif infoDict["update"][0] == "@UPDATE@": 324 elif infoDict["update"][0] == "@UPDATE@":
308 uinfo = self.tr( 325 uinfo = self.tr(
309 "%n new changeset(s)<br/>Update required", "", 326 "%n new changeset(s)<br/>Update required",
310 infoDict["update"][1]) 327 "",
328 infoDict["update"][1],
329 )
311 elif infoDict["update"][0] == "@MERGE@": 330 elif infoDict["update"][0] == "@MERGE@":
312 uinfo1 = self.tr( 331 uinfo1 = self.tr("%n new changeset(s)", "", infoDict["update"][1])
313 "%n new changeset(s)", "", infoDict["update"][1]) 332 uinfo2 = self.tr("%n branch head(s)", "", infoDict["update"][2])
314 uinfo2 = self.tr(
315 "%n branch head(s)", "", infoDict["update"][2])
316 uinfo = self.tr( 333 uinfo = self.tr(
317 "{0}<br/>{1}<br/>Merge required", 334 "{0}<br/>{1}<br/>Merge required",
318 "0 is changesets, 1 is branch heads" 335 "0 is changesets, 1 is branch heads",
319 ).format(uinfo1, uinfo2) 336 ).format(uinfo1, uinfo2)
320 else: 337 else:
321 uinfo = self.tr("unknown status") 338 uinfo = self.tr("unknown status")
322 info.append(self.tr( 339 info.append(
323 "<tr><td><b>Update Status</b></td><td>{0}</td></tr>") 340 self.tr(
324 .format(uinfo)) 341 "<tr><td><b>Update Status</b></td><td>{0}</td></tr>"
342 ).format(uinfo)
343 )
325 if "remote" in infoDict: 344 if "remote" in infoDict:
326 if infoDict["remote"] == (0, 0, 0, 0): 345 if infoDict["remote"] == (0, 0, 0, 0):
327 rinfo = self.tr("synched") 346 rinfo = self.tr("synched")
328 else: 347 else:
329 li = [] 348 li = []
330 if infoDict["remote"][0]: 349 if infoDict["remote"][0]:
331 li.append(self.tr("1 or more incoming changesets")) 350 li.append(self.tr("1 or more incoming changesets"))
332 if infoDict["remote"][1]: 351 if infoDict["remote"][1]:
333 li.append(self.tr("%n outgoing changeset(s)", "", 352 li.append(
334 infoDict["remote"][1])) 353 self.tr(
354 "%n outgoing changeset(s)", "", infoDict["remote"][1]
355 )
356 )
335 if infoDict["remote"][2]: 357 if infoDict["remote"][2]:
336 li.append(self.tr("%n incoming bookmark(s)", "", 358 li.append(
337 infoDict["remote"][2])) 359 self.tr(
360 "%n incoming bookmark(s)", "", infoDict["remote"][2]
361 )
362 )
338 if infoDict["remote"][3]: 363 if infoDict["remote"][3]:
339 li.append(self.tr("%n outgoing bookmark(s)", "", 364 li.append(
340 infoDict["remote"][3])) 365 self.tr(
366 "%n outgoing bookmark(s)", "", infoDict["remote"][3]
367 )
368 )
341 rinfo = "<br/>".join(li) 369 rinfo = "<br/>".join(li)
342 info.append(self.tr( 370 info.append(
343 "<tr><td><b>Remote Status</b></td><td>{0}</td></tr>") 371 self.tr(
344 .format(rinfo)) 372 "<tr><td><b>Remote Status</b></td><td>{0}</td></tr>"
373 ).format(rinfo)
374 )
345 if "mq" in infoDict: 375 if "mq" in infoDict:
346 if infoDict["mq"] == (0, 0): 376 if infoDict["mq"] == (0, 0):
347 qinfo = self.tr("empty queue") 377 qinfo = self.tr("empty queue")
348 else: 378 else:
349 li = [] 379 li = []
350 if infoDict["mq"][0]: 380 if infoDict["mq"][0]:
351 li.append(self.tr("{0} applied") 381 li.append(self.tr("{0} applied").format(infoDict["mq"][0]))
352 .format(infoDict["mq"][0]))
353 if infoDict["mq"][1]: 382 if infoDict["mq"][1]:
354 li.append(self.tr("{0} unapplied") 383 li.append(self.tr("{0} unapplied").format(infoDict["mq"][1]))
355 .format(infoDict["mq"][1]))
356 qinfo = "<br/>".join(li) 384 qinfo = "<br/>".join(li)
357 info.append(self.tr( 385 info.append(
358 "<tr><td><b>Queues Status</b></td><td>{0}</td></tr>") 386 self.tr(
359 .format(qinfo)) 387 "<tr><td><b>Queues Status</b></td><td>{0}</td></tr>"
388 ).format(qinfo)
389 )
360 if "largefiles" in infoDict: 390 if "largefiles" in infoDict:
361 if infoDict["largefiles"] == 0: 391 if infoDict["largefiles"] == 0:
362 lfInfo = self.tr("No files to upload") 392 lfInfo = self.tr("No files to upload")
363 else: 393 else:
364 lfInfo = self.tr("%n file(s) to upload", "", 394 lfInfo = self.tr("%n file(s) to upload", "", infoDict["largefiles"])
365 infoDict["largefiles"]) 395 info.append(
366 info.append(self.tr( 396 self.tr("<tr><td><b>Large Files</b></td><td>{0}</td></tr>").format(
367 "<tr><td><b>Large Files</b></td><td>{0}</td></tr>") 397 lfInfo
368 .format(lfInfo)) 398 )
399 )
369 info.append("</table>") 400 info.append("</table>")
370 else: 401 else:
371 info = [self.tr("<p>No status information available.</p>")] 402 info = [self.tr("<p>No status information available.</p>")]
372 403
373 self.summary.insertHtml("\n".join(info)) 404 self.summary.insertHtml("\n".join(info))

eric ide

mercurial