Plugins/VcsPlugins/vcsPySvn/SvnStatusDialog.py

changeset 917
746c54b643eb
parent 889
65585df1d52c
child 945
8cd4d08fa9f6
equal deleted inserted replaced
915:c1e052773c08 917:746c54b643eb
18 from E5Gui.E5Application import e5App 18 from E5Gui.E5Application import e5App
19 from E5Gui import E5MessageBox 19 from E5Gui import E5MessageBox
20 20
21 from .SvnConst import svnStatusMap 21 from .SvnConst import svnStatusMap
22 from .SvnDialogMixin import SvnDialogMixin 22 from .SvnDialogMixin import SvnDialogMixin
23 from .SvnDiffDialog import SvnDiffDialog
24
23 from .Ui_SvnStatusDialog import Ui_SvnStatusDialog 25 from .Ui_SvnStatusDialog import Ui_SvnStatusDialog
24 26
25 import Preferences 27 import Preferences
26 28
27 class SvnStatusDialog(QWidget, SvnDialogMixin, Ui_SvnStatusDialog): 29 class SvnStatusDialog(QWidget, SvnDialogMixin, Ui_SvnStatusDialog):
38 """ 40 """
39 QWidget.__init__(self, parent) 41 QWidget.__init__(self, parent)
40 self.setupUi(self) 42 self.setupUi(self)
41 SvnDialogMixin.__init__(self) 43 SvnDialogMixin.__init__(self)
42 44
43 self.__changelistColumn = 0 45 self.__toBeCommittedColumn = 0
44 self.__statusColumn = 1 46 self.__changelistColumn = 1
45 self.__propStatusColumn = 2 47 self.__statusColumn = 2
46 self.__lockedColumn = 3 48 self.__propStatusColumn = 3
47 self.__historyColumn = 4 49 self.__lockedColumn = 4
48 self.__switchedColumn = 5 50 self.__historyColumn = 5
49 self.__lockinfoColumn = 6 51 self.__switchedColumn = 6
50 self.__upToDateColumn = 7 52 self.__lockinfoColumn = 7
51 self.__pathColumn = 11 53 self.__upToDateColumn = 8
54 self.__pathColumn = 12
52 self.__lastColumn = self.statusList.columnCount() 55 self.__lastColumn = self.statusList.columnCount()
53 56
54 self.refreshButton = \ 57 self.refreshButton = \
55 self.buttonBox.addButton(self.trUtf8("Refresh"), 58 self.buttonBox.addButton(self.trUtf8("Refresh"),
56 QDialogButtonBox.ActionRole) 59 QDialogButtonBox.ActionRole)
58 self.trUtf8("Press to refresh the status display")) 61 self.trUtf8("Press to refresh the status display"))
59 self.refreshButton.setEnabled(False) 62 self.refreshButton.setEnabled(False)
60 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) 63 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
61 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) 64 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
62 65
66 self.diff = None
63 self.vcs = vcs 67 self.vcs = vcs
64 self.vcs.committed.connect(self.__committed) 68 self.vcs.committed.connect(self.__committed)
65 69
66 self.statusList.headerItem().setText(self.__lastColumn, "") 70 self.statusList.headerItem().setText(self.__lastColumn, "")
67 self.statusList.header().setSortIndicator(self.__pathColumn, 71 self.statusList.header().setSortIndicator(self.__pathColumn,
75 self.trUtf8("Commit changes to repository..."), self.__commit)) 79 self.trUtf8("Commit changes to repository..."), self.__commit))
76 self.menu.addSeparator() 80 self.menu.addSeparator()
77 self.menuactions.append(self.menu.addAction( 81 self.menuactions.append(self.menu.addAction(
78 self.trUtf8("Add to repository"), self.__add)) 82 self.trUtf8("Add to repository"), self.__add))
79 self.menuactions.append(self.menu.addAction( 83 self.menuactions.append(self.menu.addAction(
84 self.trUtf8("Show differences"), self.__diff))
85 self.menuactions.append(self.menu.addAction(
80 self.trUtf8("Revert changes"), self.__revert)) 86 self.trUtf8("Revert changes"), self.__revert))
87 self.menuactions.append(self.menu.addAction(
88 self.trUtf8("Restore missing"), self.__restoreMissing))
81 if pysvn.svn_version >= (1, 5, 0) and pysvn.version >= (1, 6, 0): 89 if pysvn.svn_version >= (1, 5, 0) and pysvn.version >= (1, 6, 0):
82 self.menu.addSeparator() 90 self.menu.addSeparator()
83 self.menuactions.append(self.menu.addAction( 91 self.menuactions.append(self.menu.addAction(
84 self.trUtf8("Add to Changelist"), self.__addToChangelist)) 92 self.trUtf8("Add to Changelist"), self.__addToChangelist))
85 self.menuactions.append(self.menu.addAction( 93 self.menuactions.append(self.menu.addAction(
112 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.added]), 120 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.added]),
113 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.deleted]), 121 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.deleted]),
114 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.modified]) 122 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.modified])
115 ] 123 ]
116 124
125 self.missingIndicators = [
126 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.missing]),
127 ]
128
117 self.unversionedIndicators = [ 129 self.unversionedIndicators = [
118 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.unversioned]) 130 self.trUtf8(svnStatusMap[pysvn.wc_status_kind.unversioned]),
119 ] 131 ]
120 132
121 self.lockedIndicators = [ 133 self.lockedIndicators = [
122 self.trUtf8('locked') 134 self.trUtf8('locked'),
123 ] 135 ]
124 136
125 self.stealBreakLockIndicators = [ 137 self.stealBreakLockIndicators = [
126 self.trUtf8('other lock'), 138 self.trUtf8('other lock'),
127 self.trUtf8('stolen lock'), 139 self.trUtf8('stolen lock'),
128 self.trUtf8('broken lock') 140 self.trUtf8('broken lock'),
129 ] 141 ]
130 142
131 self.unlockedIndicators = [ 143 self.unlockedIndicators = [
132 self.trUtf8('not locked') 144 self.trUtf8('not locked'),
133 ] 145 ]
134 146
135 self.lockinfo = { 147 self.lockinfo = {
136 ' ' : self.trUtf8('not locked'), 148 ' ' : self.trUtf8('not locked'),
137 'L' : self.trUtf8('locked'), 149 'L' : self.trUtf8('locked'),
139 'S' : self.trUtf8('stolen lock'), 151 'S' : self.trUtf8('stolen lock'),
140 'B' : self.trUtf8('broken lock'), 152 'B' : self.trUtf8('broken lock'),
141 } 153 }
142 self.yesno = [ 154 self.yesno = [
143 self.trUtf8('no'), 155 self.trUtf8('no'),
144 self.trUtf8('yes') 156 self.trUtf8('yes'),
145 ] 157 ]
146 158
147 self.client = self.vcs.getClient() 159 self.client = self.vcs.getClient()
148 self.client.callback_cancel = \ 160 self.client.callback_cancel = \
149 self._clientCancelCallback 161 self._clientCancelCallback
186 @param revision revision (integer) 198 @param revision revision (integer)
187 @param change revision of last change (integer) 199 @param change revision of last change (integer)
188 @param author author of the last change (string) 200 @param author author of the last change (string)
189 @param path path of the file or directory (string) 201 @param path path of the file or directory (string)
190 """ 202 """
203 statusText = self.trUtf8(svnStatusMap[status])
191 itm = QTreeWidgetItem(self.statusList, [ 204 itm = QTreeWidgetItem(self.statusList, [
205 "",
192 changelist, 206 changelist,
193 self.trUtf8(svnStatusMap[status]), 207 statusText,
194 self.trUtf8(svnStatusMap[propStatus]), 208 self.trUtf8(svnStatusMap[propStatus]),
195 self.yesno[locked], 209 self.yesno[locked],
196 self.yesno[history], 210 self.yesno[history],
197 self.yesno[switched], 211 self.yesno[switched],
198 self.lockinfo[lockinfo], 212 self.lockinfo[lockinfo],
201 "{0:7}".format(str(change)), 215 "{0:7}".format(str(change)),
202 author, 216 author,
203 path, 217 path,
204 ]) 218 ])
205 219
206 itm.setTextAlignment(0, Qt.AlignLeft) 220 itm.setTextAlignment(1, Qt.AlignLeft)
207 itm.setTextAlignment(1, Qt.AlignHCenter)
208 itm.setTextAlignment(2, Qt.AlignHCenter) 221 itm.setTextAlignment(2, Qt.AlignHCenter)
209 itm.setTextAlignment(3, Qt.AlignHCenter) 222 itm.setTextAlignment(3, Qt.AlignHCenter)
210 itm.setTextAlignment(4, Qt.AlignHCenter) 223 itm.setTextAlignment(4, Qt.AlignHCenter)
211 itm.setTextAlignment(5, Qt.AlignHCenter) 224 itm.setTextAlignment(5, Qt.AlignHCenter)
212 itm.setTextAlignment(6, Qt.AlignHCenter) 225 itm.setTextAlignment(6, Qt.AlignHCenter)
213 itm.setTextAlignment(7, Qt.AlignHCenter) 226 itm.setTextAlignment(7, Qt.AlignHCenter)
214 itm.setTextAlignment(8, Qt.AlignRight) 227 itm.setTextAlignment(8, Qt.AlignHCenter)
215 itm.setTextAlignment(9, Qt.AlignRight) 228 itm.setTextAlignment(9, Qt.AlignRight)
216 itm.setTextAlignment(10, Qt.AlignLeft) 229 itm.setTextAlignment(10, Qt.AlignRight)
217 itm.setTextAlignment(11, Qt.AlignLeft) 230 itm.setTextAlignment(11, Qt.AlignLeft)
231 itm.setTextAlignment(12, Qt.AlignLeft)
232
233 if status in [pysvn.wc_status_kind.added,
234 pysvn.wc_status_kind.deleted,
235 pysvn.wc_status_kind.modified] or \
236 propStatus in [pysvn.wc_status_kind.added,
237 pysvn.wc_status_kind.deleted,
238 pysvn.wc_status_kind.modified]:
239 itm.setCheckState(self.__toBeCommittedColumn, Qt.Checked)
240
241 if statusText not in self.__statusFilters:
242 self.__statusFilters.append(statusText)
218 243
219 def start(self, fn): 244 def start(self, fn):
220 """ 245 """
221 Public slot to start the svn status command. 246 Public slot to start the svn status command.
222 247
223 @param fn filename(s)/directoryname(s) to show the status of 248 @param fn filename(s)/directoryname(s) to show the status of
224 (string or list of strings) 249 (string or list of strings)
225 """ 250 """
226 self.errorGroup.hide() 251 self.errorGroup.hide()
252
253 for act in self.menuactions:
254 act.setEnabled(False)
255
256 self.addButton.setEnabled(False)
257 self.commitButton.setEnabled(False)
258 self.diffButton.setEnabled(False)
259 self.revertButton.setEnabled(False)
260 self.restoreButton.setEnabled(False)
261
262 self.statusFilterCombo.clear()
263 self.__statusFilters = []
227 264
228 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) 265 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
229 QApplication.processEvents() 266 QApplication.processEvents()
230 267
231 self.args = fn 268 self.args = fn
243 opts = self.vcs.options['global'] + self.vcs.options['status'] 280 opts = self.vcs.options['global'] + self.vcs.options['status']
244 verbose = "--verbose" in opts 281 verbose = "--verbose" in opts
245 recurse = "--non-recursive" not in opts 282 recurse = "--non-recursive" not in opts
246 update = "--show-updates" in opts 283 update = "--show-updates" in opts
247 284
285 hideChangelistColumn = True
248 hidePropertyStatusColumn = True 286 hidePropertyStatusColumn = True
249 hideLockColumns = True 287 hideLockColumns = True
250 hideUpToDateColumn = True 288 hideUpToDateColumn = True
251 hideHistoryColumn = True 289 hideHistoryColumn = True
252 hideSwitchedColumn = True 290 hideSwitchedColumn = True
264 else: 302 else:
265 depth = pysvn.depth.immediate 303 depth = pysvn.depth.immediate
266 changelists = self.client.get_changelist(name, depth=depth) 304 changelists = self.client.get_changelist(name, depth=depth)
267 for entry in changelists: 305 for entry in changelists:
268 changelistsDict[entry[0]] = entry[1] 306 changelistsDict[entry[0]] = entry[1]
269 self.statusList.setColumnHidden(self.__changelistColumn, 307 hideChangelistColumn = hideChangelistColumn and \
270 len(changelistsDict) == 0) 308 len(changelistsDict) == 0
271 309
272 # step 2: determine status of files 310 # step 2: determine status of files
273 allFiles = self.client.status(name, recurse = recurse, 311 allFiles = self.client.status(name, recurse = recurse,
274 get_all=verbose, ignore=True, 312 get_all=verbose, ignore=True,
275 update = update) 313 update = update)
351 hideUpToDateColumn) 389 hideUpToDateColumn)
352 self.statusList.setColumnHidden(self.__historyColumn, 390 self.statusList.setColumnHidden(self.__historyColumn,
353 hideHistoryColumn) 391 hideHistoryColumn)
354 self.statusList.setColumnHidden(self.__switchedColumn, 392 self.statusList.setColumnHidden(self.__switchedColumn,
355 hideSwitchedColumn) 393 hideSwitchedColumn)
394 self.statusList.setColumnHidden(self.__changelistColumn,
395 hideChangelistColumn)
356 396
357 locker.unlock() 397 locker.unlock()
358 self.__finish() 398 self.__finish()
359 os.chdir(cwd) 399 os.chdir(cwd)
360 400
368 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) 408 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
369 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) 409 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
370 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) 410 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
371 411
372 self.refreshButton.setEnabled(True) 412 self.refreshButton.setEnabled(True)
413 self.__updateButtons()
414 self.__updateCommitButton()
415
416 self.__statusFilters.sort()
417 self.__statusFilters.insert(0, "<{0}>".format(self.trUtf8("all")))
418 self.statusFilterCombo.addItems(self.__statusFilters)
373 419
374 for act in self.menuactions: 420 for act in self.menuactions:
375 act.setEnabled(True) 421 act.setEnabled(True)
376 422
377 self.statusList.doItemsLayout() 423 self.statusList.doItemsLayout()
402 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) 448 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True)
403 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) 449 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
404 450
405 self.refreshButton.setEnabled(False) 451 self.refreshButton.setEnabled(False)
406 452
407 for act in self.menuactions:
408 act.setEnabled(False)
409
410 self.statusList.clear() 453 self.statusList.clear()
411 454
412 self.shouldCancel = False 455 self.shouldCancel = False
413 self.start(self.args) 456 self.start(self.args)
414 457
420 """ 463 """
421 self.errorGroup.show() 464 self.errorGroup.show()
422 self.errors.insertPlainText(msg) 465 self.errors.insertPlainText(msg)
423 self.errors.ensureCursorVisible() 466 self.errors.ensureCursorVisible()
424 467
468 def __updateButtons(self):
469 """
470 Private method to update the VCS buttons status.
471 """
472 modified = len(self.__getModifiedItems())
473 unversioned = len(self.__getUnversionedItems())
474 missing = len(self.__getMissingItems())
475
476 self.addButton.setEnabled(unversioned)
477 self.diffButton.setEnabled(modified)
478 self.revertButton.setEnabled(modified)
479 self.restoreButton.setEnabled(missing)
480
481 def __updateCommitButton(self):
482 """
483 Private method to update the Commit button status.
484 """
485 commitable = len(self.__getCommitableItems())
486 self.commitButton.setEnabled(commitable)
487
488 @pyqtSlot(str)
489 def on_statusFilterCombo_activated(self, txt):
490 """
491 Private slot to react to the selection of a status filter.
492
493 @param txt selected status filter (string)
494 """
495 if txt == "<{0}>".format(self.trUtf8("all")):
496 for topIndex in range(self.statusList.topLevelItemCount()):
497 topItem = self.statusList.topLevelItem(topIndex)
498 topItem.setHidden(False)
499 else:
500 for topIndex in range(self.statusList.topLevelItemCount()):
501 topItem = self.statusList.topLevelItem(topIndex)
502 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
503
504 @pyqtSlot(QTreeWidgetItem, int)
505 def on_statusList_itemChanged(self, item, column):
506 """
507 Private slot to act upon item changes.
508
509 @param item reference to the changed item (QTreeWidgetItem)
510 @param column index of column that changed (integer)
511 """
512 if column == self.__toBeCommittedColumn:
513 self.__updateCommitButton()
514
515 @pyqtSlot()
516 def on_statusList_itemSelectionChanged(self):
517 """
518 Private slot to act upon changes of selected items.
519 """
520 self.__updateButtons()
521
522 @pyqtSlot()
523 def on_commitButton_clicked(self):
524 """
525 Private slot to handle the press of the Commit button.
526 """
527 self.__commit()
528
529 @pyqtSlot()
530 def on_addButton_clicked(self):
531 """
532 Private slot to handle the press of the Add button.
533 """
534 self.__add()
535
536 @pyqtSlot()
537 def on_diffButton_clicked(self):
538 """
539 Private slot to handle the press of the Differences button.
540 """
541 self.__diff()
542
543 @pyqtSlot()
544 def on_revertButton_clicked(self):
545 """
546 Private slot to handle the press of the Revert button.
547 """
548 self.__revert()
549
550 @pyqtSlot()
551 def on_restoreButton_clicked(self):
552 """
553 Private slot to handle the press of the Restore button.
554 """
555 self.__restoreMissing()
556
425 ########################################################################### 557 ###########################################################################
426 ## Context menu handling methods 558 ## Context menu handling methods
427 ########################################################################### 559 ###########################################################################
428 560
429 def __showContextMenu(self, coord): 561 def __showContextMenu(self, coord):
436 568
437 def __commit(self): 569 def __commit(self):
438 """ 570 """
439 Private slot to handle the Commit context menu entry. 571 Private slot to handle the Commit context menu entry.
440 """ 572 """
441 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 573 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
442 for itm in self.__getModifiedItems()] 574 for itm in self.__getCommitableItems()]
443 if not names: 575 if not names:
444 E5MessageBox.information(self, 576 E5MessageBox.information(self,
445 self.trUtf8("Commit"), 577 self.trUtf8("Commit"),
446 self.trUtf8("""There are no uncommitted changes""" 578 self.trUtf8("""There are no entries selected to be"""
447 """ available/selected.""")) 579 """ committed."""))
448 return 580 return
449 581
450 if Preferences.getVCS("AutoSaveFiles"): 582 if Preferences.getVCS("AutoSaveFiles"):
451 vm = e5App().getObject("ViewManager") 583 vm = e5App().getObject("ViewManager")
452 for name in names: 584 for name in names:
501 project = e5App().getObject("Project") 633 project = e5App().getObject("Project")
502 for name in names: 634 for name in names:
503 project.getModel().updateVCSStatus(name) 635 project.getModel().updateVCSStatus(name)
504 self.vcs.checkVCSStatus() 636 self.vcs.checkVCSStatus()
505 637
638 def __restoreMissing(self):
639 """
640 Private slot to handle the Restore Missing context menu entry.
641 """
642 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
643 for itm in self.__getMissingItems()]
644 if not names:
645 E5MessageBox.information(self,
646 self.trUtf8("Revert"),
647 self.trUtf8("""There are no missing entries"""
648 """ available/selected."""))
649 return
650
651 self.vcs.vcsRevert(names)
652 self.on_refreshButton_clicked()
653 self.vcs.checkVCSStatus()
654
655 def __diff(self):
656 """
657 Private slot to handle the Diff context menu entry.
658 """
659 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
660 for itm in self.__getModifiedItems()]
661 if not names:
662 E5MessageBox.information(self,
663 self.trUtf8("Differences"),
664 self.trUtf8("""There are no uncommitted changes"""
665 """ available/selected."""))
666 return
667
668 if self.diff is None:
669 self.diff = SvnDiffDialog(self.vcs)
670 self.diff.show()
671 QApplication.processEvents()
672 self.diff.start(names)
673
506 def __lock(self): 674 def __lock(self):
507 """ 675 """
508 Private slot to handle the Lock context menu entry. 676 Private slot to handle the Lock context menu entry.
509 """ 677 """
510 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 678 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \
603 ) 771 )
604 return 772 return
605 self.vcs.svnRemoveFromChangelist(names) 773 self.vcs.svnRemoveFromChangelist(names)
606 self.on_refreshButton_clicked() 774 self.on_refreshButton_clicked()
607 775
776 def __getCommitableItems(self):
777 """
778 Private method to retrieve all entries the user wants to commit.
779
780 @return list of all items, the user has checked
781 """
782 commitableItems = []
783 for index in range(self.statusList.topLevelItemCount()):
784 itm = self.statusList.topLevelItem(index)
785 if itm.checkState(self.__toBeCommittedColumn) == Qt.Checked:
786 commitableItems.append(itm)
787 return commitableItems
788
608 def __getModifiedItems(self): 789 def __getModifiedItems(self):
609 """ 790 """
610 Private method to retrieve all entries, that have a modified status. 791 Private method to retrieve all entries, that have a modified status.
611 792
612 @return list of all items with a modified status 793 @return list of all items with a modified status
629 for itm in self.statusList.selectedItems(): 810 for itm in self.statusList.selectedItems():
630 if itm.text(self.__statusColumn) in self.unversionedIndicators: 811 if itm.text(self.__statusColumn) in self.unversionedIndicators:
631 unversionedItems.append(itm) 812 unversionedItems.append(itm)
632 return unversionedItems 813 return unversionedItems
633 814
815 def __getMissingItems(self):
816 """
817 Private method to retrieve all entries, that have a missing status.
818
819 @return list of all items with a missing status
820 """
821 missingItems = []
822 for itm in self.statusList.selectedItems():
823 if itm.text(self.__statusColumn) in self.missingIndicators:
824 missingItems.append(itm)
825 return missingItems
826
634 def __getLockActionItems(self, indicators): 827 def __getLockActionItems(self, indicators):
635 """ 828 """
636 Private method to retrieve all entries, that have a locked status. 829 Private method to retrieve all entries, that have a locked status.
637 830
638 @return list of all items with a locked status 831 @return list of all items with a locked status

eric ide

mercurial