src/eric7/Plugins/VcsPlugins/vcsMercurial/QueuesExtension/HgQueuesListDialog.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2011 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show a list of applied and unapplied patches.
8 """
9
10 from PyQt6.QtCore import Qt, QCoreApplication
11 from PyQt6.QtWidgets import (
12 QDialog, QDialogButtonBox, QHeaderView, QTreeWidgetItem
13 )
14
15 from .Ui_HgQueuesListDialog import Ui_HgQueuesListDialog
16
17
18 class HgQueuesListDialog(QDialog, Ui_HgQueuesListDialog):
19 """
20 Class implementing a dialog to show a list of applied and unapplied
21 patches.
22 """
23 def __init__(self, vcs, parent=None):
24 """
25 Constructor
26
27 @param vcs reference to the vcs object
28 @param parent parent widget (QWidget)
29 """
30 super().__init__(parent)
31 self.setupUi(self)
32 self.setWindowFlags(Qt.WindowType.Window)
33
34 self.buttonBox.button(
35 QDialogButtonBox.StandardButton.Close).setEnabled(False)
36 self.buttonBox.button(
37 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
38
39 self.vcs = vcs
40 self.__hgClient = vcs.getClient()
41
42 self.patchesList.header().setSortIndicator(
43 0, Qt.SortOrder.AscendingOrder)
44
45 self.__statusDict = {
46 "A": self.tr("applied"),
47 "U": self.tr("not applied"),
48 "G": self.tr("guarded"),
49 "D": self.tr("missing"),
50 }
51
52 self.show()
53 QCoreApplication.processEvents()
54
55 def closeEvent(self, e):
56 """
57 Protected slot implementing a close event handler.
58
59 @param e close event (QCloseEvent)
60 """
61 if self.__hgClient.isExecuting():
62 self.__hgClient.cancel()
63
64 e.accept()
65
66 def start(self):
67 """
68 Public slot to start the list command.
69 """
70 self.errorGroup.hide()
71 self.activateWindow()
72
73 self.__getSeries()
74
75 def __getSeries(self, missing=False):
76 """
77 Private slot to get the list of applied, unapplied and guarded patches
78 and patches missing in the series file.
79
80 @param missing flag indicating to get the patches missing in the
81 series file (boolean)
82 """
83 if missing:
84 self.__mode = "missing"
85 else:
86 self.__mode = "qseries"
87
88 args = self.vcs.initCommand("qseries")
89 args.append('--summary')
90 args.append('--verbose')
91 if missing:
92 args.append('--missing')
93
94 out, err = self.__hgClient.runcommand(args)
95 if err:
96 self.__showError(err)
97 if out:
98 for line in out.splitlines():
99 self.__processOutputLine(line)
100 if self.__hgClient.wasCanceled():
101 self.__mode = ""
102 break
103 if self.__mode == "qseries":
104 self.__getSeries(True)
105 elif self.__mode == "missing":
106 self.__getTop()
107 else:
108 self.__finish()
109
110 def __getTop(self):
111 """
112 Private slot to get patch at the top of the stack.
113 """
114 self.__mode = "qtop"
115
116 args = self.vcs.initCommand("qtop")
117
118 out, err = self.__hgClient.runcommand(args)
119 if err:
120 self.__showError(err)
121 if out:
122 for line in out.splitlines():
123 self.__processOutputLine(line)
124 if self.__hgClient.wasCanceled():
125 break
126 self.__finish()
127
128 def __finish(self):
129 """
130 Private slot called when the process finished or the user pressed
131 the button.
132 """
133 self.buttonBox.button(
134 QDialogButtonBox.StandardButton.Close).setEnabled(True)
135 self.buttonBox.button(
136 QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
137 self.buttonBox.button(
138 QDialogButtonBox.StandardButton.Close).setDefault(True)
139 self.buttonBox.button(
140 QDialogButtonBox.StandardButton.Close).setFocus(
141 Qt.FocusReason.OtherFocusReason)
142
143 if self.patchesList.topLevelItemCount() == 0:
144 # no patches present
145 self.__generateItem(
146 0, "", self.tr("no patches found"), "", True)
147 self.__resizeColumns()
148 self.__resort()
149
150 def on_buttonBox_clicked(self, button):
151 """
152 Private slot called by a button of the button box clicked.
153
154 @param button button that was clicked (QAbstractButton)
155 """
156 if button == self.buttonBox.button(
157 QDialogButtonBox.StandardButton.Close
158 ):
159 self.close()
160 elif button == self.buttonBox.button(
161 QDialogButtonBox.StandardButton.Cancel
162 ):
163 self.__mode = ""
164 self.__hgClient.cancel()
165
166 def __resort(self):
167 """
168 Private method to resort the tree.
169 """
170 self.patchesList.sortItems(
171 self.patchesList.sortColumn(),
172 self.patchesList.header().sortIndicatorOrder())
173
174 def __resizeColumns(self):
175 """
176 Private method to resize the list columns.
177 """
178 self.patchesList.header().resizeSections(
179 QHeaderView.ResizeMode.ResizeToContents)
180 self.patchesList.header().setStretchLastSection(True)
181
182 def __generateItem(self, index, status, name, summary, error=False):
183 """
184 Private method to generate a patch item in the list of patches.
185
186 @param index index of the patch (integer, -1 for missing)
187 @param status status of the patch (string)
188 @param name name of the patch (string)
189 @param summary first line of the patch header (string)
190 @param error flag indicating an error entry (boolean)
191 """
192 if error:
193 itm = QTreeWidgetItem(self.patchesList, [
194 "",
195 name,
196 "",
197 summary
198 ])
199 else:
200 if index == -1:
201 index = ""
202 try:
203 statusStr = self.__statusDict[status]
204 except KeyError:
205 statusStr = self.tr("unknown")
206 itm = QTreeWidgetItem(self.patchesList)
207 itm.setData(0, Qt.ItemDataRole.DisplayRole, index)
208 itm.setData(1, Qt.ItemDataRole.DisplayRole, name)
209 itm.setData(2, Qt.ItemDataRole.DisplayRole, statusStr)
210 itm.setData(3, Qt.ItemDataRole.DisplayRole, summary)
211 if status == "A":
212 # applied
213 for column in range(itm.columnCount()):
214 itm.setForeground(column, Qt.GlobalColor.blue)
215 elif status == "D":
216 # missing
217 for column in range(itm.columnCount()):
218 itm.setForeground(column, Qt.GlobalColor.red)
219
220 itm.setTextAlignment(0, Qt.AlignmentFlag.AlignRight)
221 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter)
222
223 def __markTopItem(self, name):
224 """
225 Private slot to mark the top patch entry.
226
227 @param name name of the patch (string)
228 """
229 items = self.patchesList.findItems(
230 name, Qt.MatchFlag.MatchCaseSensitive, 1)
231 if items:
232 itm = items[0]
233 for column in range(itm.columnCount()):
234 font = itm.font(column)
235 font.setBold(True)
236 itm.setFont(column, font)
237
238 def __processOutputLine(self, line):
239 """
240 Private method to process the lines of output.
241
242 @param line output line to be processed (string)
243 """
244 if self.__mode == "qtop":
245 self.__markTopItem(line)
246 else:
247 li = line.split(": ", 1)
248 if len(li) == 1:
249 data, summary = li[0][:-1], ""
250 else:
251 data, summary = li[0], li[1]
252 li = data.split(None, 2)
253 if len(li) == 2:
254 # missing entry
255 index, status, name = -1, li[0], li[1]
256 elif len(li) == 3:
257 index, status, name = li[:3]
258 else:
259 return
260 self.__generateItem(index, status, name, summary)
261
262 def __showError(self, out):
263 """
264 Private slot to show some error.
265
266 @param out error to be shown (string)
267 """
268 self.errorGroup.show()
269 self.errors.insertPlainText(out)
270 self.errors.ensureCursorVisible()

eric ide

mercurial