Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py

branch
Py2 comp.
changeset 3484
645c12de6b0c
parent 3178
f25fc1364c88
parent 3406
b3612f0fbf55
child 3591
2f2a4a76dd22
equal deleted inserted replaced
3456:96232974dcdb 3484:645c12de6b0c
8 process. 8 process.
9 """ 9 """
10 10
11 from __future__ import unicode_literals 11 from __future__ import unicode_literals
12 try: 12 try:
13 str = unicode # __IGNORE_WARNING__ 13 str = unicode
14 except (NameError): 14 except NameError:
15 pass 15 pass
16 16
17 import os 17 import os
18 18
19 from PyQt4.QtCore import pyqtSlot, Qt, QProcess, QTimer 19 from PyQt4.QtCore import pyqtSlot, Qt, QProcess, QTimer
48 self.__statusColumn = 1 48 self.__statusColumn = 1
49 self.__pathColumn = 2 49 self.__pathColumn = 2
50 self.__lastColumn = self.statusList.columnCount() 50 self.__lastColumn = self.statusList.columnCount()
51 51
52 self.refreshButton = self.buttonBox.addButton( 52 self.refreshButton = self.buttonBox.addButton(
53 self.trUtf8("Refresh"), QDialogButtonBox.ActionRole) 53 self.tr("Refresh"), QDialogButtonBox.ActionRole)
54 self.refreshButton.setToolTip( 54 self.refreshButton.setToolTip(
55 self.trUtf8("Press to refresh the status display")) 55 self.tr("Press to refresh the status display"))
56 self.refreshButton.setEnabled(False) 56 self.refreshButton.setEnabled(False)
57 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) 57 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
58 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) 58 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
59 59
60 self.diff = None 60 self.diff = None
76 self.revertButton.setVisible(False) 76 self.revertButton.setVisible(False)
77 self.forgetButton.setVisible(False) 77 self.forgetButton.setVisible(False)
78 self.restoreButton.setVisible(False) 78 self.restoreButton.setVisible(False)
79 79
80 self.menuactions = [] 80 self.menuactions = []
81 self.lfActions = []
81 self.menu = QMenu() 82 self.menu = QMenu()
82 if not mq: 83 if not mq:
84 self.__commitAct = self.menu.addAction(
85 self.tr("Commit changes to repository..."), self.__commit)
86 self.menuactions.append(self.__commitAct)
83 self.menuactions.append(self.menu.addAction( 87 self.menuactions.append(self.menu.addAction(
84 self.trUtf8("Commit changes to repository..."), self.__commit)) 88 self.tr("Select all for commit"), self.__commitSelectAll))
85 self.menuactions.append(self.menu.addAction( 89 self.menuactions.append(self.menu.addAction(
86 self.trUtf8("Select all for commit"), self.__commitSelectAll)) 90 self.tr("Deselect all from commit"),
87 self.menuactions.append(self.menu.addAction(
88 self.trUtf8("Deselect all from commit"),
89 self.__commitDeselectAll)) 91 self.__commitDeselectAll))
90 self.menu.addSeparator() 92 self.menu.addSeparator()
91 self.menuactions.append(self.menu.addAction( 93 self.__addAct = self.menu.addAction(
92 self.trUtf8("Add to repository"), self.__add)) 94 self.tr("Add to repository"), self.__add)
93 self.menuactions.append(self.menu.addAction( 95 self.menuactions.append(self.__addAct)
94 self.trUtf8("Show differences"), self.__diff)) 96 if self.vcs.version >= (2, 0):
95 self.menuactions.append(self.menu.addAction( 97 self.lfActions.append(self.menu.addAction(
96 self.trUtf8("Show differences side-by-side"), self.__sbsDiff)) 98 self.tr("Add as Large File"),
97 self.menuactions.append(self.menu.addAction( 99 lambda: self.__lfAdd("large")))
98 self.trUtf8("Remove from repository"), self.__forget)) 100 self.lfActions.append(self.menu.addAction(
99 self.menuactions.append(self.menu.addAction( 101 self.tr("Add as Normal File"),
100 self.trUtf8("Revert changes"), self.__revert)) 102 lambda: self.__lfAdd("normal")))
101 self.menuactions.append(self.menu.addAction( 103 self.__diffAct = self.menu.addAction(
102 self.trUtf8("Restore missing"), self.__restoreMissing)) 104 self.tr("Show differences"), self.__diff)
105 self.menuactions.append(self.__diffAct)
106 self.__sbsDiffAct = self.menu.addAction(
107 self.tr("Show differences side-by-side"), self.__sbsDiff)
108 self.menuactions.append(self.__sbsDiffAct)
109 self.__revertAct = self.menu.addAction(
110 self.tr("Revert changes"), self.__revert)
111 self.menuactions.append(self.__revertAct)
112 self.__forgetAct = self.menu.addAction(
113 self.tr("Forget missing"), self.__forget)
114 self.menuactions.append(self.__forgetAct)
115 self.__restoreAct = self.menu.addAction(
116 self.tr("Restore missing"), self.__restoreMissing)
117 self.menuactions.append(self.__restoreAct)
103 self.menu.addSeparator() 118 self.menu.addSeparator()
104 self.menuactions.append(self.menu.addAction( 119 self.menuactions.append(self.menu.addAction(
105 self.trUtf8("Adjust column sizes"), self.__resizeColumns)) 120 self.tr("Adjust column sizes"), self.__resizeColumns))
106 for act in self.menuactions: 121 for act in self.menuactions:
122 act.setEnabled(False)
123 for act in self.lfActions:
107 act.setEnabled(False) 124 act.setEnabled(False)
108 125
109 self.statusList.setContextMenuPolicy(Qt.CustomContextMenu) 126 self.statusList.setContextMenuPolicy(Qt.CustomContextMenu)
110 self.statusList.customContextMenuRequested.connect( 127 self.statusList.customContextMenuRequested.connect(
111 self.__showContextMenu) 128 self.__showContextMenu)
112 129
130 if not mq and self.vcs.version >= (2, 0):
131 self.__lfAddActions = []
132 self.__addButtonMenu = QMenu()
133 self.__addButtonMenu.addAction(self.tr("Add"), self.__add)
134 self.__lfAddActions.append(
135 self.__addButtonMenu.addAction(self.tr("Add as Large File"),
136 lambda: self.__lfAdd("large")))
137 self.__lfAddActions.append(
138 self.__addButtonMenu.addAction(self.tr("Add as Normal File"),
139 lambda: self.__lfAdd("normal")))
140 self.addButton.setMenu(self.__addButtonMenu)
141 self.__addButtonMenu.aboutToShow.connect(self.__showAddMenu)
142
113 self.modifiedIndicators = [ 143 self.modifiedIndicators = [
114 self.trUtf8('added'), 144 self.tr('added'),
115 self.trUtf8('modified'), 145 self.tr('modified'),
116 self.trUtf8('removed'), 146 self.tr('removed'),
117 ] 147 ]
118 148
119 self.unversionedIndicators = [ 149 self.unversionedIndicators = [
120 self.trUtf8('not tracked'), 150 self.tr('not tracked'),
121 ] 151 ]
122 152
123 self.missingIndicators = [ 153 self.missingIndicators = [
124 self.trUtf8('missing') 154 self.tr('missing')
125 ] 155 ]
126 156
127 self.status = { 157 self.status = {
128 'A': self.trUtf8('added'), 158 'A': self.tr('added'),
129 'C': self.trUtf8('normal'), 159 'C': self.tr('normal'),
130 'I': self.trUtf8('ignored'), 160 'I': self.tr('ignored'),
131 'M': self.trUtf8('modified'), 161 'M': self.tr('modified'),
132 'R': self.trUtf8('removed'), 162 'R': self.tr('removed'),
133 '?': self.trUtf8('not tracked'), 163 '?': self.tr('not tracked'),
134 '!': self.trUtf8('missing'), 164 '!': self.tr('missing'),
135 } 165 }
136 166
137 def __resort(self): 167 def __resort(self):
138 """ 168 """
139 Private method to resort the tree. 169 Private method to resort the tree.
203 self.errorGroup.hide() 233 self.errorGroup.hide()
204 self.intercept = False 234 self.intercept = False
205 self.args = fn 235 self.args = fn
206 236
207 for act in self.menuactions: 237 for act in self.menuactions:
238 act.setEnabled(False)
239 for act in self.lfActions:
208 act.setEnabled(False) 240 act.setEnabled(False)
209 241
210 self.addButton.setEnabled(False) 242 self.addButton.setEnabled(False)
211 self.commitButton.setEnabled(False) 243 self.commitButton.setEnabled(False)
212 self.diffButton.setEnabled(False) 244 self.diffButton.setEnabled(False)
218 self.statusFilterCombo.clear() 250 self.statusFilterCombo.clear()
219 self.__statusFilters = [] 251 self.__statusFilters = []
220 252
221 if self.__mq: 253 if self.__mq:
222 self.setWindowTitle( 254 self.setWindowTitle(
223 self.trUtf8("Mercurial Queue Repository Status")) 255 self.tr("Mercurial Queue Repository Status"))
224 else: 256 else:
225 self.setWindowTitle(self.trUtf8('Mercurial Status')) 257 self.setWindowTitle(self.tr('Mercurial Status'))
226 258
227 args = [] 259 args = self.vcs.initCommand("status")
228 args.append('status')
229 self.vcs.addArguments(args, self.vcs.options['global'])
230 if self.__mq: 260 if self.__mq:
231 args.append('--mq') 261 args.append('--mq')
232 if isinstance(fn, list): 262 if isinstance(fn, list):
233 self.dname, fnames = self.vcs.splitPathList(fn) 263 self.dname, fnames = self.vcs.splitPathList(fn)
234 else: 264 else:
235 self.dname, fname = self.vcs.splitPath(fn) 265 self.dname, fname = self.vcs.splitPath(fn)
236 else: 266 else:
237 self.vcs.addArguments(args, self.vcs.options['status'])
238
239 if self.vcs.hasSubrepositories(): 267 if self.vcs.hasSubrepositories():
240 args.append("--subrepos") 268 args.append("--subrepos")
241 269
242 if isinstance(fn, list): 270 if isinstance(fn, list):
243 self.dname, fnames = self.vcs.splitPathList(fn) 271 self.dname, fnames = self.vcs.splitPathList(fn)
282 if not procStarted: 310 if not procStarted:
283 self.inputGroup.setEnabled(False) 311 self.inputGroup.setEnabled(False)
284 self.inputGroup.hide() 312 self.inputGroup.hide()
285 E5MessageBox.critical( 313 E5MessageBox.critical(
286 self, 314 self,
287 self.trUtf8('Process Generation Error'), 315 self.tr('Process Generation Error'),
288 self.trUtf8( 316 self.tr(
289 'The process {0} could not be started. ' 317 'The process {0} could not be started. '
290 'Ensure, that it is in the search path.' 318 'Ensure, that it is in the search path.'
291 ).format('hg')) 319 ).format('hg'))
292 else: 320 else:
293 self.inputGroup.setEnabled(True) 321 self.inputGroup.setEnabled(True)
313 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) 341 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
314 self.buttonBox.button(QDialogButtonBox.Close).setFocus( 342 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
315 Qt.OtherFocusReason) 343 Qt.OtherFocusReason)
316 344
317 self.__statusFilters.sort() 345 self.__statusFilters.sort()
318 self.__statusFilters.insert(0, "<{0}>".format(self.trUtf8("all"))) 346 self.__statusFilters.insert(0, "<{0}>".format(self.tr("all")))
319 self.statusFilterCombo.addItems(self.__statusFilters) 347 self.statusFilterCombo.addItems(self.__statusFilters)
320 348
321 for act in self.menuactions: 349 for act in self.menuactions:
322 act.setEnabled(True) 350 act.setEnabled(True)
323 351
363 """ 391 """
364 if self.process is not None: 392 if self.process is not None:
365 self.process.setReadChannel(QProcess.StandardOutput) 393 self.process.setReadChannel(QProcess.StandardOutput)
366 394
367 while self.process.canReadLine(): 395 while self.process.canReadLine():
368 line = str( 396 line = str(self.process.readLine(), self.vcs.getEncoding(),
369 self.process.readLine(), 397 'replace')
370 Preferences.getSystem("IOEncoding"),
371 'replace')
372 self.__processOutputLine(line) 398 self.__processOutputLine(line)
373 399
374 def __processOutputLine(self, line): 400 def __processOutputLine(self, line):
375 """ 401 """
376 Private method to process the lines of output. 402 Private method to process the lines of output.
388 It reads the error output of the process and inserts it into the 414 It reads the error output of the process and inserts it into the
389 error pane. 415 error pane.
390 """ 416 """
391 if self.process is not None: 417 if self.process is not None:
392 s = str(self.process.readAllStandardError(), 418 s = str(self.process.readAllStandardError(),
393 Preferences.getSystem("IOEncoding"), 419 self.vcs.getEncoding(), 'replace')
394 'replace')
395 self.__showError(s) 420 self.__showError(s)
396 421
397 def __showError(self, out): 422 def __showError(self, out):
398 """ 423 """
399 Private slot to show some error. 424 Private slot to show some error.
498 """ 523 """
499 Private slot to react to the selection of a status filter. 524 Private slot to react to the selection of a status filter.
500 525
501 @param txt selected status filter (string) 526 @param txt selected status filter (string)
502 """ 527 """
503 if txt == "<{0}>".format(self.trUtf8("all")): 528 if txt == "<{0}>".format(self.tr("all")):
504 for topIndex in range(self.statusList.topLevelItemCount()): 529 for topIndex in range(self.statusList.topLevelItemCount()):
505 topItem = self.statusList.topLevelItem(topIndex) 530 topItem = self.statusList.topLevelItem(topIndex)
506 topItem.setHidden(False) 531 topItem.setHidden(False)
507 else: 532 else:
508 for topIndex in range(self.statusList.topLevelItemCount()): 533 for topIndex in range(self.statusList.topLevelItemCount()):
584 """ 609 """
585 Protected slot to show the context menu of the status list. 610 Protected slot to show the context menu of the status list.
586 611
587 @param coord the position of the mouse pointer (QPoint) 612 @param coord the position of the mouse pointer (QPoint)
588 """ 613 """
614 modified = len(self.__getModifiedItems())
615 unversioned = len(self.__getUnversionedItems())
616 missing = len(self.__getMissingItems())
617 commitable = len(self.__getCommitableItems())
618
619 self.__addAct.setEnabled(unversioned)
620 self.__diffAct.setEnabled(modified)
621 self.__sbsDiffAct.setEnabled(modified == 1)
622 self.__revertAct.setEnabled(modified)
623 self.__forgetAct.setEnabled(missing)
624 self.__restoreAct.setEnabled(missing)
625 self.__commitAct.setEnabled(commitable)
626
627 if self.vcs.isExtensionActive("largefiles"):
628 enable = len(self.__getUnversionedItems()) > 0
629 else:
630 enable = False
631 for act in self.lfActions:
632 act.setEnabled(enable)
589 self.menu.popup(self.mapToGlobal(coord)) 633 self.menu.popup(self.mapToGlobal(coord))
634
635 def __showAddMenu(self):
636 """
637 Private slot to prepare the Add button menu before it is shown.
638 """
639 enable = self.vcs.isExtensionActive("largefiles")
640 for act in self.__lfAddActions:
641 act.setEnabled(enable)
590 642
591 def __commit(self): 643 def __commit(self):
592 """ 644 """
593 Private slot to handle the Commit context menu entry. 645 Private slot to handle the Commit context menu entry.
594 """ 646 """
598 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 650 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
599 for itm in self.__getCommitableItems()] 651 for itm in self.__getCommitableItems()]
600 if not names: 652 if not names:
601 E5MessageBox.information( 653 E5MessageBox.information(
602 self, 654 self,
603 self.trUtf8("Commit"), 655 self.tr("Commit"),
604 self.trUtf8("""There are no entries selected to be""" 656 self.tr("""There are no entries selected to be"""
605 """ committed.""")) 657 """ committed."""))
606 return 658 return
607 659
608 if Preferences.getVCS("AutoSaveFiles"): 660 if Preferences.getVCS("AutoSaveFiles"):
609 vm = e5App().getObject("ViewManager") 661 vm = e5App().getObject("ViewManager")
610 for name in names: 662 for name in names:
638 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 690 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
639 for itm in self.__getUnversionedItems()] 691 for itm in self.__getUnversionedItems()]
640 if not names: 692 if not names:
641 E5MessageBox.information( 693 E5MessageBox.information(
642 self, 694 self,
643 self.trUtf8("Add"), 695 self.tr("Add"),
644 self.trUtf8("""There are no unversioned entries""" 696 self.tr("""There are no unversioned entries"""
645 """ available/selected.""")) 697 """ available/selected."""))
646 return 698 return
647 699
648 self.vcs.vcsAdd(names) 700 self.vcs.vcsAdd(names)
701 self.on_refreshButton_clicked()
702
703 project = e5App().getObject("Project")
704 for name in names:
705 project.getModel().updateVCSStatus(name)
706 self.vcs.checkVCSStatus()
707
708 def __lfAdd(self, mode):
709 """
710 Private slot to add a file to the repository.
711
712 @param mode add mode (string one of 'normal' or 'large')
713 """
714 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
715 for itm in self.__getUnversionedItems()]
716 if not names:
717 E5MessageBox.information(
718 self,
719 self.tr("Add"),
720 self.tr("""There are no unversioned entries"""
721 """ available/selected."""))
722 return
723
724 self.vcs.getExtensionObject("largefiles").hgAdd(
725 names, mode)
649 self.on_refreshButton_clicked() 726 self.on_refreshButton_clicked()
650 727
651 project = e5App().getObject("Project") 728 project = e5App().getObject("Project")
652 for name in names: 729 for name in names:
653 project.getModel().updateVCSStatus(name) 730 project.getModel().updateVCSStatus(name)
660 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 737 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
661 for itm in self.__getMissingItems()] 738 for itm in self.__getMissingItems()]
662 if not names: 739 if not names:
663 E5MessageBox.information( 740 E5MessageBox.information(
664 self, 741 self,
665 self.trUtf8("Remove"), 742 self.tr("Remove"),
666 self.trUtf8("""There are no missing entries""" 743 self.tr("""There are no missing entries"""
667 """ available/selected.""")) 744 """ available/selected."""))
668 return 745 return
669 746
670 self.vcs.hgForget(names) 747 self.vcs.hgForget(names)
671 self.on_refreshButton_clicked() 748 self.on_refreshButton_clicked()
672 749
677 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 754 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
678 for itm in self.__getModifiedItems()] 755 for itm in self.__getModifiedItems()]
679 if not names: 756 if not names:
680 E5MessageBox.information( 757 E5MessageBox.information(
681 self, 758 self,
682 self.trUtf8("Revert"), 759 self.tr("Revert"),
683 self.trUtf8("""There are no uncommitted changes""" 760 self.tr("""There are no uncommitted changes"""
684 """ available/selected.""")) 761 """ available/selected."""))
685 return 762 return
686 763
687 self.vcs.hgRevert(names) 764 self.vcs.hgRevert(names)
688 self.raise_() 765 self.raise_()
689 self.activateWindow() 766 self.activateWindow()
701 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 778 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
702 for itm in self.__getMissingItems()] 779 for itm in self.__getMissingItems()]
703 if not names: 780 if not names:
704 E5MessageBox.information( 781 E5MessageBox.information(
705 self, 782 self,
706 self.trUtf8("Revert"), 783 self.tr("Revert"),
707 self.trUtf8("""There are no missing entries""" 784 self.tr("""There are no missing entries"""
708 """ available/selected.""")) 785 """ available/selected."""))
709 return 786 return
710 787
711 self.vcs.hgRevert(names) 788 self.vcs.hgRevert(names)
712 self.on_refreshButton_clicked() 789 self.on_refreshButton_clicked()
713 self.vcs.checkVCSStatus() 790 self.vcs.checkVCSStatus()
719 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 796 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
720 for itm in self.__getModifiedItems()] 797 for itm in self.__getModifiedItems()]
721 if not names: 798 if not names:
722 E5MessageBox.information( 799 E5MessageBox.information(
723 self, 800 self,
724 self.trUtf8("Differences"), 801 self.tr("Differences"),
725 self.trUtf8("""There are no uncommitted changes""" 802 self.tr("""There are no uncommitted changes"""
726 """ available/selected.""")) 803 """ available/selected."""))
727 return 804 return
728 805
729 if self.diff is None: 806 if self.diff is None:
730 from .HgDiffDialog import HgDiffDialog 807 from .HgDiffDialog import HgDiffDialog
731 self.diff = HgDiffDialog(self.vcs) 808 self.diff = HgDiffDialog(self.vcs)
739 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) 816 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
740 for itm in self.__getModifiedItems()] 817 for itm in self.__getModifiedItems()]
741 if not names: 818 if not names:
742 E5MessageBox.information( 819 E5MessageBox.information(
743 self, 820 self,
744 self.trUtf8("Side-by-Side Diff"), 821 self.tr("Side-by-Side Diff"),
745 self.trUtf8("""There are no uncommitted changes""" 822 self.tr("""There are no uncommitted changes"""
746 """ available/selected.""")) 823 """ available/selected."""))
747 return 824 return
748 elif len(names) > 1: 825 elif len(names) > 1:
749 E5MessageBox.information( 826 E5MessageBox.information(
750 self, 827 self,
751 self.trUtf8("Side-by-Side Diff"), 828 self.tr("Side-by-Side Diff"),
752 self.trUtf8("""Only one file with uncommitted changes""" 829 self.tr("""Only one file with uncommitted changes"""
753 """ must be selected.""")) 830 """ must be selected."""))
754 return 831 return
755 832
756 self.vcs.hgSbsDiff(names[0]) 833 self.vcs.hgSbsDiff(names[0])
757 834
758 def __getCommitableItems(self): 835 def __getCommitableItems(self):

eric ide

mercurial