eric7/Plugins/VcsPlugins/vcsPySvn/SvnStatusDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8234
fcb6b4b96274
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2003 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show the output of the svn status command
8 process.
9 """
10
11 import os
12
13 import pysvn
14
15 from PyQt5.QtCore import Qt, pyqtSlot
16 from PyQt5.QtWidgets import (
17 QWidget, QHeaderView, QApplication, QMenu, QDialogButtonBox,
18 QTreeWidgetItem
19 )
20
21 from E5Gui.E5Application import e5App
22 from E5Gui import E5MessageBox
23 from E5Gui.E5OverrideCursor import E5OverrideCursor
24
25 from E5Utilities.E5MutexLocker import E5MutexLocker
26
27 from .SvnConst import svnStatusMap
28 from .SvnDialogMixin import SvnDialogMixin
29
30 from .Ui_SvnStatusDialog import Ui_SvnStatusDialog
31
32 import Preferences
33 import Utilities
34
35
36 class SvnStatusDialog(QWidget, SvnDialogMixin, Ui_SvnStatusDialog):
37 """
38 Class implementing a dialog to show the output of the svn status command
39 process.
40 """
41 def __init__(self, vcs, parent=None):
42 """
43 Constructor
44
45 @param vcs reference to the vcs object
46 @param parent parent widget (QWidget)
47 """
48 super().__init__(parent)
49 self.setupUi(self)
50 SvnDialogMixin.__init__(self)
51
52 self.__toBeCommittedColumn = 0
53 self.__changelistColumn = 1
54 self.__statusColumn = 2
55 self.__propStatusColumn = 3
56 self.__lockedColumn = 4
57 self.__historyColumn = 5
58 self.__switchedColumn = 6
59 self.__lockinfoColumn = 7
60 self.__upToDateColumn = 8
61 self.__pathColumn = 12
62 self.__lastColumn = self.statusList.columnCount()
63
64 self.refreshButton = self.buttonBox.addButton(
65 self.tr("Refresh"), QDialogButtonBox.ButtonRole.ActionRole)
66 self.refreshButton.setToolTip(
67 self.tr("Press to refresh the status display"))
68 self.refreshButton.setEnabled(False)
69 self.buttonBox.button(
70 QDialogButtonBox.StandardButton.Close).setEnabled(False)
71 self.buttonBox.button(
72 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
73
74 self.diff = None
75 self.vcs = vcs
76 self.vcs.committed.connect(self.__committed)
77
78 self.statusList.headerItem().setText(self.__lastColumn, "")
79 self.statusList.header().setSortIndicator(self.__pathColumn,
80 Qt.SortOrder.AscendingOrder)
81 if pysvn.svn_version < (1, 5, 0) or pysvn.version < (1, 6, 0):
82 self.statusList.header().hideSection(self.__changelistColumn)
83
84 self.menuactions = []
85 self.menu = QMenu()
86 self.menuactions.append(self.menu.addAction(
87 self.tr("Commit changes to repository..."), self.__commit))
88 self.menuactions.append(self.menu.addAction(
89 self.tr("Select all for commit"), self.__commitSelectAll))
90 self.menuactions.append(self.menu.addAction(
91 self.tr("Deselect all from commit"), self.__commitDeselectAll))
92 self.menu.addSeparator()
93 self.menuactions.append(self.menu.addAction(
94 self.tr("Add to repository"), self.__add))
95 self.menuactions.append(self.menu.addAction(
96 self.tr("Show differences"), self.__diff))
97 self.menuactions.append(self.menu.addAction(
98 self.tr("Show differences side-by-side"), self.__sbsDiff))
99 self.menuactions.append(self.menu.addAction(
100 self.tr("Revert changes"), self.__revert))
101 self.menuactions.append(self.menu.addAction(
102 self.tr("Restore missing"), self.__restoreMissing))
103 if pysvn.svn_version >= (1, 5, 0) and pysvn.version >= (1, 6, 0):
104 self.menu.addSeparator()
105 self.menuactions.append(self.menu.addAction(
106 self.tr("Add to Changelist"), self.__addToChangelist))
107 self.menuactions.append(self.menu.addAction(
108 self.tr("Remove from Changelist"),
109 self.__removeFromChangelist))
110 if self.vcs.version >= (1, 2, 0):
111 self.menu.addSeparator()
112 self.menuactions.append(
113 self.menu.addAction(self.tr("Lock"), self.__lock))
114 self.menuactions.append(
115 self.menu.addAction(self.tr("Unlock"), self.__unlock))
116 self.menuactions.append(self.menu.addAction(
117 self.tr("Break lock"),
118 self.__breakLock))
119 self.menuactions.append(self.menu.addAction(
120 self.tr("Steal lock"),
121 self.__stealLock))
122 self.menu.addSeparator()
123 self.menuactions.append(self.menu.addAction(
124 self.tr("Adjust column sizes"),
125 self.__resizeColumns))
126 for act in self.menuactions:
127 act.setEnabled(False)
128
129 self.statusList.setContextMenuPolicy(
130 Qt.ContextMenuPolicy.CustomContextMenu)
131 self.statusList.customContextMenuRequested.connect(
132 self.__showContextMenu)
133
134 self.modifiedIndicators = [
135 self.tr(svnStatusMap[pysvn.wc_status_kind.added]),
136 self.tr(svnStatusMap[pysvn.wc_status_kind.deleted]),
137 self.tr(svnStatusMap[pysvn.wc_status_kind.modified])
138 ]
139
140 self.missingIndicators = [
141 self.tr(svnStatusMap[pysvn.wc_status_kind.missing]),
142 ]
143
144 self.unversionedIndicators = [
145 self.tr(svnStatusMap[pysvn.wc_status_kind.unversioned]),
146 ]
147
148 self.lockedIndicators = [
149 self.tr('locked'),
150 ]
151
152 self.stealBreakLockIndicators = [
153 self.tr('other lock'),
154 self.tr('stolen lock'),
155 self.tr('broken lock'),
156 ]
157
158 self.unlockedIndicators = [
159 self.tr('not locked'),
160 ]
161
162 self.lockinfo = {
163 ' ': self.tr('not locked'),
164 'L': self.tr('locked'),
165 'O': self.tr('other lock'),
166 'S': self.tr('stolen lock'),
167 'B': self.tr('broken lock'),
168 }
169 self.yesno = [
170 self.tr('no'),
171 self.tr('yes'),
172 ]
173
174 self.client = self.vcs.getClient()
175 self.client.callback_cancel = self._clientCancelCallback
176 self.client.callback_get_login = self._clientLoginCallback
177 self.client.callback_ssl_server_trust_prompt = (
178 self._clientSslServerTrustPromptCallback
179 )
180
181 self.show()
182 QApplication.processEvents()
183
184 def __resort(self):
185 """
186 Private method to resort the tree.
187 """
188 self.statusList.sortItems(
189 self.statusList.sortColumn(),
190 self.statusList.header().sortIndicatorOrder())
191
192 def __resizeColumns(self):
193 """
194 Private method to resize the list columns.
195 """
196 self.statusList.header().resizeSections(
197 QHeaderView.ResizeMode.ResizeToContents)
198 self.statusList.header().setStretchLastSection(True)
199
200 def __generateItem(self, changelist, status, propStatus, locked, history,
201 switched, lockinfo, uptodate, revision, change, author,
202 path):
203 """
204 Private method to generate a status item in the status list.
205
206 @param changelist name of the changelist (string)
207 @param status text status (pysvn.wc_status_kind)
208 @param propStatus property status (pysvn.wc_status_kind)
209 @param locked locked flag (boolean)
210 @param history history flag (boolean)
211 @param switched switched flag (boolean)
212 @param lockinfo lock indicator (string)
213 @param uptodate up to date flag (boolean)
214 @param revision revision (integer)
215 @param change revision of last change (integer)
216 @param author author of the last change (string)
217 @param path path of the file or directory (string)
218 """
219 statusText = self.tr(svnStatusMap[status])
220 itm = QTreeWidgetItem(self.statusList)
221 itm.setData(0, Qt.ItemDataRole.DisplayRole, "")
222 itm.setData(1, Qt.ItemDataRole.DisplayRole, changelist)
223 itm.setData(2, Qt.ItemDataRole.DisplayRole, statusText)
224 itm.setData(3, Qt.ItemDataRole.DisplayRole,
225 self.tr(svnStatusMap[propStatus]))
226 itm.setData(4, Qt.ItemDataRole.DisplayRole, self.yesno[locked])
227 itm.setData(5, Qt.ItemDataRole.DisplayRole, self.yesno[history])
228 itm.setData(6, Qt.ItemDataRole.DisplayRole, self.yesno[switched])
229 itm.setData(7, Qt.ItemDataRole.DisplayRole, self.lockinfo[lockinfo])
230 itm.setData(8, Qt.ItemDataRole.DisplayRole, self.yesno[uptodate])
231 itm.setData(9, Qt.ItemDataRole.DisplayRole, revision)
232 itm.setData(10, Qt.ItemDataRole.DisplayRole, change)
233 itm.setData(11, Qt.ItemDataRole.DisplayRole, author)
234 itm.setData(12, Qt.ItemDataRole.DisplayRole, path)
235
236 itm.setTextAlignment(1, Qt.AlignmentFlag.AlignLeft)
237 itm.setTextAlignment(2, Qt.AlignmentFlag.AlignHCenter)
238 itm.setTextAlignment(3, Qt.AlignmentFlag.AlignHCenter)
239 itm.setTextAlignment(4, Qt.AlignmentFlag.AlignHCenter)
240 itm.setTextAlignment(5, Qt.AlignmentFlag.AlignHCenter)
241 itm.setTextAlignment(6, Qt.AlignmentFlag.AlignHCenter)
242 itm.setTextAlignment(7, Qt.AlignmentFlag.AlignHCenter)
243 itm.setTextAlignment(8, Qt.AlignmentFlag.AlignHCenter)
244 itm.setTextAlignment(9, Qt.AlignmentFlag.AlignRight)
245 itm.setTextAlignment(10, Qt.AlignmentFlag.AlignRight)
246 itm.setTextAlignment(11, Qt.AlignmentFlag.AlignLeft)
247 itm.setTextAlignment(12, Qt.AlignmentFlag.AlignLeft)
248
249 if (
250 status in [pysvn.wc_status_kind.added,
251 pysvn.wc_status_kind.deleted,
252 pysvn.wc_status_kind.modified] or
253 propStatus in [pysvn.wc_status_kind.added,
254 pysvn.wc_status_kind.deleted,
255 pysvn.wc_status_kind.modified]
256 ):
257 itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable)
258 itm.setCheckState(self.__toBeCommittedColumn,
259 Qt.CheckState.Checked)
260 else:
261 itm.setFlags(itm.flags() & ~Qt.ItemFlag.ItemIsUserCheckable)
262
263 if statusText not in self.__statusFilters:
264 self.__statusFilters.append(statusText)
265
266 def start(self, fn):
267 """
268 Public slot to start the svn status command.
269
270 @param fn filename(s)/directoryname(s) to show the status of
271 (string or list of strings)
272 """
273 self.errorGroup.hide()
274
275 for act in self.menuactions:
276 act.setEnabled(False)
277
278 self.addButton.setEnabled(False)
279 self.commitButton.setEnabled(False)
280 self.diffButton.setEnabled(False)
281 self.sbsDiffButton.setEnabled(False)
282 self.revertButton.setEnabled(False)
283 self.restoreButton.setEnabled(False)
284
285 self.statusFilterCombo.clear()
286 self.__statusFilters = []
287 self.statusList.clear()
288 self.shouldCancel = False
289
290 self.buttonBox.button(
291 QDialogButtonBox.StandardButton.Close).setEnabled(False)
292 self.buttonBox.button(
293 QDialogButtonBox.StandardButton.Cancel).setEnabled(True)
294 self.buttonBox.button(
295 QDialogButtonBox.StandardButton.Cancel).setDefault(True)
296 self.refreshButton.setEnabled(False)
297
298 self.args = fn
299
300 self.setWindowTitle(self.tr('Subversion Status'))
301 self.activateWindow()
302 self.raise_()
303
304 if isinstance(fn, list):
305 self.dname, fnames = self.vcs.splitPathList(fn)
306 else:
307 self.dname, fname = self.vcs.splitPath(fn)
308 fnames = [fname]
309
310 opts = self.vcs.options['global'] + self.vcs.options['status']
311 verbose = "--verbose" in opts
312 recurse = "--non-recursive" not in opts
313 update = "--show-updates" in opts
314
315 hideChangelistColumn = True
316 hidePropertyStatusColumn = True
317 hideLockColumns = True
318 hideUpToDateColumn = True
319 hideHistoryColumn = True
320 hideSwitchedColumn = True
321
322 with E5OverrideCursor():
323 cwd = os.getcwd()
324 os.chdir(self.dname)
325 try:
326 with E5MutexLocker(self.vcs.vcsExecutionMutex):
327 for name in fnames:
328 # step 1: determine changelists and their files
329 changelistsDict = {}
330 if hasattr(self.client, 'get_changelist'):
331 if recurse:
332 depth = pysvn.depth.infinity
333 else:
334 depth = pysvn.depth.immediate
335 changelists = self.client.get_changelist(
336 name, depth=depth)
337 for fpath, changelist in changelists:
338 fpath = Utilities.normcasepath(fpath)
339 changelistsDict[fpath] = changelist
340 hideChangelistColumn = (
341 hideChangelistColumn and len(changelistsDict) == 0
342 )
343
344 # step 2: determine status of files
345 allFiles = self.client.status(
346 name, recurse=recurse, get_all=verbose,
347 ignore=True, update=update)
348 for counter, file in enumerate(allFiles):
349 uptodate = True
350 if (
351 file.repos_text_status !=
352 pysvn.wc_status_kind.none
353 ):
354 uptodate = (
355 uptodate and
356 file.repos_text_status !=
357 pysvn.wc_status_kind.modified
358 )
359 if (
360 file.repos_prop_status !=
361 pysvn.wc_status_kind.none
362 ):
363 uptodate = (
364 uptodate and
365 file.repos_prop_status !=
366 pysvn.wc_status_kind.modified
367 )
368
369 lockState = " "
370 if (
371 file.entry is not None and
372 hasattr(file.entry, 'lock_token') and
373 file.entry.lock_token is not None
374 ):
375 lockState = "L"
376 if hasattr(file, 'repos_lock') and update:
377 if (
378 lockState == "L" and
379 file.repos_lock is None
380 ):
381 lockState = "B"
382 elif (
383 lockState == " " and
384 file.repos_lock is not None
385 ):
386 lockState = "O"
387 elif (
388 lockState == "L" and
389 file.repos_lock is not None and
390 file.entry.lock_token !=
391 file.repos_lock["token"]
392 ):
393 lockState = "S"
394
395 fpath = Utilities.normcasepath(
396 os.path.join(self.dname, file.path))
397 changelist = (changelistsDict[fpath]
398 if fpath in changelistsDict else "")
399
400 hidePropertyStatusColumn = (
401 hidePropertyStatusColumn and
402 file.prop_status in [
403 pysvn.wc_status_kind.none,
404 pysvn.wc_status_kind.normal
405 ]
406 )
407 hideLockColumns = (
408 hideLockColumns and
409 not file.is_locked and
410 lockState == " "
411 )
412 hideUpToDateColumn = (
413 hideUpToDateColumn and uptodate
414 )
415 hideHistoryColumn = (
416 hideHistoryColumn and
417 not file.is_copied
418 )
419 hideSwitchedColumn = (
420 hideSwitchedColumn and
421 not file.is_switched
422 )
423
424 self.__generateItem(
425 changelist,
426 file.text_status,
427 file.prop_status,
428 file.is_locked,
429 file.is_copied,
430 file.is_switched,
431 lockState,
432 uptodate,
433 file.entry.revision.number if file.entry
434 else "",
435 file.entry.commit_revision.number
436 if file.entry else "",
437 file.entry.commit_author if file.entry else "",
438 file.path
439 )
440 if (
441 counter % 30 == 0 and
442 self._clientCancelCallback()
443 ):
444 # check for cancel every 30 items
445 break
446 if self._clientCancelCallback():
447 break
448 except pysvn.ClientError as e:
449 self.__showError(e.args[0] + '\n')
450
451 self.statusList.setColumnHidden(self.__propStatusColumn,
452 hidePropertyStatusColumn)
453 self.statusList.setColumnHidden(self.__lockedColumn,
454 hideLockColumns)
455 self.statusList.setColumnHidden(self.__lockinfoColumn,
456 hideLockColumns)
457 self.statusList.setColumnHidden(self.__upToDateColumn,
458 hideUpToDateColumn)
459 self.statusList.setColumnHidden(self.__historyColumn,
460 hideHistoryColumn)
461 self.statusList.setColumnHidden(self.__switchedColumn,
462 hideSwitchedColumn)
463 self.statusList.setColumnHidden(self.__changelistColumn,
464 hideChangelistColumn)
465 self.__finish()
466 os.chdir(cwd)
467
468 def __finish(self):
469 """
470 Private slot called when the process finished or the user pressed
471 the button.
472 """
473 self.buttonBox.button(
474 QDialogButtonBox.StandardButton.Close).setEnabled(True)
475 self.buttonBox.button(
476 QDialogButtonBox.StandardButton.Cancel).setEnabled(False)
477 self.buttonBox.button(
478 QDialogButtonBox.StandardButton.Close).setDefault(True)
479
480 self.refreshButton.setEnabled(True)
481 self.__updateButtons()
482 self.__updateCommitButton()
483
484 self.__statusFilters.sort()
485 self.__statusFilters.insert(0, "<{0}>".format(self.tr("all")))
486 self.statusFilterCombo.addItems(self.__statusFilters)
487
488 for act in self.menuactions:
489 act.setEnabled(True)
490
491 self.__resizeColumns()
492 self.__resort()
493
494 self._cancel()
495
496 def on_buttonBox_clicked(self, button):
497 """
498 Private slot called by a button of the button box clicked.
499
500 @param button button that was clicked (QAbstractButton)
501 """
502 if button == self.buttonBox.button(
503 QDialogButtonBox.StandardButton.Close
504 ):
505 self.close()
506 elif button == self.buttonBox.button(
507 QDialogButtonBox.StandardButton.Cancel
508 ):
509 self.__finish()
510 elif button == self.refreshButton:
511 self.on_refreshButton_clicked()
512
513 @pyqtSlot()
514 def on_refreshButton_clicked(self):
515 """
516 Private slot to refresh the status display.
517 """
518 self.start(self.args)
519
520 def __showError(self, msg):
521 """
522 Private slot to show an error message.
523
524 @param msg error message to show (string)
525 """
526 self.errorGroup.show()
527 self.errors.insertPlainText(msg)
528 self.errors.ensureCursorVisible()
529
530 def __updateButtons(self):
531 """
532 Private method to update the VCS buttons status.
533 """
534 modified = len(self.__getModifiedItems())
535 unversioned = len(self.__getUnversionedItems())
536 missing = len(self.__getMissingItems())
537
538 self.addButton.setEnabled(unversioned)
539 self.diffButton.setEnabled(modified)
540 self.sbsDiffButton.setEnabled(modified == 1)
541 self.revertButton.setEnabled(modified)
542 self.restoreButton.setEnabled(missing)
543
544 def __updateCommitButton(self):
545 """
546 Private method to update the Commit button status.
547 """
548 commitable = len(self.__getCommitableItems())
549 self.commitButton.setEnabled(commitable)
550
551 @pyqtSlot(int)
552 def on_statusFilterCombo_activated(self, index):
553 """
554 Private slot to react to the selection of a status filter.
555
556 @param index index of the selected entry
557 @type int
558 """
559 txt = self.statusFilterCombo.itemText(index)
560 if txt == "<{0}>".format(self.tr("all")):
561 for topIndex in range(self.statusList.topLevelItemCount()):
562 topItem = self.statusList.topLevelItem(topIndex)
563 topItem.setHidden(False)
564 else:
565 for topIndex in range(self.statusList.topLevelItemCount()):
566 topItem = self.statusList.topLevelItem(topIndex)
567 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
568
569 @pyqtSlot(QTreeWidgetItem, int)
570 def on_statusList_itemChanged(self, item, column):
571 """
572 Private slot to act upon item changes.
573
574 @param item reference to the changed item (QTreeWidgetItem)
575 @param column index of column that changed (integer)
576 """
577 if column == self.__toBeCommittedColumn:
578 self.__updateCommitButton()
579
580 @pyqtSlot()
581 def on_statusList_itemSelectionChanged(self):
582 """
583 Private slot to act upon changes of selected items.
584 """
585 self.__updateButtons()
586
587 @pyqtSlot()
588 def on_commitButton_clicked(self):
589 """
590 Private slot to handle the press of the Commit button.
591 """
592 self.__commit()
593
594 @pyqtSlot()
595 def on_addButton_clicked(self):
596 """
597 Private slot to handle the press of the Add button.
598 """
599 self.__add()
600
601 @pyqtSlot()
602 def on_diffButton_clicked(self):
603 """
604 Private slot to handle the press of the Differences button.
605 """
606 self.__diff()
607
608 @pyqtSlot()
609 def on_sbsDiffButton_clicked(self):
610 """
611 Private slot to handle the press of the Side-by-Side Diff button.
612 """
613 self.__sbsDiff()
614
615 @pyqtSlot()
616 def on_revertButton_clicked(self):
617 """
618 Private slot to handle the press of the Revert button.
619 """
620 self.__revert()
621
622 @pyqtSlot()
623 def on_restoreButton_clicked(self):
624 """
625 Private slot to handle the press of the Restore button.
626 """
627 self.__restoreMissing()
628
629 ###########################################################################
630 ## Context menu handling methods
631 ###########################################################################
632
633 def __showContextMenu(self, coord):
634 """
635 Private slot to show the context menu of the status list.
636
637 @param coord the position of the mouse pointer (QPoint)
638 """
639 self.menu.popup(self.statusList.mapToGlobal(coord))
640
641 def __commit(self):
642 """
643 Private slot to handle the Commit context menu entry.
644 """
645 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
646 for itm in self.__getCommitableItems()]
647 if not names:
648 E5MessageBox.information(
649 self,
650 self.tr("Commit"),
651 self.tr("""There are no entries selected to be"""
652 """ committed."""))
653 return
654
655 if Preferences.getVCS("AutoSaveFiles"):
656 vm = e5App().getObject("ViewManager")
657 for name in names:
658 vm.saveEditor(name)
659 self.vcs.vcsCommit(names, '')
660
661 def __committed(self):
662 """
663 Private slot called after the commit has finished.
664 """
665 if self.isVisible():
666 self.on_refreshButton_clicked()
667 self.vcs.checkVCSStatus()
668
669 def __commitSelectAll(self):
670 """
671 Private slot to select all entries for commit.
672 """
673 self.__commitSelect(True)
674
675 def __commitDeselectAll(self):
676 """
677 Private slot to deselect all entries from commit.
678 """
679 self.__commitSelect(False)
680
681 def __add(self):
682 """
683 Private slot to handle the Add context menu entry.
684 """
685 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
686 for itm in self.__getUnversionedItems()]
687 if not names:
688 E5MessageBox.information(
689 self,
690 self.tr("Add"),
691 self.tr("""There are no unversioned entries"""
692 """ available/selected."""))
693 return
694
695 self.vcs.vcsAdd(names)
696 self.on_refreshButton_clicked()
697
698 project = e5App().getObject("Project")
699 for name in names:
700 project.getModel().updateVCSStatus(name)
701 self.vcs.checkVCSStatus()
702
703 def __revert(self):
704 """
705 Private slot to handle the Revert context menu entry.
706 """
707 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
708 for itm in self.__getModifiedItems()]
709 if not names:
710 E5MessageBox.information(
711 self,
712 self.tr("Revert"),
713 self.tr("""There are no uncommitted changes"""
714 """ available/selected."""))
715 return
716
717 self.vcs.vcsRevert(names)
718 self.raise_()
719 self.activateWindow()
720 self.on_refreshButton_clicked()
721
722 project = e5App().getObject("Project")
723 for name in names:
724 project.getModel().updateVCSStatus(name)
725 self.vcs.checkVCSStatus()
726
727 def __restoreMissing(self):
728 """
729 Private slot to handle the Restore Missing context menu entry.
730 """
731 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
732 for itm in self.__getMissingItems()]
733 if not names:
734 E5MessageBox.information(
735 self,
736 self.tr("Revert"),
737 self.tr("""There are no missing entries"""
738 """ available/selected."""))
739 return
740
741 self.vcs.vcsRevert(names)
742 self.on_refreshButton_clicked()
743 self.vcs.checkVCSStatus()
744
745 def __diff(self):
746 """
747 Private slot to handle the Diff context menu entry.
748 """
749 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
750 for itm in self.__getModifiedItems()]
751 if not names:
752 E5MessageBox.information(
753 self,
754 self.tr("Differences"),
755 self.tr("""There are no uncommitted changes"""
756 """ available/selected."""))
757 return
758
759 if self.diff is None:
760 from .SvnDiffDialog import SvnDiffDialog
761 self.diff = SvnDiffDialog(self.vcs)
762 self.diff.show()
763 QApplication.processEvents()
764 self.diff.start(names, refreshable=True)
765
766 def __sbsDiff(self):
767 """
768 Private slot to handle the Side-by-Side Diff context menu entry.
769 """
770 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
771 for itm in self.__getModifiedItems()]
772 if not names:
773 E5MessageBox.information(
774 self,
775 self.tr("Side-by-Side Diff"),
776 self.tr("""There are no uncommitted changes"""
777 """ available/selected."""))
778 return
779 elif len(names) > 1:
780 E5MessageBox.information(
781 self,
782 self.tr("Side-by-Side Diff"),
783 self.tr("""Only one file with uncommitted changes"""
784 """ must be selected."""))
785 return
786
787 self.vcs.svnSbsDiff(names[0])
788
789 def __lock(self):
790 """
791 Private slot to handle the Lock context menu entry.
792 """
793 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
794 for itm in self.__getLockActionItems(self.unlockedIndicators)]
795 if not names:
796 E5MessageBox.information(
797 self,
798 self.tr("Lock"),
799 self.tr("""There are no unlocked files"""
800 """ available/selected."""))
801 return
802
803 self.vcs.svnLock(names, parent=self)
804 self.on_refreshButton_clicked()
805
806 def __unlock(self):
807 """
808 Private slot to handle the Unlock context menu entry.
809 """
810 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
811 for itm in self.__getLockActionItems(self.lockedIndicators)]
812 if not names:
813 E5MessageBox.information(
814 self,
815 self.tr("Unlock"),
816 self.tr("""There are no locked files"""
817 """ available/selected."""))
818 return
819
820 self.vcs.svnUnlock(names, parent=self)
821 self.on_refreshButton_clicked()
822
823 def __breakLock(self):
824 """
825 Private slot to handle the Break Lock context menu entry.
826 """
827 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
828 for itm in self.__getLockActionItems(
829 self.stealBreakLockIndicators)]
830 if not names:
831 E5MessageBox.information(
832 self,
833 self.tr("Break Lock"),
834 self.tr("""There are no locked files"""
835 """ available/selected."""))
836 return
837
838 self.vcs.svnUnlock(names, parent=self, breakIt=True)
839 self.on_refreshButton_clicked()
840
841 def __stealLock(self):
842 """
843 Private slot to handle the Break Lock context menu entry.
844 """
845 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
846 for itm in self.__getLockActionItems(
847 self.stealBreakLockIndicators)]
848 if not names:
849 E5MessageBox.information(
850 self,
851 self.tr("Steal Lock"),
852 self.tr("""There are no locked files"""
853 """ available/selected."""))
854 return
855
856 self.vcs.svnLock(names, parent=self, stealIt=True)
857 self.on_refreshButton_clicked()
858
859 def __addToChangelist(self):
860 """
861 Private slot to add entries to a changelist.
862 """
863 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
864 for itm in self.__getNonChangelistItems()]
865 if not names:
866 E5MessageBox.information(
867 self,
868 self.tr("Remove from Changelist"),
869 self.tr(
870 """There are no files available/selected not """
871 """belonging to a changelist."""
872 )
873 )
874 return
875 self.vcs.svnAddToChangelist(names)
876 self.on_refreshButton_clicked()
877
878 def __removeFromChangelist(self):
879 """
880 Private slot to remove entries from their changelists.
881 """
882 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
883 for itm in self.__getChangelistItems()]
884 if not names:
885 E5MessageBox.information(
886 self,
887 self.tr("Remove from Changelist"),
888 self.tr(
889 """There are no files available/selected belonging"""
890 """ to a changelist."""
891 )
892 )
893 return
894 self.vcs.svnRemoveFromChangelist(names)
895 self.on_refreshButton_clicked()
896
897 def __getCommitableItems(self):
898 """
899 Private method to retrieve all entries the user wants to commit.
900
901 @return list of all items, the user has checked
902 """
903 commitableItems = []
904 for index in range(self.statusList.topLevelItemCount()):
905 itm = self.statusList.topLevelItem(index)
906 if (
907 itm.checkState(self.__toBeCommittedColumn) ==
908 Qt.CheckState.Checked
909 ):
910 commitableItems.append(itm)
911 return commitableItems
912
913 def __getModifiedItems(self):
914 """
915 Private method to retrieve all entries, that have a modified status.
916
917 @return list of all items with a modified status
918 """
919 modifiedItems = []
920 for itm in self.statusList.selectedItems():
921 if (
922 itm.text(self.__statusColumn) in self.modifiedIndicators or
923 itm.text(self.__propStatusColumn) in self.modifiedIndicators
924 ):
925 modifiedItems.append(itm)
926 return modifiedItems
927
928 def __getUnversionedItems(self):
929 """
930 Private method to retrieve all entries, that have an
931 unversioned status.
932
933 @return list of all items with an unversioned status
934 """
935 unversionedItems = []
936 for itm in self.statusList.selectedItems():
937 if itm.text(self.__statusColumn) in self.unversionedIndicators:
938 unversionedItems.append(itm)
939 return unversionedItems
940
941 def __getMissingItems(self):
942 """
943 Private method to retrieve all entries, that have a missing status.
944
945 @return list of all items with a missing status
946 """
947 missingItems = []
948 for itm in self.statusList.selectedItems():
949 if itm.text(self.__statusColumn) in self.missingIndicators:
950 missingItems.append(itm)
951 return missingItems
952
953 def __getLockActionItems(self, indicators):
954 """
955 Private method to retrieve all entries, that have a locked status.
956
957 @param indicators list of indicators to check against (list of strings)
958 @return list of all items with a locked status
959 """
960 lockitems = []
961 for itm in self.statusList.selectedItems():
962 if itm.text(self.__lockinfoColumn) in indicators:
963 lockitems.append(itm)
964 return lockitems
965
966 def __getChangelistItems(self):
967 """
968 Private method to retrieve all entries, that are members of
969 a changelist.
970
971 @return list of all items belonging to a changelist
972 """
973 clitems = []
974 for itm in self.statusList.selectedItems():
975 if itm.text(self.__changelistColumn):
976 clitems.append(itm)
977 return clitems
978
979 def __getNonChangelistItems(self):
980 """
981 Private method to retrieve all entries, that are not members of
982 a changelist.
983
984 @return list of all items not belonging to a changelist
985 """
986 clitems = []
987 for itm in self.statusList.selectedItems():
988 if not itm.text(self.__changelistColumn):
989 clitems.append(itm)
990 return clitems
991
992 def __commitSelect(self, selected):
993 """
994 Private slot to select or deselect all entries.
995
996 @param selected commit selection state to be set (boolean)
997 """
998 for index in range(self.statusList.topLevelItemCount()):
999 itm = self.statusList.topLevelItem(index)
1000 if itm.flags() & Qt.ItemFlag.ItemIsUserCheckable:
1001 if selected:
1002 itm.setCheckState(
1003 self.__toBeCommittedColumn, Qt.CheckState.Checked)
1004 else:
1005 itm.setCheckState(
1006 self.__toBeCommittedColumn, Qt.CheckState.Unchecked)

eric ide

mercurial