src/eric7/Plugins/VcsPlugins/vcsSubversion/SvnStatusDialog.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
11 import re 11 import re
12 import os 12 import os
13 13
14 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QProcess 14 from PyQt6.QtCore import pyqtSlot, Qt, QTimer, QProcess
15 from PyQt6.QtWidgets import ( 15 from PyQt6.QtWidgets import (
16 QWidget, QHeaderView, QLineEdit, QApplication, QMenu, QDialogButtonBox, 16 QWidget,
17 QTreeWidgetItem 17 QHeaderView,
18 QLineEdit,
19 QApplication,
20 QMenu,
21 QDialogButtonBox,
22 QTreeWidgetItem,
18 ) 23 )
19 24
20 from EricWidgets.EricApplication import ericApp 25 from EricWidgets.EricApplication import ericApp
21 from EricWidgets import EricMessageBox 26 from EricWidgets import EricMessageBox
22 27
29 class SvnStatusDialog(QWidget, Ui_SvnStatusDialog): 34 class SvnStatusDialog(QWidget, Ui_SvnStatusDialog):
30 """ 35 """
31 Class implementing a dialog to show the output of the svn status command 36 Class implementing a dialog to show the output of the svn status command
32 process. 37 process.
33 """ 38 """
39
34 def __init__(self, vcs, parent=None): 40 def __init__(self, vcs, parent=None):
35 """ 41 """
36 Constructor 42 Constructor
37 43
38 @param vcs reference to the vcs object 44 @param vcs reference to the vcs object
39 @param parent parent widget (QWidget) 45 @param parent parent widget (QWidget)
40 """ 46 """
41 super().__init__(parent) 47 super().__init__(parent)
42 self.setupUi(self) 48 self.setupUi(self)
43 49
44 self.__toBeCommittedColumn = 0 50 self.__toBeCommittedColumn = 0
45 self.__changelistColumn = 1 51 self.__changelistColumn = 1
46 self.__statusColumn = 2 52 self.__statusColumn = 2
47 self.__propStatusColumn = 3 53 self.__propStatusColumn = 3
48 self.__lockedColumn = 4 54 self.__lockedColumn = 4
50 self.__switchedColumn = 6 56 self.__switchedColumn = 6
51 self.__lockinfoColumn = 7 57 self.__lockinfoColumn = 7
52 self.__upToDateColumn = 8 58 self.__upToDateColumn = 8
53 self.__pathColumn = 12 59 self.__pathColumn = 12
54 self.__lastColumn = self.statusList.columnCount() 60 self.__lastColumn = self.statusList.columnCount()
55 61
56 self.refreshButton = self.buttonBox.addButton( 62 self.refreshButton = self.buttonBox.addButton(
57 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole) 63 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole
58 self.refreshButton.setToolTip( 64 )
59 self.tr("Press to refresh the status display")) 65 self.refreshButton.setToolTip(self.tr("Press to refresh the status display"))
60 self.refreshButton.setEnabled(False) 66 self.refreshButton.setEnabled(False)
61 self.buttonBox.button( 67 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(False)
62 QDialogButtonBox.StandardButton.Close).setEnabled(False) 68 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(True)
63 self.buttonBox.button( 69
64 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
65
66 self.diff = None 70 self.diff = None
67 self.vcs = vcs 71 self.vcs = vcs
68 self.vcs.committed.connect(self.__committed) 72 self.vcs.committed.connect(self.__committed)
69 73
70 self.process = QProcess() 74 self.process = QProcess()
71 self.process.finished.connect(self.__procFinished) 75 self.process.finished.connect(self.__procFinished)
72 self.process.readyReadStandardOutput.connect(self.__readStdout) 76 self.process.readyReadStandardOutput.connect(self.__readStdout)
73 self.process.readyReadStandardError.connect(self.__readStderr) 77 self.process.readyReadStandardError.connect(self.__readStderr)
74 78
75 self.statusList.headerItem().setText(self.__lastColumn, "") 79 self.statusList.headerItem().setText(self.__lastColumn, "")
76 self.statusList.header().setSortIndicator(self.__pathColumn, 80 self.statusList.header().setSortIndicator(
77 Qt.SortOrder.AscendingOrder) 81 self.__pathColumn, Qt.SortOrder.AscendingOrder
82 )
78 if self.vcs.version < (1, 5, 0): 83 if self.vcs.version < (1, 5, 0):
79 self.statusList.header().hideSection(self.__changelistColumn) 84 self.statusList.header().hideSection(self.__changelistColumn)
80 85
81 self.menuactions = [] 86 self.menuactions = []
82 self.menu = QMenu() 87 self.menu = QMenu()
83 self.menuactions.append(self.menu.addAction( 88 self.menuactions.append(
84 self.tr("Commit changes to repository..."), self.__commit)) 89 self.menu.addAction(
85 self.menuactions.append(self.menu.addAction( 90 self.tr("Commit changes to repository..."), self.__commit
86 self.tr("Select all for commit"), self.__commitSelectAll)) 91 )
87 self.menuactions.append(self.menu.addAction( 92 )
88 self.tr("Deselect all from commit"), self.__commitDeselectAll)) 93 self.menuactions.append(
94 self.menu.addAction(
95 self.tr("Select all for commit"), self.__commitSelectAll
96 )
97 )
98 self.menuactions.append(
99 self.menu.addAction(
100 self.tr("Deselect all from commit"), self.__commitDeselectAll
101 )
102 )
89 self.menu.addSeparator() 103 self.menu.addSeparator()
90 self.menuactions.append(self.menu.addAction( 104 self.menuactions.append(
91 self.tr("Add to repository"), self.__add)) 105 self.menu.addAction(self.tr("Add to repository"), self.__add)
92 self.menuactions.append(self.menu.addAction( 106 )
93 self.tr("Show differences"), self.__diff)) 107 self.menuactions.append(
94 self.menuactions.append(self.menu.addAction( 108 self.menu.addAction(self.tr("Show differences"), self.__diff)
95 self.tr("Show differences side-by-side"), self.__sbsDiff)) 109 )
96 self.menuactions.append(self.menu.addAction( 110 self.menuactions.append(
97 self.tr("Revert changes"), self.__revert)) 111 self.menu.addAction(
98 self.menuactions.append(self.menu.addAction( 112 self.tr("Show differences side-by-side"), self.__sbsDiff
99 self.tr("Restore missing"), self.__restoreMissing)) 113 )
114 )
115 self.menuactions.append(
116 self.menu.addAction(self.tr("Revert changes"), self.__revert)
117 )
118 self.menuactions.append(
119 self.menu.addAction(self.tr("Restore missing"), self.__restoreMissing)
120 )
100 if self.vcs.version >= (1, 5, 0): 121 if self.vcs.version >= (1, 5, 0):
101 self.menu.addSeparator() 122 self.menu.addSeparator()
102 self.menuactions.append(self.menu.addAction( 123 self.menuactions.append(
103 self.tr("Add to Changelist"), self.__addToChangelist)) 124 self.menu.addAction(
104 self.menuactions.append(self.menu.addAction( 125 self.tr("Add to Changelist"), self.__addToChangelist
105 self.tr("Remove from Changelist"), 126 )
106 self.__removeFromChangelist)) 127 )
128 self.menuactions.append(
129 self.menu.addAction(
130 self.tr("Remove from Changelist"), self.__removeFromChangelist
131 )
132 )
107 if self.vcs.version >= (1, 2, 0): 133 if self.vcs.version >= (1, 2, 0):
108 self.menu.addSeparator() 134 self.menu.addSeparator()
109 self.menuactions.append(self.menu.addAction( 135 self.menuactions.append(self.menu.addAction(self.tr("Lock"), self.__lock))
110 self.tr("Lock"), self.__lock)) 136 self.menuactions.append(
111 self.menuactions.append(self.menu.addAction( 137 self.menu.addAction(self.tr("Unlock"), self.__unlock)
112 self.tr("Unlock"), self.__unlock)) 138 )
113 self.menuactions.append(self.menu.addAction( 139 self.menuactions.append(
114 self.tr("Break lock"), 140 self.menu.addAction(self.tr("Break lock"), self.__breakLock)
115 self.__breakLock)) 141 )
116 self.menuactions.append(self.menu.addAction( 142 self.menuactions.append(
117 self.tr("Steal lock"), 143 self.menu.addAction(self.tr("Steal lock"), self.__stealLock)
118 self.__stealLock)) 144 )
119 self.menu.addSeparator() 145 self.menu.addSeparator()
120 self.menuactions.append(self.menu.addAction( 146 self.menuactions.append(
121 self.tr("Adjust column sizes"), 147 self.menu.addAction(self.tr("Adjust column sizes"), self.__resizeColumns)
122 self.__resizeColumns)) 148 )
123 for act in self.menuactions: 149 for act in self.menuactions:
124 act.setEnabled(False) 150 act.setEnabled(False)
125 151
126 self.statusList.setContextMenuPolicy( 152 self.statusList.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
127 Qt.ContextMenuPolicy.CustomContextMenu) 153 self.statusList.customContextMenuRequested.connect(self.__showContextMenu)
128 self.statusList.customContextMenuRequested.connect( 154
129 self.__showContextMenu)
130
131 self.modifiedIndicators = [ 155 self.modifiedIndicators = [
132 self.tr('added'), 156 self.tr("added"),
133 self.tr('deleted'), 157 self.tr("deleted"),
134 self.tr('modified'), 158 self.tr("modified"),
135 ] 159 ]
136 160
137 self.missingIndicators = [ 161 self.missingIndicators = [
138 self.tr('missing'), 162 self.tr("missing"),
139 ] 163 ]
140 164
141 self.unversionedIndicators = [ 165 self.unversionedIndicators = [
142 self.tr('unversioned'), 166 self.tr("unversioned"),
143 ] 167 ]
144 168
145 self.lockedIndicators = [ 169 self.lockedIndicators = [
146 self.tr('locked'), 170 self.tr("locked"),
147 ] 171 ]
148 172
149 self.stealBreakLockIndicators = [ 173 self.stealBreakLockIndicators = [
150 self.tr('other lock'), 174 self.tr("other lock"),
151 self.tr('stolen lock'), 175 self.tr("stolen lock"),
152 self.tr('broken lock'), 176 self.tr("broken lock"),
153 ] 177 ]
154 178
155 self.unlockedIndicators = [ 179 self.unlockedIndicators = [
156 self.tr('not locked'), 180 self.tr("not locked"),
157 ] 181 ]
158 182
159 self.status = { 183 self.status = {
160 ' ': self.tr('normal'), 184 " ": self.tr("normal"),
161 'A': self.tr('added'), 185 "A": self.tr("added"),
162 'C': self.tr('conflict'), 186 "C": self.tr("conflict"),
163 'D': self.tr('deleted'), 187 "D": self.tr("deleted"),
164 'I': self.tr('ignored'), 188 "I": self.tr("ignored"),
165 'M': self.tr('modified'), 189 "M": self.tr("modified"),
166 'R': self.tr('replaced'), 190 "R": self.tr("replaced"),
167 'X': self.tr('external'), 191 "X": self.tr("external"),
168 '?': self.tr('unversioned'), 192 "?": self.tr("unversioned"),
169 '!': self.tr('missing'), 193 "!": self.tr("missing"),
170 '~': self.tr('type error'), 194 "~": self.tr("type error"),
171 } 195 }
172 self.propStatus = { 196 self.propStatus = {
173 ' ': self.tr('normal'), 197 " ": self.tr("normal"),
174 'M': self.tr('modified'), 198 "M": self.tr("modified"),
175 'C': self.tr('conflict'), 199 "C": self.tr("conflict"),
176 } 200 }
177 self.locked = { 201 self.locked = {
178 ' ': self.tr('no'), 202 " ": self.tr("no"),
179 'L': self.tr('yes'), 203 "L": self.tr("yes"),
180 } 204 }
181 self.history = { 205 self.history = {
182 ' ': self.tr('no'), 206 " ": self.tr("no"),
183 '+': self.tr('yes'), 207 "+": self.tr("yes"),
184 } 208 }
185 self.switched = { 209 self.switched = {
186 ' ': self.tr('no'), 210 " ": self.tr("no"),
187 'S': self.tr('yes'), 211 "S": self.tr("yes"),
188 'X': self.tr('external') 212 "X": self.tr("external"),
189 } 213 }
190 self.lockinfo = { 214 self.lockinfo = {
191 ' ': self.tr('not locked'), 215 " ": self.tr("not locked"),
192 'K': self.tr('locked'), 216 "K": self.tr("locked"),
193 'O': self.tr('other lock'), 217 "O": self.tr("other lock"),
194 'T': self.tr('stolen lock'), 218 "T": self.tr("stolen lock"),
195 'B': self.tr('broken lock'), 219 "B": self.tr("broken lock"),
196 } 220 }
197 self.uptodate = { 221 self.uptodate = {
198 ' ': self.tr('yes'), 222 " ": self.tr("yes"),
199 '*': self.tr('no'), 223 "*": self.tr("no"),
200 } 224 }
201 225
202 self.rx_status = re.compile( 226 self.rx_status = re.compile(
203 '(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*') 227 "(.{8,9})\\s+([0-9-]+)\\s+([0-9?]+)\\s+(\\S+)\\s+(.+)\\s*"
228 )
204 # flags (8 or 9 anything), revision, changed rev, author, path 229 # flags (8 or 9 anything), revision, changed rev, author, path
205 self.rx_status2 = re.compile('(.{8,9})\\s+(.+)\\s*') 230 self.rx_status2 = re.compile("(.{8,9})\\s+(.+)\\s*")
206 # flags (8 or 9 anything), path 231 # flags (8 or 9 anything), path
207 self.rx_changelist = re.compile('--- \\S+ .([\\w\\s]+).:\\s+') 232 self.rx_changelist = re.compile("--- \\S+ .([\\w\\s]+).:\\s+")
208 # three dashes, Changelist (translated), quote, 233 # three dashes, Changelist (translated), quote,
209 # changelist name, quote, : 234 # changelist name, quote, :
210 235
211 self.__nonverbose = True 236 self.__nonverbose = True
212 237
213 def __resort(self): 238 def __resort(self):
214 """ 239 """
215 Private method to resort the tree. 240 Private method to resort the tree.
216 """ 241 """
217 self.statusList.sortItems( 242 self.statusList.sortItems(
218 self.statusList.sortColumn(), 243 self.statusList.sortColumn(), self.statusList.header().sortIndicatorOrder()
219 self.statusList.header().sortIndicatorOrder()) 244 )
220 245
221 def __resizeColumns(self): 246 def __resizeColumns(self):
222 """ 247 """
223 Private method to resize the list columns. 248 Private method to resize the list columns.
224 """ 249 """
225 self.statusList.header().resizeSections( 250 self.statusList.header().resizeSections(QHeaderView.ResizeMode.ResizeToContents)
226 QHeaderView.ResizeMode.ResizeToContents)
227 self.statusList.header().setStretchLastSection(True) 251 self.statusList.header().setStretchLastSection(True)
228 252
229 def __generateItem(self, status, propStatus, locked, history, switched, 253 def __generateItem(
230 lockinfo, uptodate, revision, change, author, path): 254 self,
255 status,
256 propStatus,
257 locked,
258 history,
259 switched,
260 lockinfo,
261 uptodate,
262 revision,
263 change,
264 author,
265 path,
266 ):
231 """ 267 """
232 Private method to generate a status item in the status list. 268 Private method to generate a status item in the status list.
233 269
234 @param status status indicator (string) 270 @param status status indicator (string)
235 @param propStatus property status indicator (string) 271 @param propStatus property status indicator (string)
236 @param locked locked indicator (string) 272 @param locked locked indicator (string)
237 @param history history indicator (string) 273 @param history history indicator (string)
238 @param switched switched indicator (string) 274 @param switched switched indicator (string)
242 @param change revision of last change (string) 278 @param change revision of last change (string)
243 @param author author of the last change (string) 279 @param author author of the last change (string)
244 @param path path of the file or directory (string) 280 @param path path of the file or directory (string)
245 """ 281 """
246 if ( 282 if (
247 self.__nonverbose and 283 self.__nonverbose
248 status == " " and 284 and status == " "
249 propStatus == " " and 285 and propStatus == " "
250 locked == " " and 286 and locked == " "
251 history == " " and 287 and history == " "
252 switched == " " and 288 and switched == " "
253 lockinfo == " " and 289 and lockinfo == " "
254 uptodate == " " and 290 and uptodate == " "
255 self.currentChangelist == "" 291 and self.currentChangelist == ""
256 ): 292 ):
257 return 293 return
258 294
259 if revision == "": 295 if revision == "":
260 rev = "" 296 rev = ""
261 else: 297 else:
262 try: 298 try:
263 rev = int(revision) 299 rev = int(revision)
269 try: 305 try:
270 chg = int(change) 306 chg = int(change)
271 except ValueError: 307 except ValueError:
272 chg = change 308 chg = change
273 statusText = self.status[status] 309 statusText = self.status[status]
274 310
275 itm = QTreeWidgetItem(self.statusList) 311 itm = QTreeWidgetItem(self.statusList)
276 itm.setData(0, Qt.ItemDataRole.DisplayRole, "") 312 itm.setData(0, Qt.ItemDataRole.DisplayRole, "")
277 itm.setData(1, Qt.ItemDataRole.DisplayRole, self.currentChangelist) 313 itm.setData(1, Qt.ItemDataRole.DisplayRole, self.currentChangelist)
278 itm.setData(2, Qt.ItemDataRole.DisplayRole, statusText) 314 itm.setData(2, Qt.ItemDataRole.DisplayRole, statusText)
279 itm.setData(3, Qt.ItemDataRole.DisplayRole, 315 itm.setData(3, Qt.ItemDataRole.DisplayRole, self.propStatus[propStatus])
280 self.propStatus[propStatus])
281 itm.setData(4, Qt.ItemDataRole.DisplayRole, self.locked[locked]) 316 itm.setData(4, Qt.ItemDataRole.DisplayRole, self.locked[locked])
282 itm.setData(5, Qt.ItemDataRole.DisplayRole, self.history[history]) 317 itm.setData(5, Qt.ItemDataRole.DisplayRole, self.history[history])
283 itm.setData(6, Qt.ItemDataRole.DisplayRole, self.switched[switched]) 318 itm.setData(6, Qt.ItemDataRole.DisplayRole, self.switched[switched])
284 itm.setData(7, Qt.ItemDataRole.DisplayRole, self.lockinfo[lockinfo]) 319 itm.setData(7, Qt.ItemDataRole.DisplayRole, self.lockinfo[lockinfo])
285 itm.setData(8, Qt.ItemDataRole.DisplayRole, self.uptodate[uptodate]) 320 itm.setData(8, Qt.ItemDataRole.DisplayRole, self.uptodate[uptodate])
286 itm.setData(9, Qt.ItemDataRole.DisplayRole, rev) 321 itm.setData(9, Qt.ItemDataRole.DisplayRole, rev)
287 itm.setData(10, Qt.ItemDataRole.DisplayRole, chg) 322 itm.setData(10, Qt.ItemDataRole.DisplayRole, chg)
288 itm.setData(11, Qt.ItemDataRole.DisplayRole, author) 323 itm.setData(11, Qt.ItemDataRole.DisplayRole, author)
289 itm.setData(12, Qt.ItemDataRole.DisplayRole, path) 324 itm.setData(12, Qt.ItemDataRole.DisplayRole, path)
290 325
291 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignLeft) 326 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignLeft)
292 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter) 327 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter)
293 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignHCenter) 328 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignHCenter)
294 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignHCenter) 329 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignHCenter)
295 itm.setTextAlignment(5, Qt.AlignmentFlag.AlignHCenter) 330 itm.setTextAlignment(5, Qt.AlignmentFlag.AlignHCenter)
298 itm.setTextAlignment(8, Qt.AlignmentFlag.AlignHCenter) 333 itm.setTextAlignment(8, Qt.AlignmentFlag.AlignHCenter)
299 itm.setTextAlignment(9, Qt.AlignmentFlag.AlignRight) 334 itm.setTextAlignment(9, Qt.AlignmentFlag.AlignRight)
300 itm.setTextAlignment(10, Qt.AlignmentFlag.AlignRight) 335 itm.setTextAlignment(10, Qt.AlignmentFlag.AlignRight)
301 itm.setTextAlignment(11, Qt.AlignmentFlag.AlignLeft) 336 itm.setTextAlignment(11, Qt.AlignmentFlag.AlignLeft)
302 itm.setTextAlignment(12, Qt.AlignmentFlag.AlignLeft) 337 itm.setTextAlignment(12, Qt.AlignmentFlag.AlignLeft)
303 338
304 if status in "ADM" or propStatus in "M": 339 if status in "ADM" or propStatus in "M":
305 itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable) 340 itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable)
306 itm.setCheckState(self.__toBeCommittedColumn, 341 itm.setCheckState(self.__toBeCommittedColumn, Qt.CheckState.Checked)
307 Qt.CheckState.Checked)
308 else: 342 else:
309 itm.setFlags(itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable) 343 itm.setFlags(itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable)
310 344
311 self.hidePropertyStatusColumn = ( 345 self.hidePropertyStatusColumn = (
312 self.hidePropertyStatusColumn and 346 self.hidePropertyStatusColumn and propStatus == " "
313 propStatus == " "
314 ) 347 )
315 self.hideLockColumns = ( 348 self.hideLockColumns = (
316 self.hideLockColumns and 349 self.hideLockColumns and locked == " " and lockinfo == " "
317 locked == " " and
318 lockinfo == " "
319 ) 350 )
320 self.hideUpToDateColumn = self.hideUpToDateColumn and uptodate == " " 351 self.hideUpToDateColumn = self.hideUpToDateColumn and uptodate == " "
321 self.hideHistoryColumn = self.hideHistoryColumn and history == " " 352 self.hideHistoryColumn = self.hideHistoryColumn and history == " "
322 self.hideSwitchedColumn = self.hideSwitchedColumn and switched == " " 353 self.hideSwitchedColumn = self.hideSwitchedColumn and switched == " "
323 354
324 if statusText not in self.__statusFilters: 355 if statusText not in self.__statusFilters:
325 self.__statusFilters.append(statusText) 356 self.__statusFilters.append(statusText)
326 357
327 def closeEvent(self, e): 358 def closeEvent(self, e):
328 """ 359 """
329 Protected slot implementing a close event handler. 360 Protected slot implementing a close event handler.
330 361
331 @param e close event (QCloseEvent) 362 @param e close event (QCloseEvent)
332 """ 363 """
333 if ( 364 if (
334 self.process is not None and 365 self.process is not None
335 self.process.state() != QProcess.ProcessState.NotRunning 366 and self.process.state() != QProcess.ProcessState.NotRunning
336 ): 367 ):
337 self.process.terminate() 368 self.process.terminate()
338 QTimer.singleShot(2000, self.process.kill) 369 QTimer.singleShot(2000, self.process.kill)
339 self.process.waitForFinished(3000) 370 self.process.waitForFinished(3000)
340 371
341 e.accept() 372 e.accept()
342 373
343 def start(self, fn): 374 def start(self, fn):
344 """ 375 """
345 Public slot to start the svn status command. 376 Public slot to start the svn status command.
346 377
347 @param fn filename(s)/directoryname(s) to show the status of 378 @param fn filename(s)/directoryname(s) to show the status of
348 (string or list of strings) 379 (string or list of strings)
349 """ 380 """
350 self.errorGroup.hide() 381 self.errorGroup.hide()
351 self.intercept = False 382 self.intercept = False
352 self.args = fn 383 self.args = fn
353 384
354 for act in self.menuactions: 385 for act in self.menuactions:
355 act.setEnabled(False) 386 act.setEnabled(False)
356 387
357 self.addButton.setEnabled(False) 388 self.addButton.setEnabled(False)
358 self.commitButton.setEnabled(False) 389 self.commitButton.setEnabled(False)
359 self.diffButton.setEnabled(False) 390 self.diffButton.setEnabled(False)
360 self.sbsDiffButton.setEnabled(False) 391 self.sbsDiffButton.setEnabled(False)
361 self.revertButton.setEnabled(False) 392 self.revertButton.setEnabled(False)
362 self.restoreButton.setEnabled(False) 393 self.restoreButton.setEnabled(False)
363 394
364 self.statusFilterCombo.clear() 395 self.statusFilterCombo.clear()
365 self.__statusFilters = [] 396 self.__statusFilters = []
366 self.statusList.clear() 397 self.statusList.clear()
367 398
368 self.currentChangelist = "" 399 self.currentChangelist = ""
369 self.changelistFound = False 400 self.changelistFound = False
370 401
371 self.hidePropertyStatusColumn = True 402 self.hidePropertyStatusColumn = True
372 self.hideLockColumns = True 403 self.hideLockColumns = True
373 self.hideUpToDateColumn = True 404 self.hideUpToDateColumn = True
374 self.hideHistoryColumn = True 405 self.hideHistoryColumn = True
375 self.hideSwitchedColumn = True 406 self.hideSwitchedColumn = True
376 407
377 self.process.kill() 408 self.process.kill()
378 409
379 args = [] 410 args = []
380 args.append('status') 411 args.append("status")
381 self.vcs.addArguments(args, self.vcs.options['global']) 412 self.vcs.addArguments(args, self.vcs.options["global"])
382 self.vcs.addArguments(args, self.vcs.options['status']) 413 self.vcs.addArguments(args, self.vcs.options["status"])
383 if ( 414 if (
384 '--verbose' not in self.vcs.options['global'] and 415 "--verbose" not in self.vcs.options["global"]
385 '--verbose' not in self.vcs.options['status'] 416 and "--verbose" not in self.vcs.options["status"]
386 ): 417 ):
387 args.append('--verbose') 418 args.append("--verbose")
388 self.__nonverbose = True 419 self.__nonverbose = True
389 else: 420 else:
390 self.__nonverbose = False 421 self.__nonverbose = False
391 if ( 422 if (
392 '--show-updates' in self.vcs.options['status'] or 423 "--show-updates" in self.vcs.options["status"]
393 '-u' in self.vcs.options['status'] 424 or "-u" in self.vcs.options["status"]
394 ): 425 ):
395 self.activateWindow() 426 self.activateWindow()
396 self.raise_() 427 self.raise_()
397 if isinstance(fn, list): 428 if isinstance(fn, list):
398 self.dname, fnames = self.vcs.splitPathList(fn) 429 self.dname, fnames = self.vcs.splitPathList(fn)
399 self.vcs.addArguments(args, fnames) 430 self.vcs.addArguments(args, fnames)
400 else: 431 else:
401 self.dname, fname = self.vcs.splitPath(fn) 432 self.dname, fname = self.vcs.splitPath(fn)
402 args.append(fname) 433 args.append(fname)
403 434
404 self.process.setWorkingDirectory(self.dname) 435 self.process.setWorkingDirectory(self.dname)
405 436
406 self.setWindowTitle(self.tr('Subversion Status')) 437 self.setWindowTitle(self.tr("Subversion Status"))
407 438
408 self.process.start('svn', args) 439 self.process.start("svn", args)
409 procStarted = self.process.waitForStarted(5000) 440 procStarted = self.process.waitForStarted(5000)
410 if not procStarted: 441 if not procStarted:
411 self.inputGroup.setEnabled(False) 442 self.inputGroup.setEnabled(False)
412 self.inputGroup.hide() 443 self.inputGroup.hide()
413 EricMessageBox.critical( 444 EricMessageBox.critical(
414 self, 445 self,
415 self.tr('Process Generation Error'), 446 self.tr("Process Generation Error"),
416 self.tr( 447 self.tr(
417 'The process {0} could not be started. ' 448 "The process {0} could not be started. "
418 'Ensure, that it is in the search path.' 449 "Ensure, that it is in the search path."
419 ).format('svn')) 450 ).format("svn"),
451 )
420 else: 452 else:
421 self.buttonBox.button( 453 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(
422 QDialogButtonBox.StandardButton.Close).setEnabled(False) 454 False
423 self.buttonBox.button( 455 )
424 QDialogButtonBox.StandardButton.Cancel).setEnabled(True) 456 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(
425 self.buttonBox.button( 457 True
426 QDialogButtonBox.StandardButton.Cancel).setDefault(True) 458 )
427 459 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setDefault(
460 True
461 )
462
428 self.inputGroup.setEnabled(True) 463 self.inputGroup.setEnabled(True)
429 self.inputGroup.show() 464 self.inputGroup.show()
430 self.refreshButton.setEnabled(False) 465 self.refreshButton.setEnabled(False)
431 466
432 def __finish(self): 467 def __finish(self):
433 """ 468 """
434 Private slot called when the process finished or the user pressed 469 Private slot called when the process finished or the user pressed
435 the button. 470 the button.
436 """ 471 """
437 if ( 472 if (
438 self.process is not None and 473 self.process is not None
439 self.process.state() != QProcess.ProcessState.NotRunning 474 and self.process.state() != QProcess.ProcessState.NotRunning
440 ): 475 ):
441 self.process.terminate() 476 self.process.terminate()
442 QTimer.singleShot(2000, self.process.kill) 477 QTimer.singleShot(2000, self.process.kill)
443 self.process.waitForFinished(3000) 478 self.process.waitForFinished(3000)
444 479
445 self.buttonBox.button( 480 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setEnabled(True)
446 QDialogButtonBox.StandardButton.Close).setEnabled(True) 481 self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
447 self.buttonBox.button( 482 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setDefault(True)
448 QDialogButtonBox.StandardButton.Cancel).setEnabled(False) 483 self.buttonBox.button(QDialogButtonBox.StandardButton.Close).setFocus(
449 self.buttonBox.button( 484 Qt.FocusReason.OtherFocusReason
450 QDialogButtonBox.StandardButton.Close).setDefault(True) 485 )
451 self.buttonBox.button( 486
452 QDialogButtonBox.StandardButton.Close).setFocus(
453 Qt.FocusReason.OtherFocusReason)
454
455 self.inputGroup.setEnabled(False) 487 self.inputGroup.setEnabled(False)
456 self.inputGroup.hide() 488 self.inputGroup.hide()
457 self.refreshButton.setEnabled(True) 489 self.refreshButton.setEnabled(True)
458 490
459 self.__statusFilters.sort() 491 self.__statusFilters.sort()
460 self.__statusFilters.insert(0, "<{0}>".format(self.tr("all"))) 492 self.__statusFilters.insert(0, "<{0}>".format(self.tr("all")))
461 self.statusFilterCombo.addItems(self.__statusFilters) 493 self.statusFilterCombo.addItems(self.__statusFilters)
462 494
463 for act in self.menuactions: 495 for act in self.menuactions:
464 act.setEnabled(True) 496 act.setEnabled(True)
465 497
466 self.__resort() 498 self.__resort()
467 self.__resizeColumns() 499 self.__resizeColumns()
468 500
469 self.statusList.setColumnHidden(self.__changelistColumn, 501 self.statusList.setColumnHidden(
470 not self.changelistFound) 502 self.__changelistColumn, not self.changelistFound
471 self.statusList.setColumnHidden(self.__propStatusColumn, 503 )
472 self.hidePropertyStatusColumn) 504 self.statusList.setColumnHidden(
473 self.statusList.setColumnHidden(self.__lockedColumn, 505 self.__propStatusColumn, self.hidePropertyStatusColumn
474 self.hideLockColumns) 506 )
475 self.statusList.setColumnHidden(self.__lockinfoColumn, 507 self.statusList.setColumnHidden(self.__lockedColumn, self.hideLockColumns)
476 self.hideLockColumns) 508 self.statusList.setColumnHidden(self.__lockinfoColumn, self.hideLockColumns)
477 self.statusList.setColumnHidden(self.__upToDateColumn, 509 self.statusList.setColumnHidden(self.__upToDateColumn, self.hideUpToDateColumn)
478 self.hideUpToDateColumn) 510 self.statusList.setColumnHidden(self.__historyColumn, self.hideHistoryColumn)
479 self.statusList.setColumnHidden(self.__historyColumn, 511 self.statusList.setColumnHidden(self.__switchedColumn, self.hideSwitchedColumn)
480 self.hideHistoryColumn) 512
481 self.statusList.setColumnHidden(self.__switchedColumn,
482 self.hideSwitchedColumn)
483
484 self.__updateButtons() 513 self.__updateButtons()
485 self.__updateCommitButton() 514 self.__updateCommitButton()
486 515
487 def on_buttonBox_clicked(self, button): 516 def on_buttonBox_clicked(self, button):
488 """ 517 """
489 Private slot called by a button of the button box clicked. 518 Private slot called by a button of the button box clicked.
490 519
491 @param button button that was clicked (QAbstractButton) 520 @param button button that was clicked (QAbstractButton)
492 """ 521 """
493 if button == self.buttonBox.button( 522 if button == self.buttonBox.button(QDialogButtonBox.StandardButton.Close):
494 QDialogButtonBox.StandardButton.Close
495 ):
496 self.close() 523 self.close()
497 elif button == self.buttonBox.button( 524 elif button == self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel):
498 QDialogButtonBox.StandardButton.Cancel
499 ):
500 self.__finish() 525 self.__finish()
501 elif button == self.refreshButton: 526 elif button == self.refreshButton:
502 self.on_refreshButton_clicked() 527 self.on_refreshButton_clicked()
503 528
504 def __procFinished(self, exitCode, exitStatus): 529 def __procFinished(self, exitCode, exitStatus):
505 """ 530 """
506 Private slot connected to the finished signal. 531 Private slot connected to the finished signal.
507 532
508 @param exitCode exit code of the process (integer) 533 @param exitCode exit code of the process (integer)
509 @param exitStatus exit status of the process (QProcess.ExitStatus) 534 @param exitStatus exit status of the process (QProcess.ExitStatus)
510 """ 535 """
511 self.__finish() 536 self.__finish()
512 537
513 def __readStdout(self): 538 def __readStdout(self):
514 """ 539 """
515 Private slot to handle the readyReadStandardOutput signal. 540 Private slot to handle the readyReadStandardOutput signal.
516 541
517 It reads the output of the process, formats it and inserts it into 542 It reads the output of the process, formats it and inserts it into
518 the contents pane. 543 the contents pane.
519 """ 544 """
520 if self.process is not None: 545 if self.process is not None:
521 self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput) 546 self.process.setReadChannel(QProcess.ProcessChannel.StandardOutput)
522 547
523 while self.process.canReadLine(): 548 while self.process.canReadLine():
524 s = str(self.process.readLine(), 549 s = str(
525 Preferences.getSystem("IOEncoding"), 550 self.process.readLine(),
526 'replace') 551 Preferences.getSystem("IOEncoding"),
552 "replace",
553 )
527 match = ( 554 match = (
528 self.rx_status.fullmatch(s) or 555 self.rx_status.fullmatch(s)
529 self.rx_status2.fullmatch(s) or 556 or self.rx_status2.fullmatch(s)
530 self.rx_changelist.fullmatch(s) 557 or self.rx_changelist.fullmatch(s)
531 ) 558 )
532 if match.re is self.rx_status: 559 if match.re is self.rx_status:
533 flags = match.group(1) 560 flags = match.group(1)
534 rev = match.group(2) 561 rev = match.group(2)
535 change = match.group(3) 562 change = match.group(3)
536 author = match.group(4) 563 author = match.group(4)
537 path = match.group(5).strip() 564 path = match.group(5).strip()
538 565
539 self.__generateItem(flags[0], flags[1], flags[2], flags[3], 566 self.__generateItem(
540 flags[4], flags[5], flags[-1], rev, 567 flags[0],
541 change, author, path) 568 flags[1],
569 flags[2],
570 flags[3],
571 flags[4],
572 flags[5],
573 flags[-1],
574 rev,
575 change,
576 author,
577 path,
578 )
542 elif match.re is self.rx_status2: 579 elif match.re is self.rx_status2:
543 flags = match.group(1) 580 flags = match.group(1)
544 path = match.group(2).strip() 581 path = match.group(2).strip()
545 582
546 if flags[-1] in self.uptodate: 583 if flags[-1] in self.uptodate:
547 self.__generateItem(flags[0], flags[1], flags[2], 584 self.__generateItem(
548 flags[3], flags[4], flags[5], 585 flags[0],
549 flags[-1], "", "", "", path) 586 flags[1],
587 flags[2],
588 flags[3],
589 flags[4],
590 flags[5],
591 flags[-1],
592 "",
593 "",
594 "",
595 path,
596 )
550 elif match.re is self.rx_changelist: 597 elif match.re is self.rx_changelist:
551 self.currentChangelist = match.group(1) 598 self.currentChangelist = match.group(1)
552 self.changelistFound = True 599 self.changelistFound = True
553 600
554 def __readStderr(self): 601 def __readStderr(self):
555 """ 602 """
556 Private slot to handle the readyReadStandardError signal. 603 Private slot to handle the readyReadStandardError signal.
557 604
558 It reads the error output of the process and inserts it into the 605 It reads the error output of the process and inserts it into the
559 error pane. 606 error pane.
560 """ 607 """
561 if self.process is not None: 608 if self.process is not None:
562 self.errorGroup.show() 609 self.errorGroup.show()
563 s = str(self.process.readAllStandardError(), 610 s = str(
564 Preferences.getSystem("IOEncoding"), 611 self.process.readAllStandardError(),
565 'replace') 612 Preferences.getSystem("IOEncoding"),
613 "replace",
614 )
566 self.errors.insertPlainText(s) 615 self.errors.insertPlainText(s)
567 self.errors.ensureCursorVisible() 616 self.errors.ensureCursorVisible()
568 617
569 def on_passwordCheckBox_toggled(self, isOn): 618 def on_passwordCheckBox_toggled(self, isOn):
570 """ 619 """
571 Private slot to handle the password checkbox toggled. 620 Private slot to handle the password checkbox toggled.
572 621
573 @param isOn flag indicating the status of the check box (boolean) 622 @param isOn flag indicating the status of the check box (boolean)
574 """ 623 """
575 if isOn: 624 if isOn:
576 self.input.setEchoMode(QLineEdit.EchoMode.Password) 625 self.input.setEchoMode(QLineEdit.EchoMode.Password)
577 else: 626 else:
578 self.input.setEchoMode(QLineEdit.EchoMode.Normal) 627 self.input.setEchoMode(QLineEdit.EchoMode.Normal)
579 628
580 @pyqtSlot() 629 @pyqtSlot()
581 def on_sendButton_clicked(self): 630 def on_sendButton_clicked(self):
582 """ 631 """
583 Private slot to send the input to the subversion process. 632 Private slot to send the input to the subversion process.
584 """ 633 """
585 inputTxt = self.input.text() 634 inputTxt = self.input.text()
586 inputTxt += os.linesep 635 inputTxt += os.linesep
587 636
588 if self.passwordCheckBox.isChecked(): 637 if self.passwordCheckBox.isChecked():
589 self.errors.insertPlainText(os.linesep) 638 self.errors.insertPlainText(os.linesep)
590 self.errors.ensureCursorVisible() 639 self.errors.ensureCursorVisible()
591 else: 640 else:
592 self.errors.insertPlainText(inputTxt) 641 self.errors.insertPlainText(inputTxt)
593 self.errors.ensureCursorVisible() 642 self.errors.ensureCursorVisible()
594 643
595 self.process.write(strToQByteArray(inputTxt)) 644 self.process.write(strToQByteArray(inputTxt))
596 645
597 self.passwordCheckBox.setChecked(False) 646 self.passwordCheckBox.setChecked(False)
598 self.input.clear() 647 self.input.clear()
599 648
600 def on_input_returnPressed(self): 649 def on_input_returnPressed(self):
601 """ 650 """
602 Private slot to handle the press of the return key in the input field. 651 Private slot to handle the press of the return key in the input field.
603 """ 652 """
604 self.intercept = True 653 self.intercept = True
605 self.on_sendButton_clicked() 654 self.on_sendButton_clicked()
606 655
607 def keyPressEvent(self, evt): 656 def keyPressEvent(self, evt):
608 """ 657 """
609 Protected slot to handle a key press event. 658 Protected slot to handle a key press event.
610 659
611 @param evt the key press event (QKeyEvent) 660 @param evt the key press event (QKeyEvent)
612 """ 661 """
613 if self.intercept: 662 if self.intercept:
614 self.intercept = False 663 self.intercept = False
615 evt.accept() 664 evt.accept()
616 return 665 return
617 super().keyPressEvent(evt) 666 super().keyPressEvent(evt)
618 667
619 @pyqtSlot() 668 @pyqtSlot()
620 def on_refreshButton_clicked(self): 669 def on_refreshButton_clicked(self):
621 """ 670 """
622 Private slot to refresh the status display. 671 Private slot to refresh the status display.
623 """ 672 """
624 self.start(self.args) 673 self.start(self.args)
625 674
626 def __updateButtons(self): 675 def __updateButtons(self):
627 """ 676 """
628 Private method to update the VCS buttons status. 677 Private method to update the VCS buttons status.
629 """ 678 """
630 modified = len(self.__getModifiedItems()) 679 modified = len(self.__getModifiedItems())
634 self.addButton.setEnabled(unversioned) 683 self.addButton.setEnabled(unversioned)
635 self.diffButton.setEnabled(modified) 684 self.diffButton.setEnabled(modified)
636 self.sbsDiffButton.setEnabled(modified == 1) 685 self.sbsDiffButton.setEnabled(modified == 1)
637 self.revertButton.setEnabled(modified) 686 self.revertButton.setEnabled(modified)
638 self.restoreButton.setEnabled(missing) 687 self.restoreButton.setEnabled(missing)
639 688
640 def __updateCommitButton(self): 689 def __updateCommitButton(self):
641 """ 690 """
642 Private method to update the Commit button status. 691 Private method to update the Commit button status.
643 """ 692 """
644 commitable = len(self.__getCommitableItems()) 693 commitable = len(self.__getCommitableItems())
645 self.commitButton.setEnabled(commitable) 694 self.commitButton.setEnabled(commitable)
646 695
647 @pyqtSlot(int) 696 @pyqtSlot(int)
648 def on_statusFilterCombo_activated(self, index): 697 def on_statusFilterCombo_activated(self, index):
649 """ 698 """
650 Private slot to react to the selection of a status filter. 699 Private slot to react to the selection of a status filter.
651 700
652 @param index index of the selected entry 701 @param index index of the selected entry
653 @type int 702 @type int
654 """ 703 """
655 txt = self.statusFilterCombo.itemText(index) 704 txt = self.statusFilterCombo.itemText(index)
656 if txt == "<{0}>".format(self.tr("all")): 705 if txt == "<{0}>".format(self.tr("all")):
659 topItem.setHidden(False) 708 topItem.setHidden(False)
660 else: 709 else:
661 for topIndex in range(self.statusList.topLevelItemCount()): 710 for topIndex in range(self.statusList.topLevelItemCount()):
662 topItem = self.statusList.topLevelItem(topIndex) 711 topItem = self.statusList.topLevelItem(topIndex)
663 topItem.setHidden(topItem.text(self.__statusColumn) != txt) 712 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
664 713
665 @pyqtSlot(QTreeWidgetItem, int) 714 @pyqtSlot(QTreeWidgetItem, int)
666 def on_statusList_itemChanged(self, item, column): 715 def on_statusList_itemChanged(self, item, column):
667 """ 716 """
668 Private slot to act upon item changes. 717 Private slot to act upon item changes.
669 718
670 @param item reference to the changed item (QTreeWidgetItem) 719 @param item reference to the changed item (QTreeWidgetItem)
671 @param column index of column that changed (integer) 720 @param column index of column that changed (integer)
672 """ 721 """
673 if column == self.__toBeCommittedColumn: 722 if column == self.__toBeCommittedColumn:
674 self.__updateCommitButton() 723 self.__updateCommitButton()
675 724
676 @pyqtSlot() 725 @pyqtSlot()
677 def on_statusList_itemSelectionChanged(self): 726 def on_statusList_itemSelectionChanged(self):
678 """ 727 """
679 Private slot to act upon changes of selected items. 728 Private slot to act upon changes of selected items.
680 """ 729 """
681 self.__updateButtons() 730 self.__updateButtons()
682 731
683 @pyqtSlot() 732 @pyqtSlot()
684 def on_commitButton_clicked(self): 733 def on_commitButton_clicked(self):
685 """ 734 """
686 Private slot to handle the press of the Commit button. 735 Private slot to handle the press of the Commit button.
687 """ 736 """
688 self.__commit() 737 self.__commit()
689 738
690 @pyqtSlot() 739 @pyqtSlot()
691 def on_addButton_clicked(self): 740 def on_addButton_clicked(self):
692 """ 741 """
693 Private slot to handle the press of the Add button. 742 Private slot to handle the press of the Add button.
694 """ 743 """
695 self.__add() 744 self.__add()
696 745
697 @pyqtSlot() 746 @pyqtSlot()
698 def on_diffButton_clicked(self): 747 def on_diffButton_clicked(self):
699 """ 748 """
700 Private slot to handle the press of the Differences button. 749 Private slot to handle the press of the Differences button.
701 """ 750 """
702 self.__diff() 751 self.__diff()
703 752
704 @pyqtSlot() 753 @pyqtSlot()
705 def on_sbsDiffButton_clicked(self): 754 def on_sbsDiffButton_clicked(self):
706 """ 755 """
707 Private slot to handle the press of the Side-by-Side Diff button. 756 Private slot to handle the press of the Side-by-Side Diff button.
708 """ 757 """
709 self.__sbsDiff() 758 self.__sbsDiff()
710 759
711 @pyqtSlot() 760 @pyqtSlot()
712 def on_revertButton_clicked(self): 761 def on_revertButton_clicked(self):
713 """ 762 """
714 Private slot to handle the press of the Revert button. 763 Private slot to handle the press of the Revert button.
715 """ 764 """
716 self.__revert() 765 self.__revert()
717 766
718 @pyqtSlot() 767 @pyqtSlot()
719 def on_restoreButton_clicked(self): 768 def on_restoreButton_clicked(self):
720 """ 769 """
721 Private slot to handle the press of the Restore button. 770 Private slot to handle the press of the Restore button.
722 """ 771 """
723 self.__restoreMissing() 772 self.__restoreMissing()
724 773
725 ########################################################################### 774 ###########################################################################
726 ## Context menu handling methods 775 ## Context menu handling methods
727 ########################################################################### 776 ###########################################################################
728 777
729 def __showContextMenu(self, coord): 778 def __showContextMenu(self, coord):
730 """ 779 """
731 Private slot to show the context menu of the status list. 780 Private slot to show the context menu of the status list.
732 781
733 @param coord the position of the mouse pointer (QPoint) 782 @param coord the position of the mouse pointer (QPoint)
734 """ 783 """
735 self.menu.popup(self.statusList.mapToGlobal(coord)) 784 self.menu.popup(self.statusList.mapToGlobal(coord))
736 785
737 def __commit(self): 786 def __commit(self):
738 """ 787 """
739 Private slot to handle the Commit context menu entry. 788 Private slot to handle the Commit context menu entry.
740 """ 789 """
741 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 790 names = [
742 for itm in self.__getCommitableItems()] 791 os.path.join(self.dname, itm.text(self.__pathColumn))
792 for itm in self.__getCommitableItems()
793 ]
743 if not names: 794 if not names:
744 EricMessageBox.information( 795 EricMessageBox.information(
745 self, 796 self,
746 self.tr("Commit"), 797 self.tr("Commit"),
747 self.tr("""There are no entries selected to be""" 798 self.tr("""There are no entries selected to be""" """ committed."""),
748 """ committed.""")) 799 )
749 return 800 return
750 801
751 if Preferences.getVCS("AutoSaveFiles"): 802 if Preferences.getVCS("AutoSaveFiles"):
752 vm = ericApp().getObject("ViewManager") 803 vm = ericApp().getObject("ViewManager")
753 for name in names: 804 for name in names:
754 vm.saveEditor(name) 805 vm.saveEditor(name)
755 self.vcs.vcsCommit(names, '') 806 self.vcs.vcsCommit(names, "")
756 807
757 def __committed(self): 808 def __committed(self):
758 """ 809 """
759 Private slot called after the commit has finished. 810 Private slot called after the commit has finished.
760 """ 811 """
761 if self.isVisible(): 812 if self.isVisible():
762 self.on_refreshButton_clicked() 813 self.on_refreshButton_clicked()
763 self.vcs.checkVCSStatus() 814 self.vcs.checkVCSStatus()
764 815
765 def __commitSelectAll(self): 816 def __commitSelectAll(self):
766 """ 817 """
767 Private slot to select all entries for commit. 818 Private slot to select all entries for commit.
768 """ 819 """
769 self.__commitSelect(True) 820 self.__commitSelect(True)
770 821
771 def __commitDeselectAll(self): 822 def __commitDeselectAll(self):
772 """ 823 """
773 Private slot to deselect all entries from commit. 824 Private slot to deselect all entries from commit.
774 """ 825 """
775 self.__commitSelect(False) 826 self.__commitSelect(False)
776 827
777 def __add(self): 828 def __add(self):
778 """ 829 """
779 Private slot to handle the Add context menu entry. 830 Private slot to handle the Add context menu entry.
780 """ 831 """
781 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 832 names = [
782 for itm in self.__getUnversionedItems()] 833 os.path.join(self.dname, itm.text(self.__pathColumn))
834 for itm in self.__getUnversionedItems()
835 ]
783 if not names: 836 if not names:
784 EricMessageBox.information( 837 EricMessageBox.information(
785 self, 838 self,
786 self.tr("Add"), 839 self.tr("Add"),
787 self.tr("""There are no unversioned entries""" 840 self.tr(
788 """ available/selected.""")) 841 """There are no unversioned entries""" """ available/selected."""
789 return 842 ),
790 843 )
844 return
845
791 self.vcs.vcsAdd(names) 846 self.vcs.vcsAdd(names)
792 self.on_refreshButton_clicked() 847 self.on_refreshButton_clicked()
793 848
794 project = ericApp().getObject("Project") 849 project = ericApp().getObject("Project")
795 for name in names: 850 for name in names:
796 project.getModel().updateVCSStatus(name) 851 project.getModel().updateVCSStatus(name)
797 self.vcs.checkVCSStatus() 852 self.vcs.checkVCSStatus()
798 853
799 def __revert(self): 854 def __revert(self):
800 """ 855 """
801 Private slot to handle the Revert context menu entry. 856 Private slot to handle the Revert context menu entry.
802 """ 857 """
803 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 858 names = [
804 for itm in self.__getModifiedItems()] 859 os.path.join(self.dname, itm.text(self.__pathColumn))
860 for itm in self.__getModifiedItems()
861 ]
805 if not names: 862 if not names:
806 EricMessageBox.information( 863 EricMessageBox.information(
807 self, 864 self,
808 self.tr("Revert"), 865 self.tr("Revert"),
809 self.tr("""There are no uncommitted changes""" 866 self.tr(
810 """ available/selected.""")) 867 """There are no uncommitted changes""" """ available/selected."""
811 return 868 ),
812 869 )
870 return
871
813 self.vcs.vcsRevert(names) 872 self.vcs.vcsRevert(names)
814 self.raise_() 873 self.raise_()
815 self.activateWindow() 874 self.activateWindow()
816 self.on_refreshButton_clicked() 875 self.on_refreshButton_clicked()
817 876
818 project = ericApp().getObject("Project") 877 project = ericApp().getObject("Project")
819 for name in names: 878 for name in names:
820 project.getModel().updateVCSStatus(name) 879 project.getModel().updateVCSStatus(name)
821 self.vcs.checkVCSStatus() 880 self.vcs.checkVCSStatus()
822 881
823 def __restoreMissing(self): 882 def __restoreMissing(self):
824 """ 883 """
825 Private slot to handle the Restore Missing context menu entry. 884 Private slot to handle the Restore Missing context menu entry.
826 """ 885 """
827 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 886 names = [
828 for itm in self.__getMissingItems()] 887 os.path.join(self.dname, itm.text(self.__pathColumn))
888 for itm in self.__getMissingItems()
889 ]
829 if not names: 890 if not names:
830 EricMessageBox.information( 891 EricMessageBox.information(
831 self, 892 self,
832 self.tr("Revert"), 893 self.tr("Revert"),
833 self.tr("""There are no missing entries""" 894 self.tr("""There are no missing entries""" """ available/selected."""),
834 """ available/selected.""")) 895 )
835 return 896 return
836 897
837 self.vcs.vcsRevert(names) 898 self.vcs.vcsRevert(names)
838 self.on_refreshButton_clicked() 899 self.on_refreshButton_clicked()
839 self.vcs.checkVCSStatus() 900 self.vcs.checkVCSStatus()
840 901
841 def __diff(self): 902 def __diff(self):
842 """ 903 """
843 Private slot to handle the Diff context menu entry. 904 Private slot to handle the Diff context menu entry.
844 """ 905 """
845 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 906 names = [
846 for itm in self.__getModifiedItems()] 907 os.path.join(self.dname, itm.text(self.__pathColumn))
908 for itm in self.__getModifiedItems()
909 ]
847 if not names: 910 if not names:
848 EricMessageBox.information( 911 EricMessageBox.information(
849 self, 912 self,
850 self.tr("Differences"), 913 self.tr("Differences"),
851 self.tr("""There are no uncommitted changes""" 914 self.tr(
852 """ available/selected.""")) 915 """There are no uncommitted changes""" """ available/selected."""
853 return 916 ),
854 917 )
918 return
919
855 if self.diff is None: 920 if self.diff is None:
856 from .SvnDiffDialog import SvnDiffDialog 921 from .SvnDiffDialog import SvnDiffDialog
922
857 self.diff = SvnDiffDialog(self.vcs) 923 self.diff = SvnDiffDialog(self.vcs)
858 self.diff.show() 924 self.diff.show()
859 QApplication.processEvents() 925 QApplication.processEvents()
860 self.diff.start(names, refreshable=True) 926 self.diff.start(names, refreshable=True)
861 927
862 def __sbsDiff(self): 928 def __sbsDiff(self):
863 """ 929 """
864 Private slot to handle the Side-by-Side Diff context menu entry. 930 Private slot to handle the Side-by-Side Diff context menu entry.
865 """ 931 """
866 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 932 names = [
867 for itm in self.__getModifiedItems()] 933 os.path.join(self.dname, itm.text(self.__pathColumn))
934 for itm in self.__getModifiedItems()
935 ]
868 if not names: 936 if not names:
869 EricMessageBox.information( 937 EricMessageBox.information(
870 self, 938 self,
871 self.tr("Side-by-Side Diff"), 939 self.tr("Side-by-Side Diff"),
872 self.tr("""There are no uncommitted changes""" 940 self.tr(
873 """ available/selected.""")) 941 """There are no uncommitted changes""" """ available/selected."""
942 ),
943 )
874 return 944 return
875 elif len(names) > 1: 945 elif len(names) > 1:
876 EricMessageBox.information( 946 EricMessageBox.information(
877 self, 947 self,
878 self.tr("Side-by-Side Diff"), 948 self.tr("Side-by-Side Diff"),
879 self.tr("""Only one file with uncommitted changes""" 949 self.tr(
880 """ must be selected.""")) 950 """Only one file with uncommitted changes"""
881 return 951 """ must be selected."""
882 952 ),
953 )
954 return
955
883 self.vcs.vcsSbsDiff(names[0]) 956 self.vcs.vcsSbsDiff(names[0])
884 957
885 def __lock(self): 958 def __lock(self):
886 """ 959 """
887 Private slot to handle the Lock context menu entry. 960 Private slot to handle the Lock context menu entry.
888 """ 961 """
889 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 962 names = [
890 for itm in self.__getLockActionItems(self.unlockedIndicators)] 963 os.path.join(self.dname, itm.text(self.__pathColumn))
964 for itm in self.__getLockActionItems(self.unlockedIndicators)
965 ]
891 if not names: 966 if not names:
892 EricMessageBox.information( 967 EricMessageBox.information(
893 self, 968 self,
894 self.tr("Lock"), 969 self.tr("Lock"),
895 self.tr("""There are no unlocked files""" 970 self.tr("""There are no unlocked files""" """ available/selected."""),
896 """ available/selected.""")) 971 )
897 return 972 return
898 973
899 self.vcs.svnLock(names, parent=self) 974 self.vcs.svnLock(names, parent=self)
900 self.on_refreshButton_clicked() 975 self.on_refreshButton_clicked()
901 976
902 def __unlock(self): 977 def __unlock(self):
903 """ 978 """
904 Private slot to handle the Unlock context menu entry. 979 Private slot to handle the Unlock context menu entry.
905 """ 980 """
906 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 981 names = [
907 for itm in self.__getLockActionItems(self.lockedIndicators)] 982 os.path.join(self.dname, itm.text(self.__pathColumn))
983 for itm in self.__getLockActionItems(self.lockedIndicators)
984 ]
908 if not names: 985 if not names:
909 EricMessageBox.information( 986 EricMessageBox.information(
910 self, 987 self,
911 self.tr("Unlock"), 988 self.tr("Unlock"),
912 self.tr("""There are no locked files""" 989 self.tr("""There are no locked files""" """ available/selected."""),
913 """ available/selected.""")) 990 )
914 return 991 return
915 992
916 self.vcs.svnUnlock(names, parent=self) 993 self.vcs.svnUnlock(names, parent=self)
917 self.on_refreshButton_clicked() 994 self.on_refreshButton_clicked()
918 995
919 def __breakLock(self): 996 def __breakLock(self):
920 """ 997 """
921 Private slot to handle the Break Lock context menu entry. 998 Private slot to handle the Break Lock context menu entry.
922 """ 999 """
923 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 1000 names = [
924 for itm in self.__getLockActionItems( 1001 os.path.join(self.dname, itm.text(self.__pathColumn))
925 self.stealBreakLockIndicators)] 1002 for itm in self.__getLockActionItems(self.stealBreakLockIndicators)
1003 ]
926 if not names: 1004 if not names:
927 EricMessageBox.information( 1005 EricMessageBox.information(
928 self, 1006 self,
929 self.tr("Break Lock"), 1007 self.tr("Break Lock"),
930 self.tr("""There are no locked files""" 1008 self.tr("""There are no locked files""" """ available/selected."""),
931 """ available/selected.""")) 1009 )
932 return 1010 return
933 1011
934 self.vcs.svnUnlock(names, parent=self, breakIt=True) 1012 self.vcs.svnUnlock(names, parent=self, breakIt=True)
935 self.on_refreshButton_clicked() 1013 self.on_refreshButton_clicked()
936 1014
937 def __stealLock(self): 1015 def __stealLock(self):
938 """ 1016 """
939 Private slot to handle the Break Lock context menu entry. 1017 Private slot to handle the Break Lock context menu entry.
940 """ 1018 """
941 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 1019 names = [
942 for itm in self.__getLockActionItems( 1020 os.path.join(self.dname, itm.text(self.__pathColumn))
943 self.stealBreakLockIndicators)] 1021 for itm in self.__getLockActionItems(self.stealBreakLockIndicators)
1022 ]
944 if not names: 1023 if not names:
945 EricMessageBox.information( 1024 EricMessageBox.information(
946 self, 1025 self,
947 self.tr("Steal Lock"), 1026 self.tr("Steal Lock"),
948 self.tr("""There are no locked files""" 1027 self.tr("""There are no locked files""" """ available/selected."""),
949 """ available/selected.""")) 1028 )
950 return 1029 return
951 1030
952 self.vcs.svnLock(names, parent=self, stealIt=True) 1031 self.vcs.svnLock(names, parent=self, stealIt=True)
953 self.on_refreshButton_clicked() 1032 self.on_refreshButton_clicked()
954 1033
955 def __addToChangelist(self): 1034 def __addToChangelist(self):
956 """ 1035 """
957 Private slot to add entries to a changelist. 1036 Private slot to add entries to a changelist.
958 """ 1037 """
959 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 1038 names = [
960 for itm in self.__getNonChangelistItems()] 1039 os.path.join(self.dname, itm.text(self.__pathColumn))
1040 for itm in self.__getNonChangelistItems()
1041 ]
961 if not names: 1042 if not names:
962 EricMessageBox.information( 1043 EricMessageBox.information(
963 self, 1044 self,
964 self.tr("Remove from Changelist"), 1045 self.tr("Remove from Changelist"),
965 self.tr( 1046 self.tr(
966 """There are no files available/selected not """ 1047 """There are no files available/selected not """
967 """belonging to a changelist.""" 1048 """belonging to a changelist."""
968 ) 1049 ),
969 ) 1050 )
970 return 1051 return
971 self.vcs.svnAddToChangelist(names) 1052 self.vcs.svnAddToChangelist(names)
972 self.on_refreshButton_clicked() 1053 self.on_refreshButton_clicked()
973 1054
974 def __removeFromChangelist(self): 1055 def __removeFromChangelist(self):
975 """ 1056 """
976 Private slot to remove entries from their changelists. 1057 Private slot to remove entries from their changelists.
977 """ 1058 """
978 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 1059 names = [
979 for itm in self.__getChangelistItems()] 1060 os.path.join(self.dname, itm.text(self.__pathColumn))
1061 for itm in self.__getChangelistItems()
1062 ]
980 if not names: 1063 if not names:
981 EricMessageBox.information( 1064 EricMessageBox.information(
982 self, 1065 self,
983 self.tr("Remove from Changelist"), 1066 self.tr("Remove from Changelist"),
984 self.tr( 1067 self.tr(
985 """There are no files available/selected belonging""" 1068 """There are no files available/selected belonging"""
986 """ to a changelist.""" 1069 """ to a changelist."""
987 ) 1070 ),
988 ) 1071 )
989 return 1072 return
990 self.vcs.svnRemoveFromChangelist(names) 1073 self.vcs.svnRemoveFromChangelist(names)
991 self.on_refreshButton_clicked() 1074 self.on_refreshButton_clicked()
992 1075
993 def __getCommitableItems(self): 1076 def __getCommitableItems(self):
994 """ 1077 """
995 Private method to retrieve all entries the user wants to commit. 1078 Private method to retrieve all entries the user wants to commit.
996 1079
997 @return list of all items, the user has checked 1080 @return list of all items, the user has checked
998 """ 1081 """
999 commitableItems = [] 1082 commitableItems = []
1000 for index in range(self.statusList.topLevelItemCount()): 1083 for index in range(self.statusList.topLevelItemCount()):
1001 itm = self.statusList.topLevelItem(index) 1084 itm = self.statusList.topLevelItem(index)
1002 if ( 1085 if itm.checkState(self.__toBeCommittedColumn) == Qt.CheckState.Checked:
1003 itm.checkState(self.__toBeCommittedColumn) ==
1004 Qt.CheckState.Checked
1005 ):
1006 commitableItems.append(itm) 1086 commitableItems.append(itm)
1007 return commitableItems 1087 return commitableItems
1008 1088
1009 def __getModifiedItems(self): 1089 def __getModifiedItems(self):
1010 """ 1090 """
1011 Private method to retrieve all entries, that have a modified status. 1091 Private method to retrieve all entries, that have a modified status.
1012 1092
1013 @return list of all items with a modified status 1093 @return list of all items with a modified status
1014 """ 1094 """
1015 modifiedItems = [] 1095 modifiedItems = []
1016 for itm in self.statusList.selectedItems(): 1096 for itm in self.statusList.selectedItems():
1017 if ( 1097 if (
1018 itm.text(self.__statusColumn) in self.modifiedIndicators or 1098 itm.text(self.__statusColumn) in self.modifiedIndicators
1019 itm.text(self.__propStatusColumn) in self.modifiedIndicators 1099 or itm.text(self.__propStatusColumn) in self.modifiedIndicators
1020 ): 1100 ):
1021 modifiedItems.append(itm) 1101 modifiedItems.append(itm)
1022 return modifiedItems 1102 return modifiedItems
1023 1103
1024 def __getUnversionedItems(self): 1104 def __getUnversionedItems(self):
1025 """ 1105 """
1026 Private method to retrieve all entries, that have an unversioned 1106 Private method to retrieve all entries, that have an unversioned
1027 status. 1107 status.
1028 1108
1029 @return list of all items with an unversioned status 1109 @return list of all items with an unversioned status
1030 """ 1110 """
1031 unversionedItems = [] 1111 unversionedItems = []
1032 for itm in self.statusList.selectedItems(): 1112 for itm in self.statusList.selectedItems():
1033 if itm.text(self.__statusColumn) in self.unversionedIndicators: 1113 if itm.text(self.__statusColumn) in self.unversionedIndicators:
1034 unversionedItems.append(itm) 1114 unversionedItems.append(itm)
1035 return unversionedItems 1115 return unversionedItems
1036 1116
1037 def __getMissingItems(self): 1117 def __getMissingItems(self):
1038 """ 1118 """
1039 Private method to retrieve all entries, that have a missing status. 1119 Private method to retrieve all entries, that have a missing status.
1040 1120
1041 @return list of all items with a missing status 1121 @return list of all items with a missing status
1042 """ 1122 """
1043 missingItems = [] 1123 missingItems = []
1044 for itm in self.statusList.selectedItems(): 1124 for itm in self.statusList.selectedItems():
1045 if itm.text(self.__statusColumn) in self.missingIndicators: 1125 if itm.text(self.__statusColumn) in self.missingIndicators:
1046 missingItems.append(itm) 1126 missingItems.append(itm)
1047 return missingItems 1127 return missingItems
1048 1128
1049 def __getLockActionItems(self, indicators): 1129 def __getLockActionItems(self, indicators):
1050 """ 1130 """
1051 Private method to retrieve all emtries, that have a locked status. 1131 Private method to retrieve all emtries, that have a locked status.
1052 1132
1053 @param indicators list of indicators to check against (list of strings) 1133 @param indicators list of indicators to check against (list of strings)
1054 @return list of all items with a locked status 1134 @return list of all items with a locked status
1055 """ 1135 """
1056 lockitems = [] 1136 lockitems = []
1057 for itm in self.statusList.selectedItems(): 1137 for itm in self.statusList.selectedItems():
1058 if itm.text(self.__lockinfoColumn) in indicators: 1138 if itm.text(self.__lockinfoColumn) in indicators:
1059 lockitems.append(itm) 1139 lockitems.append(itm)
1060 return lockitems 1140 return lockitems
1061 1141
1062 def __getChangelistItems(self): 1142 def __getChangelistItems(self):
1063 """ 1143 """
1064 Private method to retrieve all entries, that are members of 1144 Private method to retrieve all entries, that are members of
1065 a changelist. 1145 a changelist.
1066 1146
1067 @return list of all items belonging to a changelist 1147 @return list of all items belonging to a changelist
1068 """ 1148 """
1069 clitems = [] 1149 clitems = []
1070 for itm in self.statusList.selectedItems(): 1150 for itm in self.statusList.selectedItems():
1071 if itm.text(self.__changelistColumn) != "": 1151 if itm.text(self.__changelistColumn) != "":
1072 clitems.append(itm) 1152 clitems.append(itm)
1073 return clitems 1153 return clitems
1074 1154
1075 def __getNonChangelistItems(self): 1155 def __getNonChangelistItems(self):
1076 """ 1156 """
1077 Private method to retrieve all entries, that are not members of 1157 Private method to retrieve all entries, that are not members of
1078 a changelist. 1158 a changelist.
1079 1159
1080 @return list of all items not belonging to a changelist 1160 @return list of all items not belonging to a changelist
1081 """ 1161 """
1082 clitems = [] 1162 clitems = []
1083 for itm in self.statusList.selectedItems(): 1163 for itm in self.statusList.selectedItems():
1084 if itm.text(self.__changelistColumn) == "": 1164 if itm.text(self.__changelistColumn) == "":
1085 clitems.append(itm) 1165 clitems.append(itm)
1086 return clitems 1166 return clitems
1087 1167
1088 def __commitSelect(self, selected): 1168 def __commitSelect(self, selected):
1089 """ 1169 """
1090 Private slot to select or deselect all entries. 1170 Private slot to select or deselect all entries.
1091 1171
1092 @param selected commit selection state to be set (boolean) 1172 @param selected commit selection state to be set (boolean)
1093 """ 1173 """
1094 for index in range(self.statusList.topLevelItemCount()): 1174 for index in range(self.statusList.topLevelItemCount()):
1095 itm = self.statusList.topLevelItem(index) 1175 itm = self.statusList.topLevelItem(index)
1096 if ( 1176 if (
1097 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable == 1177 itm.flags() & Qt.ItemFlag.ItemIsUserCheckable
1098 Qt.ItemFlag.ItemIsUserCheckable 1178 == Qt.ItemFlag.ItemIsUserCheckable
1099 ): 1179 ):
1100 if selected: 1180 if selected:
1101 itm.setCheckState(self.__toBeCommittedColumn, 1181 itm.setCheckState(self.__toBeCommittedColumn, Qt.CheckState.Checked)
1102 Qt.CheckState.Checked)
1103 else: 1182 else:
1104 itm.setCheckState(self.__toBeCommittedColumn, 1183 itm.setCheckState(
1105 Qt.CheckState.Unchecked) 1184 self.__toBeCommittedColumn, Qt.CheckState.Unchecked
1185 )

eric ide

mercurial