1# -*- coding: utf-8 -*- 2 3# Copyright (c) 2014 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> 4# 5 6""" 7Module implementing the VCS project browser helper for Git. 8""" 9 10import os 11 12from PyQt5.QtWidgets import QMenu, QDialog 13 14from E5Gui.E5Application import e5App 15 16from Project.ProjectBrowserModel import ProjectBrowserFileItem 17 18from VCS.ProjectBrowserHelper import VcsProjectBrowserHelper 19 20import UI.PixmapCache 21 22 23class GitProjectBrowserHelper(VcsProjectBrowserHelper): 24 """ 25 Class implementing the VCS project browser helper for Git. 26 """ 27 def __init__(self, vcsObject, browserObject, projectObject, 28 isTranslationsBrowser, parent=None, name=None): 29 """ 30 Constructor 31 32 @param vcsObject reference to the vcs object 33 @param browserObject reference to the project browser object 34 @param projectObject reference to the project object 35 @param isTranslationsBrowser flag indicating, the helper is requested 36 for the translations browser (this needs some special treatment) 37 @param parent parent widget (QWidget) 38 @param name name of this object (string) 39 """ 40 VcsProjectBrowserHelper.__init__(self, vcsObject, browserObject, 41 projectObject, isTranslationsBrowser, 42 parent, name) 43 44 def showContextMenu(self, menu, standardItems): 45 """ 46 Public slot called before the context menu is shown. 47 48 It enables/disables the VCS menu entries depending on the overall 49 VCS status and the file status. 50 51 @param menu reference to the menu to be shown 52 @param standardItems array of standard items that need 53 activation/deactivation depending on the overall VCS status 54 """ 55 if self.browser.currentItem().data(1) == self.vcs.vcsName(): 56 for act in self.vcsMenuActions: 57 act.setEnabled(True) 58 for act in standardItems: 59 act.setEnabled(False) 60 else: 61 for act in self.vcsMenuActions: 62 act.setEnabled(False) 63 for act in standardItems: 64 act.setEnabled(True) 65 66 def showContextMenuMulti(self, menu, standardItems): 67 """ 68 Public slot called before the context menu (multiple selections) is 69 shown. 70 71 It enables/disables the VCS menu entries depending on the overall 72 VCS status and the files status. 73 74 @param menu reference to the menu to be shown 75 @param standardItems array of standard items that need 76 activation/deactivation depending on the overall VCS status 77 """ 78 vcsName = self.vcs.vcsName() 79 items = self.browser.getSelectedItems() 80 vcsItems = 0 81 # determine number of selected items under VCS control 82 for itm in items: 83 if itm.data(1) == vcsName: 84 vcsItems += 1 85 86 if vcsItems > 0: 87 if vcsItems != len(items): 88 for act in self.vcsMultiMenuActions: 89 act.setEnabled(False) 90 else: 91 for act in self.vcsMultiMenuActions: 92 act.setEnabled(True) 93 for act in standardItems: 94 act.setEnabled(False) 95 else: 96 for act in self.vcsMultiMenuActions: 97 act.setEnabled(False) 98 for act in standardItems: 99 act.setEnabled(True) 100 101 def showContextMenuDir(self, menu, standardItems): 102 """ 103 Public slot called before the context menu is shown. 104 105 It enables/disables the VCS menu entries depending on the overall 106 VCS status and the directory status. 107 108 @param menu reference to the menu to be shown 109 @param standardItems array of standard items that need 110 activation/deactivation depending on the overall VCS status 111 """ 112 if self.browser.currentItem().data(1) == self.vcs.vcsName(): 113 for act in self.vcsDirMenuActions: 114 act.setEnabled(True) 115 for act in standardItems: 116 act.setEnabled(False) 117 else: 118 for act in self.vcsDirMenuActions: 119 act.setEnabled(False) 120 for act in standardItems: 121 act.setEnabled(True) 122 123 def showContextMenuDirMulti(self, menu, standardItems): 124 """ 125 Public slot called before the context menu is shown. 126 127 It enables/disables the VCS menu entries depending on the overall 128 VCS status and the directory status. 129 130 @param menu reference to the menu to be shown 131 @param standardItems array of standard items that need 132 activation/deactivation depending on the overall VCS status 133 """ 134 vcsName = self.vcs.vcsName() 135 items = self.browser.getSelectedItems() 136 vcsItems = 0 137 # determine number of selected items under VCS control 138 for itm in items: 139 if itm.data(1) == vcsName: 140 vcsItems += 1 141 142 if vcsItems > 0: 143 if vcsItems != len(items): 144 for act in self.vcsDirMultiMenuActions: 145 act.setEnabled(False) 146 else: 147 for act in self.vcsDirMultiMenuActions: 148 act.setEnabled(True) 149 for act in standardItems: 150 act.setEnabled(False) 151 else: 152 for act in self.vcsDirMultiMenuActions: 153 act.setEnabled(False) 154 for act in standardItems: 155 act.setEnabled(True) 156 157 ########################################################################### 158 ## Protected menu generation methods below 159 ########################################################################### 160 161 def _addVCSMenu(self, mainMenu): 162 """ 163 Protected method used to add the VCS menu to all project browsers. 164 165 @param mainMenu reference to the menu to be amended 166 """ 167 self.vcsMenuActions = [] 168 self.vcsAddMenuActions = [] 169 170 menu = QMenu(self.tr("Version Control")) 171 172 act = menu.addAction( 173 UI.PixmapCache.getIcon( 174 os.path.join("VcsPlugins", "vcsGit", "icons", "git.svg")), 175 self.vcs.vcsName(), self._VCSInfoDisplay) 176 font = act.font() 177 font.setBold(True) 178 act.setFont(font) 179 menu.addSeparator() 180 181 act = menu.addAction( 182 UI.PixmapCache.getIcon("vcsCommit"), 183 self.tr('Commit changes to repository...'), 184 self._VCSCommit) 185 self.vcsMenuActions.append(act) 186 menu.addSeparator() 187 act = menu.addAction( 188 UI.PixmapCache.getIcon("vcsAdd"), 189 self.tr('Add/Stage to repository'), 190 self._VCSAdd) 191 act = menu.addAction( 192 UI.PixmapCache.getIcon("vcsRevert"), 193 self.tr('Unstage changes'), 194 self.__GitUnstage) 195 self.vcsMenuActions.append(act) 196 menu.addSeparator() 197 act = menu.addAction( 198 UI.PixmapCache.getIcon("vcsRemove"), 199 self.tr('Remove from repository (and disk)'), 200 self._VCSRemove) 201 self.vcsMenuActions.append(act) 202 act = menu.addAction( 203 UI.PixmapCache.getIcon("vcsRemove"), 204 self.tr('Remove from repository only'), 205 self.__GitForget) 206 self.vcsMenuActions.append(act) 207 menu.addSeparator() 208 act = menu.addAction(self.tr('Copy'), self.__GitCopy) 209 self.vcsMenuActions.append(act) 210 act = menu.addAction(self.tr('Move'), self.__GitMove) 211 self.vcsMenuActions.append(act) 212 menu.addSeparator() 213 act = menu.addAction( 214 UI.PixmapCache.getIcon("vcsLog"), 215 self.tr('Show log browser'), self._VCSLogBrowser) 216 self.vcsMenuActions.append(act) 217 menu.addSeparator() 218 act = menu.addAction( 219 UI.PixmapCache.getIcon("vcsStatus"), 220 self.tr('Show status'), self._VCSStatus) 221 self.vcsMenuActions.append(act) 222 menu.addSeparator() 223 act = menu.addAction( 224 UI.PixmapCache.getIcon("vcsDiff"), 225 self.tr('Show differences'), self._VCSDiff) 226 self.vcsMenuActions.append(act) 227 act = menu.addAction( 228 UI.PixmapCache.getIcon("vcsSbsDiff"), 229 self.tr('Show differences side-by-side'), self.__GitSbsDiff) 230 self.vcsMenuActions.append(act) 231 act = menu.addAction( 232 UI.PixmapCache.getIcon("vcsDiff"), 233 self.tr('Show differences (extended)'), 234 self.__GitExtendedDiff) 235 self.vcsMenuActions.append(act) 236 act = menu.addAction( 237 UI.PixmapCache.getIcon("vcsSbsDiff"), 238 self.tr('Show differences side-by-side (extended)'), 239 self.__GitSbsExtendedDiff) 240 self.vcsMenuActions.append(act) 241 menu.addSeparator() 242 self.annotateAct = menu.addAction( 243 self.tr('Show annotated file'), 244 self.__GitBlame) 245 self.vcsMenuActions.append(self.annotateAct) 246 menu.addSeparator() 247 act = menu.addAction( 248 UI.PixmapCache.getIcon("vcsRevert"), 249 self.tr('Revert changes'), self.__GitRevert) 250 self.vcsMenuActions.append(act) 251 menu.addSeparator() 252 menu.addAction(self.tr('Select all local file entries'), 253 self.browser.selectLocalEntries) 254 menu.addAction(self.tr('Select all versioned file entries'), 255 self.browser.selectVCSEntries) 256 menu.addAction(self.tr('Select all local directory entries'), 257 self.browser.selectLocalDirEntries) 258 menu.addAction(self.tr('Select all versioned directory entries'), 259 self.browser.selectVCSDirEntries) 260 menu.addSeparator() 261 menu.addAction(self.tr("Configure..."), self.__GitConfigure) 262 263 mainMenu.addSeparator() 264 mainMenu.addMenu(menu) 265 self.menu = menu 266 267 def _addVCSMenuMulti(self, mainMenu): 268 """ 269 Protected method used to add the VCS menu for multi selection to all 270 project browsers. 271 272 @param mainMenu reference to the menu to be amended 273 """ 274 self.vcsMultiMenuActions = [] 275 276 menu = QMenu(self.tr("Version Control")) 277 278 act = menu.addAction( 279 UI.PixmapCache.getIcon( 280 os.path.join("VcsPlugins", "vcsGit", "icons", "git.svg")), 281 self.vcs.vcsName(), self._VCSInfoDisplay) 282 font = act.font() 283 font.setBold(True) 284 act.setFont(font) 285 menu.addSeparator() 286 287 act = menu.addAction( 288 UI.PixmapCache.getIcon("vcsCommit"), 289 self.tr('Commit changes to repository...'), 290 self._VCSCommit) 291 self.vcsMultiMenuActions.append(act) 292 menu.addSeparator() 293 act = menu.addAction( 294 UI.PixmapCache.getIcon("vcsAdd"), 295 self.tr('Add/Stage to repository'), self._VCSAdd) 296 act = menu.addAction( 297 UI.PixmapCache.getIcon("vcsRevert"), 298 self.tr('Unstage changes'), 299 self.__GitUnstage) 300 self.vcsMultiMenuActions.append(act) 301 menu.addSeparator() 302 act = menu.addAction( 303 UI.PixmapCache.getIcon("vcsRemove"), 304 self.tr('Remove from repository (and disk)'), 305 self._VCSRemove) 306 self.vcsMultiMenuActions.append(act) 307 act = menu.addAction( 308 UI.PixmapCache.getIcon("vcsRemove"), 309 self.tr('Remove from repository only'), 310 self.__GitForget) 311 self.vcsMultiMenuActions.append(act) 312 menu.addSeparator() 313 act = menu.addAction( 314 UI.PixmapCache.getIcon("vcsStatus"), 315 self.tr('Show status'), self._VCSStatus) 316 self.vcsMultiMenuActions.append(act) 317 menu.addSeparator() 318 act = menu.addAction( 319 UI.PixmapCache.getIcon("vcsDiff"), 320 self.tr('Show differences'), self._VCSDiff) 321 self.vcsMultiMenuActions.append(act) 322 act = menu.addAction( 323 UI.PixmapCache.getIcon("vcsDiff"), 324 self.tr('Show differences (extended)'), 325 self.__GitExtendedDiff) 326 self.vcsMultiMenuActions.append(act) 327 menu.addSeparator() 328 act = menu.addAction( 329 UI.PixmapCache.getIcon("vcsRevert"), 330 self.tr('Revert changes'), self.__GitRevert) 331 self.vcsMultiMenuActions.append(act) 332 menu.addSeparator() 333 334 menu.addSeparator() 335 menu.addAction(self.tr('Select all local file entries'), 336 self.browser.selectLocalEntries) 337 menu.addAction(self.tr('Select all versioned file entries'), 338 self.browser.selectVCSEntries) 339 menu.addAction(self.tr('Select all local directory entries'), 340 self.browser.selectLocalDirEntries) 341 menu.addAction(self.tr('Select all versioned directory entries'), 342 self.browser.selectVCSDirEntries) 343 menu.addSeparator() 344 menu.addAction(self.tr("Configure..."), self.__GitConfigure) 345 346 mainMenu.addSeparator() 347 mainMenu.addMenu(menu) 348 self.menuMulti = menu 349 350 def _addVCSMenuBack(self, mainMenu): 351 """ 352 Protected method used to add the VCS menu to all project browsers. 353 354 @param mainMenu reference to the menu to be amended 355 """ 356 menu = QMenu(self.tr("Version Control")) 357 358 act = menu.addAction( 359 UI.PixmapCache.getIcon( 360 os.path.join("VcsPlugins", "vcsGit", "icons", "git.svg")), 361 self.vcs.vcsName(), self._VCSInfoDisplay) 362 font = act.font() 363 font.setBold(True) 364 act.setFont(font) 365 menu.addSeparator() 366 367 menu.addAction(self.tr('Select all local file entries'), 368 self.browser.selectLocalEntries) 369 menu.addAction(self.tr('Select all versioned file entries'), 370 self.browser.selectVCSEntries) 371 menu.addAction(self.tr('Select all local directory entries'), 372 self.browser.selectLocalDirEntries) 373 menu.addAction(self.tr('Select all versioned directory entries'), 374 self.browser.selectVCSDirEntries) 375 menu.addSeparator() 376 menu.addAction(self.tr("Configure..."), self.__GitConfigure) 377 378 mainMenu.addSeparator() 379 mainMenu.addMenu(menu) 380 self.menuBack = menu 381 382 def _addVCSMenuDir(self, mainMenu): 383 """ 384 Protected method used to add the VCS menu to all project browsers. 385 386 @param mainMenu reference to the menu to be amended 387 """ 388 if mainMenu is None: 389 return 390 391 self.vcsDirMenuActions = [] 392 self.vcsAddDirMenuActions = [] 393 394 menu = QMenu(self.tr("Version Control")) 395 396 act = menu.addAction( 397 UI.PixmapCache.getIcon( 398 os.path.join("VcsPlugins", "vcsGit", "icons", "git.svg")), 399 self.vcs.vcsName(), self._VCSInfoDisplay) 400 font = act.font() 401 font.setBold(True) 402 act.setFont(font) 403 menu.addSeparator() 404 405 act = menu.addAction( 406 UI.PixmapCache.getIcon("vcsCommit"), 407 self.tr('Commit changes to repository...'), 408 self._VCSCommit) 409 self.vcsDirMenuActions.append(act) 410 menu.addSeparator() 411 act = menu.addAction( 412 UI.PixmapCache.getIcon("vcsAdd"), 413 self.tr('Add/Stage to repository'), self._VCSAdd) 414 act = menu.addAction( 415 UI.PixmapCache.getIcon("vcsRevert"), 416 self.tr('Unstage changes'), 417 self.__GitUnstage) 418 self.vcsDirMenuActions.append(act) 419 menu.addSeparator() 420 act = menu.addAction( 421 UI.PixmapCache.getIcon("vcsRemove"), 422 self.tr('Remove from repository (and disk)'), 423 self._VCSRemove) 424 self.vcsDirMenuActions.append(act) 425 menu.addSeparator() 426 act = menu.addAction(self.tr('Copy'), self.__GitCopy) 427 self.vcsDirMenuActions.append(act) 428 act = menu.addAction(self.tr('Move'), self.__GitMove) 429 self.vcsDirMenuActions.append(act) 430 menu.addSeparator() 431 act = menu.addAction( 432 UI.PixmapCache.getIcon("vcsLog"), 433 self.tr('Show log browser'), self._VCSLogBrowser) 434 self.vcsDirMenuActions.append(act) 435 menu.addSeparator() 436 act = menu.addAction( 437 UI.PixmapCache.getIcon("vcsStatus"), 438 self.tr('Show status'), self._VCSStatus) 439 self.vcsDirMenuActions.append(act) 440 menu.addSeparator() 441 act = menu.addAction( 442 UI.PixmapCache.getIcon("vcsDiff"), 443 self.tr('Show differences'), self._VCSDiff) 444 self.vcsDirMenuActions.append(act) 445 act = menu.addAction( 446 UI.PixmapCache.getIcon("vcsDiff"), 447 self.tr('Show differences (extended)'), 448 self.__GitExtendedDiff) 449 self.vcsDirMenuActions.append(act) 450 menu.addSeparator() 451 act = menu.addAction( 452 UI.PixmapCache.getIcon("vcsRevert"), 453 self.tr('Revert changes'), self.__GitRevert) 454 self.vcsDirMenuActions.append(act) 455 menu.addSeparator() 456 457 menu.addSeparator() 458 menu.addAction(self.tr('Select all local file entries'), 459 self.browser.selectLocalEntries) 460 menu.addAction(self.tr('Select all versioned file entries'), 461 self.browser.selectVCSEntries) 462 menu.addAction(self.tr('Select all local directory entries'), 463 self.browser.selectLocalDirEntries) 464 menu.addAction(self.tr('Select all versioned directory entries'), 465 self.browser.selectVCSDirEntries) 466 menu.addSeparator() 467 menu.addAction(self.tr("Configure..."), self.__GitConfigure) 468 469 mainMenu.addSeparator() 470 mainMenu.addMenu(menu) 471 self.menuDir = menu 472 473 def _addVCSMenuDirMulti(self, mainMenu): 474 """ 475 Protected method used to add the VCS menu to all project browsers. 476 477 @param mainMenu reference to the menu to be amended 478 """ 479 if mainMenu is None: 480 return 481 482 self.vcsDirMultiMenuActions = [] 483 484 menu = QMenu(self.tr("Version Control")) 485 486 act = menu.addAction( 487 UI.PixmapCache.getIcon( 488 os.path.join("VcsPlugins", "vcsGit", "icons", "git.svg")), 489 self.vcs.vcsName(), self._VCSInfoDisplay) 490 font = act.font() 491 font.setBold(True) 492 act.setFont(font) 493 menu.addSeparator() 494 495 act = menu.addAction( 496 UI.PixmapCache.getIcon("vcsCommit"), 497 self.tr('Commit changes to repository...'), 498 self._VCSCommit) 499 self.vcsDirMultiMenuActions.append(act) 500 menu.addSeparator() 501 act = menu.addAction( 502 UI.PixmapCache.getIcon("vcsAdd"), 503 self.tr('Add/Stage to repository'), self._VCSAdd) 504 act = menu.addAction( 505 UI.PixmapCache.getIcon("vcsRevert"), 506 self.tr('Unstage changes'), 507 self.__GitUnstage) 508 self.vcsDirMultiMenuActions.append(act) 509 menu.addSeparator() 510 act = menu.addAction( 511 UI.PixmapCache.getIcon("vcsRemove"), 512 self.tr('Remove from repository (and disk)'), 513 self._VCSRemove) 514 self.vcsDirMultiMenuActions.append(act) 515 menu.addSeparator() 516 act = menu.addAction( 517 UI.PixmapCache.getIcon("vcsStatus"), 518 self.tr('Show status'), self._VCSStatus) 519 self.vcsDirMultiMenuActions.append(act) 520 menu.addSeparator() 521 act = menu.addAction( 522 UI.PixmapCache.getIcon("vcsDiff"), 523 self.tr('Show differences'), self._VCSDiff) 524 self.vcsDirMultiMenuActions.append(act) 525 act = menu.addAction( 526 UI.PixmapCache.getIcon("vcsDiff"), 527 self.tr('Show differences (extended)'), 528 self.__GitExtendedDiff) 529 self.vcsDirMultiMenuActions.append(act) 530 menu.addSeparator() 531 act = menu.addAction( 532 UI.PixmapCache.getIcon("vcsRevert"), 533 self.tr('Revert changes'), self.__GitRevert) 534 self.vcsDirMultiMenuActions.append(act) 535 menu.addSeparator() 536 537 menu.addSeparator() 538 menu.addAction(self.tr('Select all local file entries'), 539 self.browser.selectLocalEntries) 540 menu.addAction(self.tr('Select all versioned file entries'), 541 self.browser.selectVCSEntries) 542 menu.addAction(self.tr('Select all local directory entries'), 543 self.browser.selectLocalDirEntries) 544 menu.addAction(self.tr('Select all versioned directory entries'), 545 self.browser.selectVCSDirEntries) 546 menu.addSeparator() 547 menu.addAction(self.tr("Configure..."), self.__GitConfigure) 548 549 mainMenu.addSeparator() 550 mainMenu.addMenu(menu) 551 self.menuDirMulti = menu 552 553 def __GitConfigure(self): 554 """ 555 Private method to open the configuration dialog. 556 """ 557 e5App().getObject("UserInterface").showPreferences("zzz_gitPage") 558 559 def __GitForget(self): 560 """ 561 Private slot called by the context menu to remove the selected file 562 from the Git repository leaving a copy in the project directory. 563 """ 564 from UI.DeleteFilesConfirmationDialog import ( 565 DeleteFilesConfirmationDialog 566 ) 567 if self.isTranslationsBrowser: 568 items = self.browser.getSelectedItems([ProjectBrowserFileItem]) 569 names = [itm.fileName() for itm in items] 570 571 dlg = DeleteFilesConfirmationDialog( 572 self.parent(), 573 self.tr("Remove from repository only"), 574 self.tr( 575 "Do you really want to remove these files" 576 " from the repository?"), 577 names) 578 else: 579 items = self.browser.getSelectedItems() 580 names = [itm.fileName() for itm in items] 581 files = [self.browser.project.getRelativePath(name) 582 for name in names] 583 584 dlg = DeleteFilesConfirmationDialog( 585 self.parent(), 586 self.tr("Remove from repository only"), 587 self.tr( 588 "Do you really want to remove these files" 589 " from the repository?"), 590 files) 591 592 if dlg.exec() == QDialog.DialogCode.Accepted: 593 self.vcs.vcsRemove(names, stageOnly=True) 594 595 for fn in names: 596 self._updateVCSStatus(fn) 597 598 def __GitCopy(self): 599 """ 600 Private slot called by the context menu to copy the selected file. 601 """ 602 itm = self.browser.currentItem() 603 try: 604 fn = itm.fileName() 605 except AttributeError: 606 fn = itm.dirName() 607 self.vcs.gitCopy(fn, self.project) 608 609 def __GitMove(self): 610 """ 611 Private slot called by the context menu to move the selected file. 612 """ 613 itm = self.browser.currentItem() 614 try: 615 fn = itm.fileName() 616 except AttributeError: 617 fn = itm.dirName() 618 isFile = os.path.isfile(fn) 619 movefiles = self.browser.project.getFiles(fn) 620 self.browser.project.stopFileSystemMonitoring() 621 if self.vcs.vcsMove(fn, self.project): 622 if isFile: 623 self.browser.closeSourceWindow.emit(fn) 624 else: 625 for mf in movefiles: 626 self.browser.closeSourceWindow.emit(mf) 627 self.browser.project.startFileSystemMonitoring() 628 629 def __GitExtendedDiff(self): 630 """ 631 Private slot called by the context menu to show the difference of a 632 file to the repository. 633 634 This gives the chance to enter the revisions to compare. 635 """ 636 names = [] 637 for itm in self.browser.getSelectedItems(): 638 try: 639 names.append(itm.fileName()) 640 except AttributeError: 641 names.append(itm.dirName()) 642 self.vcs.gitExtendedDiff(names) 643 644 def __GitSbsDiff(self): 645 """ 646 Private slot called by the context menu to show the difference of a 647 file to the repository side-by-side. 648 """ 649 itm = self.browser.currentItem() 650 fn = itm.fileName() 651 self.vcs.gitSbsDiff(fn) 652 653 def __GitSbsExtendedDiff(self): 654 """ 655 Private slot called by the context menu to show the difference of a 656 file to the repository side-by-side. 657 658 It allows the selection of revisions to compare. 659 """ 660 itm = self.browser.currentItem() 661 fn = itm.fileName() 662 self.vcs.gitSbsDiff(fn, extended=True) 663 664 def __GitUnstage(self): 665 """ 666 Private slot to unstage changes. 667 """ 668 names = [] 669 for itm in self.browser.getSelectedItems(): 670 try: 671 name = itm.fileName() 672 except AttributeError: 673 name = itm.dirName() 674 names.append(name) 675 self.vcs.gitUnstage(names) 676 677 def __GitRevert(self): 678 """ 679 Private slot to revert changes of the working area. 680 """ 681 names = [] 682 for itm in self.browser.getSelectedItems(): 683 try: 684 name = itm.fileName() 685 except AttributeError: 686 name = itm.dirName() 687 names.append(name) 688 self.vcs.gitRevert(names) 689 690 def __GitBlame(self): 691 """ 692 Private slot called by the context menu to show the annotations of a 693 file. 694 """ 695 itm = self.browser.currentItem() 696 fn = itm.fileName() 697 self.vcs.gitBlame(fn) 698