eric6/Plugins/VcsPlugins/vcsPySvn/SvnStatusDialog.py

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

eric ide

mercurial