src/eric7/Plugins/VcsPlugins/vcsMercurial/ShelveExtension/HgShelveBrowserDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
7 Module implementing Mercurial shelve browser dialog. 7 Module implementing Mercurial shelve browser dialog.
8 """ 8 """
9 9
10 from PyQt6.QtCore import pyqtSlot, Qt, QPoint 10 from PyQt6.QtCore import pyqtSlot, Qt, QPoint
11 from PyQt6.QtWidgets import ( 11 from PyQt6.QtWidgets import (
12 QWidget, QDialogButtonBox, QTreeWidgetItem, QAbstractButton, QMenu, 12 QWidget,
13 QHeaderView, QApplication 13 QDialogButtonBox,
14 QTreeWidgetItem,
15 QAbstractButton,
16 QMenu,
17 QHeaderView,
18 QApplication,
14 ) 19 )
15 20
16 from EricGui.EricOverrideCursor import EricOverrideCursor 21 from EricGui.EricOverrideCursor import EricOverrideCursor
17 22
18 from .Ui_HgShelveBrowserDialog import Ui_HgShelveBrowserDialog 23 from .Ui_HgShelveBrowserDialog import Ui_HgShelveBrowserDialog
20 25
21 class HgShelveBrowserDialog(QWidget, Ui_HgShelveBrowserDialog): 26 class HgShelveBrowserDialog(QWidget, Ui_HgShelveBrowserDialog):
22 """ 27 """
23 Class implementing Mercurial shelve browser dialog. 28 Class implementing Mercurial shelve browser dialog.
24 """ 29 """
30
25 NameColumn = 0 31 NameColumn = 0
26 AgeColumn = 1 32 AgeColumn = 1
27 MessageColumn = 2 33 MessageColumn = 2
28 34
29 def __init__(self, vcs, parent=None): 35 def __init__(self, vcs, parent=None):
30 """ 36 """
31 Constructor 37 Constructor
32 38
33 @param vcs reference to the vcs object 39 @param vcs reference to the vcs object
34 @param parent parent widget (QWidget) 40 @param parent parent widget (QWidget)
35 """ 41 """
36 super().__init__(parent) 42 super().__init__(parent)
37 self.setupUi(self) 43 self.setupUi(self)
38 44
39 self.buttonBox.button( 45 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
40 QDialogButtonBox.StandardButton.Close).setEnabled(False) 46 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
41 self.buttonBox.button( 47
42 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
43
44 self.__position = QPoint() 48 self.__position = QPoint()
45 49
46 self.__fileStatisticsRole = Qt.ItemDataRole.UserRole 50 self.__fileStatisticsRole = Qt.ItemDataRole.UserRole
47 self.__totalStatisticsRole = Qt.ItemDataRole.UserRole + 1 51 self.__totalStatisticsRole = Qt.ItemDataRole.UserRole + 1
48 52
49 self.shelveList.header().setSortIndicator( 53 self.shelveList.header().setSortIndicator(0, Qt.SortOrder.AscendingOrder)
50 0, Qt.SortOrder.AscendingOrder) 54
51
52 self.refreshButton = self.buttonBox.addButton( 55 self.refreshButton = self.buttonBox.addButton(
53 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole) 56 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole
54 self.refreshButton.setToolTip( 57 )
55 self.tr("Press to refresh the list of shelves")) 58 self.refreshButton.setToolTip(self.tr("Press to refresh the list of shelves"))
56 self.refreshButton.setEnabled(False) 59 self.refreshButton.setEnabled(False)
57 60
58 self.vcs = vcs 61 self.vcs = vcs
59 self.__hgClient = vcs.getClient() 62 self.__hgClient = vcs.getClient()
60 self.__resetUI() 63 self.__resetUI()
61 64
62 self.__contextMenu = QMenu() 65 self.__contextMenu = QMenu()
63 self.__unshelveAct = self.__contextMenu.addAction( 66 self.__unshelveAct = self.__contextMenu.addAction(
64 self.tr("Restore selected shelve"), self.__unshelve) 67 self.tr("Restore selected shelve"), self.__unshelve
68 )
65 self.__deleteAct = self.__contextMenu.addAction( 69 self.__deleteAct = self.__contextMenu.addAction(
66 self.tr("Delete selected shelves"), self.__deleteShelves) 70 self.tr("Delete selected shelves"), self.__deleteShelves
71 )
67 self.__contextMenu.addAction( 72 self.__contextMenu.addAction(
68 self.tr("Delete all shelves"), self.__cleanupShelves) 73 self.tr("Delete all shelves"), self.__cleanupShelves
69 74 )
75
70 def closeEvent(self, e): 76 def closeEvent(self, e):
71 """ 77 """
72 Protected slot implementing a close event handler. 78 Protected slot implementing a close event handler.
73 79
74 @param e close event (QCloseEvent) 80 @param e close event (QCloseEvent)
75 """ 81 """
76 if self.__hgClient.isExecuting(): 82 if self.__hgClient.isExecuting():
77 self.__hgClient.cancel() 83 self.__hgClient.cancel()
78 84
79 self.__position = self.pos() 85 self.__position = self.pos()
80 86
81 e.accept() 87 e.accept()
82 88
83 def show(self): 89 def show(self):
84 """ 90 """
85 Public slot to show the dialog. 91 Public slot to show the dialog.
86 """ 92 """
87 if not self.__position.isNull(): 93 if not self.__position.isNull():
88 self.move(self.__position) 94 self.move(self.__position)
89 self.__resetUI() 95 self.__resetUI()
90 96
91 super().show() 97 super().show()
92 98
93 def __resetUI(self): 99 def __resetUI(self):
94 """ 100 """
95 Private method to reset the user interface. 101 Private method to reset the user interface.
96 """ 102 """
97 self.shelveList.clear() 103 self.shelveList.clear()
98 104
99 def __resizeColumnsShelves(self): 105 def __resizeColumnsShelves(self):
100 """ 106 """
101 Private method to resize the shelve list columns. 107 Private method to resize the shelve list columns.
102 """ 108 """
103 self.shelveList.header().resizeSections( 109 self.shelveList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
104 QHeaderView.ResizeMode.ResizeToContents)
105 self.shelveList.header().setStretchLastSection(True) 110 self.shelveList.header().setStretchLastSection(True)
106 111
107 def __generateShelveEntry(self, name, age, message, fileStatistics, 112 def __generateShelveEntry(self, name, age, message, fileStatistics, totals):
108 totals):
109 """ 113 """
110 Private method to generate the shelve items. 114 Private method to generate the shelve items.
111 115
112 @param name name of the shelve (string) 116 @param name name of the shelve (string)
113 @param age age of the shelve (string) 117 @param age age of the shelve (string)
114 @param message shelve message (string) 118 @param message shelve message (string)
115 @param fileStatistics per file change statistics (tuple of 119 @param fileStatistics per file change statistics (tuple of
116 four strings with file name, number of changes, number of 120 four strings with file name, number of changes, number of
120 of deleted lines) 124 of deleted lines)
121 """ 125 """
122 itm = QTreeWidgetItem(self.shelveList, [name, age, message]) 126 itm = QTreeWidgetItem(self.shelveList, [name, age, message])
123 itm.setData(0, self.__fileStatisticsRole, fileStatistics) 127 itm.setData(0, self.__fileStatisticsRole, fileStatistics)
124 itm.setData(0, self.__totalStatisticsRole, totals) 128 itm.setData(0, self.__totalStatisticsRole, totals)
125 129
126 def __getShelveEntries(self): 130 def __getShelveEntries(self):
127 """ 131 """
128 Private method to retrieve the list of shelves. 132 Private method to retrieve the list of shelves.
129 """ 133 """
130 self.buttonBox.button( 134 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
131 QDialogButtonBox.StandardButton.Close).setEnabled(False) 135 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
132 self.buttonBox.button( 136 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
133 QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
134 self.buttonBox.button(
135 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
136 QApplication.processEvents() 137 QApplication.processEvents()
137 138
138 self.buf = [] 139 self.buf = []
139 self.errors.clear() 140 self.errors.clear()
140 self.intercept = False 141 self.intercept = False
141 142
142 args = self.vcs.initCommand("shelve") 143 args = self.vcs.initCommand("shelve")
143 args.append("--list") 144 args.append("--list")
144 args.append("--stat") 145 args.append("--stat")
145 146
146 with EricOverrideCursor(): 147 with EricOverrideCursor():
147 out, err = self.__hgClient.runcommand(args) 148 out, err = self.__hgClient.runcommand(args)
148 self.buf = out.splitlines(True) 149 self.buf = out.splitlines(True)
149 if err: 150 if err:
150 self.__showError(err) 151 self.__showError(err)
151 self.__processBuffer() 152 self.__processBuffer()
152 self.__finish() 153 self.__finish()
153 154
154 def start(self): 155 def start(self):
155 """ 156 """
156 Public slot to start the hg shelve command. 157 Public slot to start the hg shelve command.
157 """ 158 """
158 self.errorGroup.hide() 159 self.errorGroup.hide()
159 QApplication.processEvents() 160 QApplication.processEvents()
160 161
161 self.activateWindow() 162 self.activateWindow()
162 self.raise_() 163 self.raise_()
163 164
164 self.shelveList.clear() 165 self.shelveList.clear()
165 self.__started = True 166 self.__started = True
166 self.__getShelveEntries() 167 self.__getShelveEntries()
167 168
168 def __finish(self): 169 def __finish(self):
169 """ 170 """
170 Private slot called when the process finished or the user pressed 171 Private slot called when the process finished or the user pressed
171 the button. 172 the button.
172 """ 173 """
173 self.buttonBox.button( 174 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
174 QDialogButtonBox.StandardButton.Close).setEnabled(True) 175 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
175 self.buttonBox.button( 176 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True)
176 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) 177
177 self.buttonBox.button(
178 QDialogButtonBox.StandardButton.Close).setDefault(True)
179
180 self.refreshButton.setEnabled(True) 178 self.refreshButton.setEnabled(True)
181 179
182 def __processBuffer(self): 180 def __processBuffer(self):
183 """ 181 """
184 Private method to process the buffered output of the hg shelve command. 182 Private method to process the buffered output of the hg shelve command.
185 """ 183 """
186 lastWasFileStats = False 184 lastWasFileStats = False
193 itemData["name"] = name.strip() 191 itemData["name"] = name.strip()
194 itemData["age"] = age.strip() 192 itemData["age"] = age.strip()
195 itemData["message"] = message.strip() 193 itemData["message"] = message.strip()
196 itemData["files"] = [] 194 itemData["files"] = []
197 firstLine = False 195 firstLine = False
198 elif '|' in line: 196 elif "|" in line:
199 # file stats: foo.py | 3 ++- 197 # file stats: foo.py | 3 ++-
200 file, changes = line.strip().split("|", 1) 198 file, changes = line.strip().split("|", 1)
201 if changes.strip().endswith(("+", "-")): 199 if changes.strip().endswith(("+", "-")):
202 total, addDelete = changes.strip().split(None, 1) 200 total, addDelete = changes.strip().split(None, 1)
203 additions = str(addDelete.count("+")) 201 additions = str(addDelete.count("+"))
204 deletions = str(addDelete.count("-")) 202 deletions = str(addDelete.count("-"))
205 else: 203 else:
206 total = changes.strip() 204 total = changes.strip()
207 additions = '0' 205 additions = "0"
208 deletions = '0' 206 deletions = "0"
209 itemData["files"].append((file, total, additions, deletions)) 207 itemData["files"].append((file, total, additions, deletions))
210 lastWasFileStats = True 208 lastWasFileStats = True
211 elif lastWasFileStats: 209 elif lastWasFileStats:
212 # summary line 210 # summary line
213 # 2 files changed, 15 insertions(+), 1 deletions(-) 211 # 2 files changed, 15 insertions(+), 1 deletions(-)
214 total, added, deleted = line.strip().split(",", 2) 212 total, added, deleted = line.strip().split(",", 2)
215 total = total.split()[0] 213 total = total.split()[0]
216 added = added.split()[0] 214 added = added.split()[0]
217 deleted = deleted.split()[0] 215 deleted = deleted.split()[0]
218 itemData["summary"] = (total, added, deleted) 216 itemData["summary"] = (total, added, deleted)
219 217
220 self.__generateShelveEntry( 218 self.__generateShelveEntry(
221 itemData["name"], itemData["age"], itemData["message"], 219 itemData["name"],
222 itemData["files"], itemData["summary"]) 220 itemData["age"],
223 221 itemData["message"],
222 itemData["files"],
223 itemData["summary"],
224 )
225
224 lastWasFileStats = False 226 lastWasFileStats = False
225 firstLine = True 227 firstLine = True
226 itemData = {} 228 itemData = {}
227 229
228 self.__resizeColumnsShelves() 230 self.__resizeColumnsShelves()
229 231
230 if self.__started: 232 if self.__started:
231 self.shelveList.setCurrentItem(self.shelveList.topLevelItem(0)) 233 self.shelveList.setCurrentItem(self.shelveList.topLevelItem(0))
232 self.__started = False 234 self.__started = False
233 235
234 def __showError(self, out): 236 def __showError(self, out):
235 """ 237 """
236 Private slot to show some error. 238 Private slot to show some error.
237 239
238 @param out error to be shown (string) 240 @param out error to be shown (string)
239 """ 241 """
240 self.errorGroup.show() 242 self.errorGroup.show()
241 self.errors.insertPlainText(out) 243 self.errors.insertPlainText(out)
242 self.errors.ensureCursorVisible() 244 self.errors.ensureCursorVisible()
243 245
244 @pyqtSlot(QAbstractButton) 246 @pyqtSlot(QAbstractButton)
245 def on_buttonBox_clicked(self, button): 247 def on_buttonBox_clicked(self, button):
246 """ 248 """
247 Private slot called by a button of the button box clicked. 249 Private slot called by a button of the button box clicked.
248 250
249 @param button button that was clicked (QAbstractButton) 251 @param button button that was clicked (QAbstractButton)
250 """ 252 """
251 if button == self.buttonBox.button( 253 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
252 QDialogButtonBox.StandardButton.Close
253 ):
254 self.close() 254 self.close()
255 elif button == self.buttonBox.button( 255 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
256 QDialogButtonBox.StandardButton.Cancel
257 ):
258 self.cancelled = True 256 self.cancelled = True
259 self.__hgClient.cancel() 257 self.__hgClient.cancel()
260 elif button == self.refreshButton: 258 elif button == self.refreshButton:
261 self.on_refreshButton_clicked() 259 self.on_refreshButton_clicked()
262 260
263 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) 261 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem)
264 def on_shelveList_currentItemChanged(self, current, previous): 262 def on_shelveList_currentItemChanged(self, current, previous):
265 """ 263 """
266 Private slot called, when the current item of the shelve list changes. 264 Private slot called, when the current item of the shelve list changes.
267 265
268 @param current reference to the new current item (QTreeWidgetItem) 266 @param current reference to the new current item (QTreeWidgetItem)
269 @param previous reference to the old current item (QTreeWidgetItem) 267 @param previous reference to the old current item (QTreeWidgetItem)
270 """ 268 """
271 self.statisticsList.clear() 269 self.statisticsList.clear()
272 if current: 270 if current:
273 for dataSet in current.data(0, self.__fileStatisticsRole): 271 for dataSet in current.data(0, self.__fileStatisticsRole):
274 QTreeWidgetItem(self.statisticsList, list(dataSet)) 272 QTreeWidgetItem(self.statisticsList, list(dataSet))
275 self.statisticsList.header().resizeSections( 273 self.statisticsList.header().resizeSections(
276 QHeaderView.ResizeMode.ResizeToContents) 274 QHeaderView.ResizeMode.ResizeToContents
275 )
277 self.statisticsList.header().setStretchLastSection(True) 276 self.statisticsList.header().setStretchLastSection(True)
278 277
279 totals = current.data(0, self.__totalStatisticsRole) 278 totals = current.data(0, self.__totalStatisticsRole)
280 self.filesLabel.setText( 279 self.filesLabel.setText(self.tr("%n file(s) changed", None, int(totals[0])))
281 self.tr("%n file(s) changed", None, int(totals[0])))
282 self.insertionsLabel.setText( 280 self.insertionsLabel.setText(
283 self.tr("%n line(s) inserted", None, int(totals[1]))) 281 self.tr("%n line(s) inserted", None, int(totals[1]))
282 )
284 self.deletionsLabel.setText( 283 self.deletionsLabel.setText(
285 self.tr("%n line(s) deleted", None, int(totals[2]))) 284 self.tr("%n line(s) deleted", None, int(totals[2]))
285 )
286 else: 286 else:
287 self.filesLabel.setText("") 287 self.filesLabel.setText("")
288 self.insertionsLabel.setText("") 288 self.insertionsLabel.setText("")
289 self.deletionsLabel.setText("") 289 self.deletionsLabel.setText("")
290 290
291 @pyqtSlot(QPoint) 291 @pyqtSlot(QPoint)
292 def on_shelveList_customContextMenuRequested(self, pos): 292 def on_shelveList_customContextMenuRequested(self, pos):
293 """ 293 """
294 Private slot to show the context menu of the shelve list. 294 Private slot to show the context menu of the shelve list.
295 295
296 @param pos position of the mouse pointer (QPoint) 296 @param pos position of the mouse pointer (QPoint)
297 """ 297 """
298 selectedItemsCount = len(self.shelveList.selectedItems()) 298 selectedItemsCount = len(self.shelveList.selectedItems())
299 self.__unshelveAct.setEnabled(selectedItemsCount == 1) 299 self.__unshelveAct.setEnabled(selectedItemsCount == 1)
300 self.__deleteAct.setEnabled(selectedItemsCount > 0) 300 self.__deleteAct.setEnabled(selectedItemsCount > 0)
301 301
302 self.__contextMenu.popup(self.mapToGlobal(pos)) 302 self.__contextMenu.popup(self.mapToGlobal(pos))
303 303
304 @pyqtSlot() 304 @pyqtSlot()
305 def on_refreshButton_clicked(self): 305 def on_refreshButton_clicked(self):
306 """ 306 """
307 Private slot to refresh the list of shelves. 307 Private slot to refresh the list of shelves.
308 """ 308 """
309 self.buttonBox.button( 309 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
310 QDialogButtonBox.StandardButton.Close).setEnabled(False) 310 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
311 self.buttonBox.button( 311 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
312 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) 312
313 self.buttonBox.button(
314 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
315
316 self.refreshButton.setEnabled(False) 313 self.refreshButton.setEnabled(False)
317 314
318 self.start() 315 self.start()
319 316
320 def __unshelve(self): 317 def __unshelve(self):
321 """ 318 """
322 Private slot to restore the selected shelve of changes. 319 Private slot to restore the selected shelve of changes.
323 """ 320 """
324 itm = self.shelveList.selectedItems()[0] 321 itm = self.shelveList.selectedItems()[0]
325 if itm is not None: 322 if itm is not None:
326 name = itm.text(self.NameColumn) 323 name = itm.text(self.NameColumn)
327 self.vcs.getExtensionObject("shelve").hgUnshelve(shelveName=name) 324 self.vcs.getExtensionObject("shelve").hgUnshelve(shelveName=name)
328 self.on_refreshButton_clicked() 325 self.on_refreshButton_clicked()
329 326
330 def __deleteShelves(self): 327 def __deleteShelves(self):
331 """ 328 """
332 Private slot to delete the selected shelves. 329 Private slot to delete the selected shelves.
333 """ 330 """
334 shelveNames = [] 331 shelveNames = []
335 for itm in self.shelveList.selectedItems(): 332 for itm in self.shelveList.selectedItems():
336 shelveNames.append(itm.text(self.NameColumn)) 333 shelveNames.append(itm.text(self.NameColumn))
337 if shelveNames: 334 if shelveNames:
338 self.vcs.getExtensionObject("shelve").hgDeleteShelves( 335 self.vcs.getExtensionObject("shelve").hgDeleteShelves(
339 shelveNames=shelveNames) 336 shelveNames=shelveNames
337 )
340 self.on_refreshButton_clicked() 338 self.on_refreshButton_clicked()
341 339
342 def __cleanupShelves(self): 340 def __cleanupShelves(self):
343 """ 341 """
344 Private slot to delete all shelves. 342 Private slot to delete all shelves.
345 """ 343 """
346 self.vcs.getExtensionObject("shelve").hgCleanupShelves() 344 self.vcs.getExtensionObject("shelve").hgCleanupShelves()

eric ide

mercurial