15 |
15 |
16 import os |
16 import os |
17 import re |
17 import re |
18 import collections |
18 import collections |
19 |
19 |
20 from PyQt5.QtCore import pyqtSlot, Qt, QDate, QProcess, QTimer, QRegExp, \ |
20 from PyQt5.QtCore import pyqtSlot, qVersion, Qt, QDate, QProcess, QTimer, \ |
21 QSize, QPoint, QFileInfo |
21 QRegExp, QSize, QPoint, QFileInfo |
22 from PyQt5.QtGui import QCursor, QColor, QPixmap, QPainter, QPen, QBrush, \ |
22 from PyQt5.QtGui import QCursor, QColor, QPixmap, QPainter, QPen, QBrush, \ |
23 QIcon, QTextCursor |
23 QIcon, QTextCursor |
24 from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QHeaderView, \ |
24 from PyQt5.QtWidgets import QWidget, QDialogButtonBox, QHeaderView, \ |
25 QTreeWidgetItem, QApplication, QLineEdit, QMenu, QInputDialog |
25 QTreeWidgetItem, QApplication, QLineEdit, QMenu, QInputDialog, QToolTip |
26 |
26 |
27 from E5Gui.E5Application import e5App |
27 from E5Gui.E5Application import e5App |
28 from E5Gui import E5MessageBox, E5FileDialog |
28 from E5Gui import E5MessageBox, E5FileDialog |
29 |
29 |
30 from .Ui_HgLogBrowserDialog import Ui_HgLogBrowserDialog |
30 from .Ui_HgLogBrowserDialog import Ui_HgLogBrowserDialog |
71 @param parent parent widget (QWidget) |
71 @param parent parent widget (QWidget) |
72 """ |
72 """ |
73 super(HgLogBrowserDialog, self).__init__(parent) |
73 super(HgLogBrowserDialog, self).__init__(parent) |
74 self.setupUi(self) |
74 self.setupUi(self) |
75 |
75 |
|
76 windowFlags = self.windowFlags() |
|
77 windowFlags |= Qt.WindowContextHelpButtonHint |
|
78 self.setWindowFlags(windowFlags) |
|
79 |
76 self.mainSplitter.setSizes([300, 400]) |
80 self.mainSplitter.setSizes([300, 400]) |
77 self.mainSplitter.setStretchFactor(0, 1) |
81 self.mainSplitter.setStretchFactor(0, 1) |
78 self.mainSplitter.setStretchFactor(1, 2) |
82 self.mainSplitter.setStretchFactor(1, 2) |
79 self.diffSplitter.setStretchFactor(0, 1) |
83 self.diffSplitter.setStretchFactor(0, 1) |
80 self.diffSplitter.setStretchFactor(1, 2) |
84 self.diffSplitter.setStretchFactor(1, 2) |
236 def __initActionsMenu(self): |
240 def __initActionsMenu(self): |
237 """ |
241 """ |
238 Private method to initialize the actions menu. |
242 Private method to initialize the actions menu. |
239 """ |
243 """ |
240 self.__actionsMenu = QMenu() |
244 self.__actionsMenu = QMenu() |
|
245 self.__actionsMenu.setTearOffEnabled(True) |
|
246 if qVersion() >= "5.1.0": |
|
247 self.__actionsMenu.setToolTipsVisible(True) |
|
248 else: |
|
249 self.__actionsMenu.hovered.connect(self.__actionsMenuHovered) |
241 |
250 |
242 self.__graftAct = self.__actionsMenu.addAction( |
251 self.__graftAct = self.__actionsMenu.addAction( |
243 UI.PixmapCache.getIcon("vcsGraft.png"), |
252 UI.PixmapCache.getIcon("vcsGraft.png"), |
244 self.tr("Copy Changesets"), self.__graftActTriggered) |
253 self.tr("Copy Changesets"), self.__graftActTriggered) |
245 self.__graftAct.setToolTip(self.tr( |
254 self.__graftAct.setToolTip(self.tr( |
331 """ If the dialog is showing outgoing changesets, all""" |
340 """ If the dialog is showing outgoing changesets, all""" |
332 """ selected changesets will be bundled.</p>""")) |
341 """ selected changesets will be bundled.</p>""")) |
333 |
342 |
334 self.__actionsMenu.addSeparator() |
343 self.__actionsMenu.addSeparator() |
335 |
344 |
|
345 self.__gpgSignAct = self.__actionsMenu.addAction( |
|
346 UI.PixmapCache.getIcon("changesetSign.png"), |
|
347 self.tr("Sign Revisions"), self.__gpgSignActTriggered) |
|
348 self.__gpgSignAct.setToolTip(self.tr( |
|
349 "Add a signature for the selected revisions")) |
|
350 self.__gpgVerifyAct = self.__actionsMenu.addAction( |
|
351 UI.PixmapCache.getIcon("changesetSignVerify.png"), |
|
352 self.tr("Verify Signatures"), self.__gpgVerifyActTriggered) |
|
353 self.__gpgVerifyAct.setToolTip(self.tr( |
|
354 "Verify all signatures there may be for the selected revision")) |
|
355 |
|
356 self.__actionsMenu.addSeparator() |
|
357 |
336 self.__stripAct = self.__actionsMenu.addAction( |
358 self.__stripAct = self.__actionsMenu.addAction( |
337 UI.PixmapCache.getIcon("fileDelete.png"), |
359 UI.PixmapCache.getIcon("fileDelete.png"), |
338 self.tr("Strip Changesets"), self.__stripActTriggered) |
360 self.tr("Strip Changesets"), self.__stripActTriggered) |
339 self.__stripAct.setToolTip(self.tr( |
361 self.__stripAct.setToolTip(self.tr( |
340 "Strip changesets from a repository")) |
362 "Strip changesets from a repository")) |
349 |
371 |
350 self.actionsButton.setIcon( |
372 self.actionsButton.setIcon( |
351 UI.PixmapCache.getIcon("actionsToolButton.png")) |
373 UI.PixmapCache.getIcon("actionsToolButton.png")) |
352 self.actionsButton.setMenu(self.__actionsMenu) |
374 self.actionsButton.setMenu(self.__actionsMenu) |
353 |
375 |
354 # TODO: add action "Sign Revision" (>= 1 revs) (GPG extension) |
376 def __actionsMenuHovered(self, action): |
355 # TODO: add action "Verify Signature" (1 rev) (GPG extension) |
377 """ |
|
378 Private slot to show the tooltip for an action menu entry. |
|
379 |
|
380 @param action action to show tooltip for |
|
381 @type QAction |
|
382 """ |
|
383 QToolTip.showText( |
|
384 QCursor.pos(), action.toolTip(), |
|
385 self.__actionsMenu, self.__actionsMenu.actionGeometry(action)) |
356 |
386 |
357 def __initData(self): |
387 def __initData(self): |
358 """ |
388 """ |
359 Private method to (re-)initialize some data. |
389 Private method to (re-)initialize some data. |
360 """ |
390 """ |
1445 otherBranches += 1 |
1475 otherBranches += 1 |
1446 |
1476 |
1447 # step 2: set the status of the graft action |
1477 # step 2: set the status of the graft action |
1448 self.__graftAct.setEnabled(otherBranches > 0) |
1478 self.__graftAct.setEnabled(otherBranches > 0) |
1449 |
1479 |
1450 self.__mergeAct.setEnabled(len(self.logTree.selectedItems()) == 1) |
1480 selectedItemsCount = len(self.logTree.selectedItems()) |
1451 self.__tagAct.setEnabled(len(self.logTree.selectedItems()) == 1) |
1481 self.__mergeAct.setEnabled(selectedItemsCount == 1) |
1452 self.__switchAct.setEnabled(len(self.logTree.selectedItems()) == 1) |
1482 self.__tagAct.setEnabled(selectedItemsCount == 1) |
1453 self.__bookmarkAct.setEnabled( |
1483 self.__switchAct.setEnabled(selectedItemsCount == 1) |
1454 len(self.logTree.selectedItems()) == 1) |
1484 self.__bookmarkAct.setEnabled(selectedItemsCount == 1) |
1455 self.__bookmarkMoveAct.setEnabled( |
1485 self.__bookmarkMoveAct.setEnabled(selectedItemsCount == 1) |
1456 len(self.logTree.selectedItems()) == 1) |
|
1457 |
1486 |
1458 if self.vcs.canPull(): |
1487 if self.vcs.canPull(): |
1459 self.__pullAct.setEnabled(True) |
1488 self.__pullAct.setEnabled(True) |
1460 self.__lfPullAct.setEnabled( |
1489 self.__lfPullAct.setEnabled( |
1461 self.vcs.isExtensionActive("largefiles") and |
1490 self.vcs.isExtensionActive("largefiles") and |
1462 bool(self.logTree.selectedItems())) |
1491 selectedItemsCount > 0) |
1463 self.__fetchAct.setEnabled( |
1492 self.__fetchAct.setEnabled( |
1464 self.vcs.isExtensionActive("fetch")) |
1493 self.vcs.isExtensionActive("fetch")) |
1465 else: |
1494 else: |
1466 self.__pullAct.setEnabled(False) |
1495 self.__pullAct.setEnabled(False) |
1467 self.__lfPullAct.setEnabled(False) |
1496 self.__lfPullAct.setEnabled(False) |
1468 self.__fetchAct.setEnabled(False) |
1497 self.__fetchAct.setEnabled(False) |
1469 |
1498 |
1470 if self.vcs.canPush(): |
1499 if self.vcs.canPush(): |
1471 self.__pushAct.setEnabled( |
1500 self.__pushAct.setEnabled( |
1472 len(self.logTree.selectedItems()) == 1 and |
1501 selectedItemsCount == 1 and |
1473 self.logTree.selectedItems()[0].text(self.PhaseColumn) == |
1502 self.logTree.selectedItems()[0].text(self.PhaseColumn) == |
1474 self.phases["draft"]) |
1503 self.phases["draft"]) |
1475 self.__pushAllAct.setEnabled(True) |
1504 self.__pushAllAct.setEnabled(True) |
1476 else: |
1505 else: |
1477 self.__pushAct.setEnabled(False) |
1506 self.__pushAct.setEnabled(False) |
1478 self.__pushAllAct.setEnabled(False) |
1507 self.__pushAllAct.setEnabled(False) |
1479 |
1508 |
1480 self.__stripAct.setEnabled( |
1509 self.__stripAct.setEnabled( |
1481 self.vcs.isExtensionActive("strip") and |
1510 self.vcs.isExtensionActive("strip") and |
1482 len(self.logTree.selectedItems()) == 1) |
1511 selectedItemsCount == 1) |
1483 |
1512 |
1484 self.__bundleAct.setEnabled(self.logTree.topLevelItemCount() > 0) |
1513 self.__bundleAct.setEnabled(self.logTree.topLevelItemCount() > 0) |
|
1514 |
|
1515 self.__gpgSignAct.setEnabled( |
|
1516 self.vcs.isExtensionActive("gpg") and |
|
1517 selectedItemsCount > 0) |
|
1518 self.__gpgVerifyAct.setEnabled( |
|
1519 self.vcs.isExtensionActive("gpg") and |
|
1520 selectedItemsCount == 1) |
1485 |
1521 |
1486 self.actionsButton.setEnabled(True) |
1522 self.actionsButton.setEnabled(True) |
1487 else: |
1523 else: |
1488 self.actionsButton.setEnabled(False) |
1524 self.actionsButton.setEnabled(False) |
1489 # TODO: add code to enable menu in incoming / outgoing mode as well |
1525 # TODO: add code to enable menu in incoming / outgoing mode as well |
2207 # TODO: implement bundle for outgoing mode |
2243 # TODO: implement bundle for outgoing mode |
2208 pass |
2244 pass |
2209 |
2245 |
2210 self.vcs.hgBundle(self.repodir, bundleData=bundleData) |
2246 self.vcs.hgBundle(self.repodir, bundleData=bundleData) |
2211 |
2247 |
|
2248 @pyqtSlot() |
|
2249 def __gpgSignActTriggered(self): |
|
2250 """ |
|
2251 Private slot to sign the selected revisions. |
|
2252 """ |
|
2253 revs = [] |
|
2254 for itm in self.logTree.selectedItems(): |
|
2255 rev = itm.text(self.RevisionColumn).split(":", 1)[0].strip() |
|
2256 if rev: |
|
2257 revs.append(rev) |
|
2258 |
|
2259 if revs: |
|
2260 self.vcs.getExtensionObject("gpg").hgGpgSign( |
|
2261 self.repodir, revisions=revs) |
|
2262 |
|
2263 @pyqtSlot() |
|
2264 def __gpgVerifyActTriggered(self): |
|
2265 """ |
|
2266 Private slot to verify the signatures of a selected revisions. |
|
2267 """ |
|
2268 rev = self.logTree.selectedItems()[0].text(self.RevisionColumn)\ |
|
2269 .split(":", 1)[0].strip() |
|
2270 if rev: |
|
2271 self.vcs.getExtensionObject("gpg").hgGpgVerifySignatures( |
|
2272 self.repodir, rev=rev) |
|
2273 |
2212 def __selectAllActTriggered(self, select=True): |
2274 def __selectAllActTriggered(self, select=True): |
2213 """ |
2275 """ |
2214 Private method to select or unselect all log entries. |
2276 Private method to select or unselect all log entries. |
2215 |
2277 |
2216 @param select flag indicating to select all entries |
2278 @param select flag indicating to select all entries |