Plugins/VcsPlugins/vcsMercurial/HgStatusDialog.py

changeset 917
746c54b643eb
parent 791
9ec2ac20e54e
child 945
8cd4d08fa9f6
equal deleted inserted replaced
915:c1e052773c08 917:746c54b643eb
13 from PyQt4.QtGui import QWidget, QDialogButtonBox, QMenu, QHeaderView, QTreeWidgetItem, \ 13 from PyQt4.QtGui import QWidget, QDialogButtonBox, QMenu, QHeaderView, QTreeWidgetItem, \
14 QLineEdit 14 QLineEdit
15 15
16 from E5Gui.E5Application import e5App 16 from E5Gui.E5Application import e5App
17 from E5Gui import E5MessageBox 17 from E5Gui import E5MessageBox
18
19 from .HgDiffDialog import HgDiffDialog
18 20
19 from .Ui_HgStatusDialog import Ui_HgStatusDialog 21 from .Ui_HgStatusDialog import Ui_HgStatusDialog
20 22
21 import Preferences 23 import Preferences
22 24
32 @param parent parent widget (QWidget) 34 @param parent parent widget (QWidget)
33 """ 35 """
34 QWidget.__init__(self, parent) 36 QWidget.__init__(self, parent)
35 self.setupUi(self) 37 self.setupUi(self)
36 38
37 self.__statusColumn = 0 39 self.__toBeCommittedColumn = 0
38 self.__pathColumn = 1 40 self.__statusColumn = 1
41 self.__pathColumn = 2
39 self.__lastColumn = self.statusList.columnCount() 42 self.__lastColumn = self.statusList.columnCount()
40 43
41 self.refreshButton = \ 44 self.refreshButton = \
42 self.buttonBox.addButton(self.trUtf8("Refresh"), QDialogButtonBox.ActionRole) 45 self.buttonBox.addButton(self.trUtf8("Refresh"), QDialogButtonBox.ActionRole)
43 self.refreshButton.setToolTip(self.trUtf8("Press to refresh the status display")) 46 self.refreshButton.setToolTip(self.trUtf8("Press to refresh the status display"))
44 self.refreshButton.setEnabled(False) 47 self.refreshButton.setEnabled(False)
45 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) 48 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False)
46 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) 49 self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
47 50
51 self.diff = None
48 self.process = None 52 self.process = None
49 self.vcs = vcs 53 self.vcs = vcs
50 self.vcs.committed.connect(self.__committed) 54 self.vcs.committed.connect(self.__committed)
51 55
52 self.statusList.headerItem().setText(self.__lastColumn, "") 56 self.statusList.headerItem().setText(self.__lastColumn, "")
58 self.trUtf8("Commit changes to repository..."), self.__commit)) 62 self.trUtf8("Commit changes to repository..."), self.__commit))
59 self.menu.addSeparator() 63 self.menu.addSeparator()
60 self.menuactions.append(self.menu.addAction( 64 self.menuactions.append(self.menu.addAction(
61 self.trUtf8("Add to repository"), self.__add)) 65 self.trUtf8("Add to repository"), self.__add))
62 self.menuactions.append(self.menu.addAction( 66 self.menuactions.append(self.menu.addAction(
67 self.trUtf8("Show differences"), self.__diff))
68 self.menuactions.append(self.menu.addAction(
63 self.trUtf8("Remove from repository"), self.__forget)) 69 self.trUtf8("Remove from repository"), self.__forget))
64 self.menuactions.append(self.menu.addAction( 70 self.menuactions.append(self.menu.addAction(
65 self.trUtf8("Revert changes"), self.__revert)) 71 self.trUtf8("Revert changes"), self.__revert))
72 self.menuactions.append(self.menu.addAction(
73 self.trUtf8("Restore missing"), self.__restoreMissing))
66 self.menu.addSeparator() 74 self.menu.addSeparator()
67 self.menuactions.append(self.menu.addAction(self.trUtf8("Adjust column sizes"), 75 self.menuactions.append(self.menu.addAction(self.trUtf8("Adjust column sizes"),
68 self.__resizeColumns)) 76 self.__resizeColumns))
69 for act in self.menuactions: 77 for act in self.menuactions:
70 act.setEnabled(False) 78 act.setEnabled(False)
115 Private method to generate a status item in the status list. 123 Private method to generate a status item in the status list.
116 124
117 @param status status indicator (string) 125 @param status status indicator (string)
118 @param path path of the file or directory (string) 126 @param path path of the file or directory (string)
119 """ 127 """
128 statusText = self.status[status]
120 itm = QTreeWidgetItem(self.statusList, [ 129 itm = QTreeWidgetItem(self.statusList, [
121 self.status[status], 130 "",
131 statusText,
122 path, 132 path,
123 ]) 133 ])
124 134
125 itm.setTextAlignment(0, Qt.AlignHCenter) 135 itm.setTextAlignment(1, Qt.AlignHCenter)
126 itm.setTextAlignment(1, Qt.AlignLeft) 136 itm.setTextAlignment(2, Qt.AlignLeft)
127 137
138 if status in "AMR":
139 itm.setCheckState(self.__toBeCommittedColumn, Qt.Checked)
140
141 if statusText not in self.__statusFilters:
142 self.__statusFilters.append(statusText)
143
128 def closeEvent(self, e): 144 def closeEvent(self, e):
129 """ 145 """
130 Private slot implementing a close event handler. 146 Private slot implementing a close event handler.
131 147
132 @param e close event (QCloseEvent) 148 @param e close event (QCloseEvent)
147 (string or list of strings) 163 (string or list of strings)
148 """ 164 """
149 self.errorGroup.hide() 165 self.errorGroup.hide()
150 self.intercept = False 166 self.intercept = False
151 self.args = fn 167 self.args = fn
168
169 for act in self.menuactions:
170 act.setEnabled(False)
171
172 self.addButton.setEnabled(False)
173 self.commitButton.setEnabled(False)
174 self.diffButton.setEnabled(False)
175 self.revertButton.setEnabled(False)
176 self.forgetButton.setEnabled(False)
177 self.restoreButton.setEnabled(False)
178
179 self.statusFilterCombo.clear()
180 self.__statusFilters = []
152 181
153 if self.process: 182 if self.process:
154 self.process.kill() 183 self.process.kill()
155 else: 184 else:
156 self.process = QProcess() 185 self.process = QProcess()
213 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) 242 self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True)
214 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) 243 self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False)
215 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) 244 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
216 self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason) 245 self.buttonBox.button(QDialogButtonBox.Close).setFocus(Qt.OtherFocusReason)
217 246
247 self.__statusFilters.sort()
248 self.__statusFilters.insert(0, "<{0}>".format(self.trUtf8("all")))
249 self.statusFilterCombo.addItems(self.__statusFilters)
250
218 for act in self.menuactions: 251 for act in self.menuactions:
219 act.setEnabled(True) 252 act.setEnabled(True)
220 253
221 self.process = None 254 self.process = None
222 255
223 self.statusList.doItemsLayout() 256 self.statusList.doItemsLayout()
224 self.__resort() 257 self.__resort()
225 self.__resizeColumns() 258 self.__resizeColumns()
259
260 self.__updateButtons()
261 self.__updateCommitButton()
226 262
227 def on_buttonBox_clicked(self, button): 263 def on_buttonBox_clicked(self, button):
228 """ 264 """
229 Private slot called by a button of the button box clicked. 265 Private slot called by a button of the button box clicked.
230 266
340 376
341 self.inputGroup.setEnabled(True) 377 self.inputGroup.setEnabled(True)
342 self.inputGroup.show() 378 self.inputGroup.show()
343 self.refreshButton.setEnabled(False) 379 self.refreshButton.setEnabled(False)
344 380
345 for act in self.menuactions:
346 act.setEnabled(False)
347
348 self.statusList.clear() 381 self.statusList.clear()
349 382
350 self.start(self.args) 383 self.start(self.args)
384
385 def __updateButtons(self):
386 """
387 Private method to update the VCS buttons status.
388 """
389 modified = len(self.__getModifiedItems())
390 unversioned = len(self.__getUnversionedItems())
391 missing = len(self.__getMissingItems())
392
393 self.addButton.setEnabled(unversioned)
394 self.diffButton.setEnabled(modified)
395 self.revertButton.setEnabled(modified)
396 self.forgetButton.setEnabled(missing)
397 self.restoreButton.setEnabled(missing)
398
399 def __updateCommitButton(self):
400 """
401 Private method to update the Commit button status.
402 """
403 commitable = len(self.__getCommitableItems())
404 self.commitButton.setEnabled(commitable)
405
406 @pyqtSlot(str)
407 def on_statusFilterCombo_activated(self, txt):
408 """
409 Private slot to react to the selection of a status filter.
410
411 @param txt selected status filter (string)
412 """
413 if txt == "<{0}>".format(self.trUtf8("all")):
414 for topIndex in range(self.statusList.topLevelItemCount()):
415 topItem = self.statusList.topLevelItem(topIndex)
416 topItem.setHidden(False)
417 else:
418 for topIndex in range(self.statusList.topLevelItemCount()):
419 topItem = self.statusList.topLevelItem(topIndex)
420 topItem.setHidden(topItem.text(self.__statusColumn) != txt)
421
422 @pyqtSlot(QTreeWidgetItem, int)
423 def on_statusList_itemChanged(self, item, column):
424 """
425 Private slot to act upon item changes.
426
427 @param item reference to the changed item (QTreeWidgetItem)
428 @param column index of column that changed (integer)
429 """
430 if column == self.__toBeCommittedColumn:
431 self.__updateCommitButton()
432
433 @pyqtSlot()
434 def on_statusList_itemSelectionChanged(self):
435 """
436 Private slot to act upon changes of selected items.
437 """
438 self.__updateButtons()
439
440 @pyqtSlot()
441 def on_commitButton_clicked(self):
442 """
443 Private slot to handle the press of the Commit button.
444 """
445 self.__commit()
446
447 @pyqtSlot()
448 def on_addButton_clicked(self):
449 """
450 Private slot to handle the press of the Add button.
451 """
452 self.__add()
453
454 @pyqtSlot()
455 def on_diffButton_clicked(self):
456 """
457 Private slot to handle the press of the Differences button.
458 """
459 self.__diff()
460
461 @pyqtSlot()
462 def on_revertButton_clicked(self):
463 """
464 Private slot to handle the press of the Revert button.
465 """
466 self.__revert()
467
468 @pyqtSlot()
469 def on_forgetButton_clicked(self):
470 """
471 Private slot to handle the press of the Forget button.
472 """
473 self.__forget()
474
475 @pyqtSlot()
476 def on_restoreButton_clicked(self):
477 """
478 Private slot to handle the press of the Restore button.
479 """
480 self.__restoreMissing()
351 481
352 ############################################################################ 482 ############################################################################
353 ## Context menu handling methods 483 ## Context menu handling methods
354 ############################################################################ 484 ############################################################################
355 485
364 def __commit(self): 494 def __commit(self):
365 """ 495 """
366 Private slot to handle the Commit context menu entry. 496 Private slot to handle the Commit context menu entry.
367 """ 497 """
368 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 498 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \
369 for itm in self.__getModifiedItems()] 499 for itm in self.__getCommitableItems()]
370 if not names: 500 if not names:
371 E5MessageBox.information(self, 501 E5MessageBox.information(self,
372 self.trUtf8("Commit"), 502 self.trUtf8("Commit"),
373 self.trUtf8("""There are no uncommitted changes available/selected.""")) 503 self.trUtf8("""There are no entries selected to be"""
504 """ committed."""))
374 return 505 return
375 506
376 if Preferences.getVCS("AutoSaveFiles"): 507 if Preferences.getVCS("AutoSaveFiles"):
377 vm = e5App().getObject("ViewManager") 508 vm = e5App().getObject("ViewManager")
378 for name in names: 509 for name in names:
394 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 525 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \
395 for itm in self.__getUnversionedItems()] 526 for itm in self.__getUnversionedItems()]
396 if not names: 527 if not names:
397 E5MessageBox.information(self, 528 E5MessageBox.information(self,
398 self.trUtf8("Add"), 529 self.trUtf8("Add"),
399 self.trUtf8("""There are no unversioned entries available/selected.""")) 530 self.trUtf8("""There are no unversioned entries"""
531 """ available/selected."""))
400 return 532 return
401 533
402 self.vcs.vcsAdd(names) 534 self.vcs.vcsAdd(names)
403 self.on_refreshButton_clicked() 535 self.on_refreshButton_clicked()
404 536
414 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 546 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \
415 for itm in self.__getMissingItems()] 547 for itm in self.__getMissingItems()]
416 if not names: 548 if not names:
417 E5MessageBox.information(self, 549 E5MessageBox.information(self,
418 self.trUtf8("Remove"), 550 self.trUtf8("Remove"),
419 self.trUtf8("""There are no missing entries available/selected.""")) 551 self.trUtf8("""There are no missing entries"""
552 """ available/selected."""))
420 return 553 return
421 554
422 self.vcs.hgForget(names) 555 self.vcs.hgForget(names)
423 self.on_refreshButton_clicked() 556 self.on_refreshButton_clicked()
424 557
429 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \ 562 names = [os.path.join(self.dname, itm.text(self.__pathColumn)) \
430 for itm in self.__getModifiedItems()] 563 for itm in self.__getModifiedItems()]
431 if not names: 564 if not names:
432 E5MessageBox.information(self, 565 E5MessageBox.information(self,
433 self.trUtf8("Revert"), 566 self.trUtf8("Revert"),
434 self.trUtf8("""There are no uncommitted changes available/selected.""")) 567 self.trUtf8("""There are no uncommitted changes"""
568 """ available/selected."""))
435 return 569 return
436 570
437 self.vcs.vcsRevert(names) 571 self.vcs.vcsRevert(names)
438 self.on_refreshButton_clicked() 572 self.on_refreshButton_clicked()
439 573
440 project = e5App().getObject("Project") 574 project = e5App().getObject("Project")
441 for name in names: 575 for name in names:
442 project.getModel().updateVCSStatus(name) 576 project.getModel().updateVCSStatus(name)
443 self.vcs.checkVCSStatus() 577 self.vcs.checkVCSStatus()
578
579 def __restoreMissing(self):
580 """
581 Private slot to handle the Restore Missing context menu entry.
582 """
583 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
584 for itm in self.__getMissingItems()]
585 if not names:
586 E5MessageBox.information(self,
587 self.trUtf8("Revert"),
588 self.trUtf8("""There are no missing entries"""
589 """ available/selected."""))
590 return
591
592 self.vcs.vcsRevert(names)
593 self.on_refreshButton_clicked()
594 self.vcs.checkVCSStatus()
595
596 def __diff(self):
597 """
598 Private slot to handle the Diff context menu entry.
599 """
600 names = [os.path.join(self.dname, itm.text(self.__pathColumn))
601 for itm in self.__getModifiedItems()]
602 if not names:
603 E5MessageBox.information(self,
604 self.trUtf8("Differences"),
605 self.trUtf8("""There are no uncommitted changes"""
606 """ available/selected."""))
607 return
608
609 if self.diff is None:
610 self.diff = HgDiffDialog(self.vcs)
611 self.diff.show()
612 self.diff.start(names)
613
614 def __getCommitableItems(self):
615 """
616 Private method to retrieve all entries the user wants to commit.
617
618 @return list of all items, the user has checked
619 """
620 commitableItems = []
621 for index in range(self.statusList.topLevelItemCount()):
622 itm = self.statusList.topLevelItem(index)
623 if itm.checkState(self.__toBeCommittedColumn) == Qt.Checked:
624 commitableItems.append(itm)
625 return commitableItems
444 626
445 def __getModifiedItems(self): 627 def __getModifiedItems(self):
446 """ 628 """
447 Private method to retrieve all entries, that have a modified status. 629 Private method to retrieve all entries, that have a modified status.
448 630

eric ide

mercurial