PageRenderTime 37ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/tortoisehg/hgqt/revdetails.py

https://bitbucket.org/tortoisehg/hgtk/
Python | 241 lines | 185 code | 38 blank | 18 comment | 5 complexity | be56892010fd1b2f246823ec62863242 MD5 | raw file
Possible License(s): GPL-2.0
  1. # repowidget.py - TortoiseHg repository widget
  2. #
  3. # Copyright (C) 2007-2010 Logilab. All rights reserved.
  4. # Copyright (C) 2010 Adrian Buehlmann <adrian@cadifra.com>
  5. #
  6. # This software may be used and distributed according to the terms
  7. # of the GNU General Public License, incorporated herein by reference.
  8. from tortoisehg.hgqt.qtlib import getfont, geticon, descriptionhtmlizer
  9. from tortoisehg.hgqt.i18n import _
  10. from tortoisehg.hgqt.filelistmodel import HgFileListModel
  11. from tortoisehg.hgqt.filelistview import HgFileListView
  12. from tortoisehg.hgqt.fileview import HgFileView
  13. from tortoisehg.hgqt.revpanel import RevPanelWidget
  14. from tortoisehg.hgqt import thgrepo, qscilib
  15. from PyQt4.QtCore import *
  16. from PyQt4.QtGui import *
  17. class RevDetailsWidget(QWidget):
  18. showMessage = pyqtSignal(QString)
  19. linkActivated = pyqtSignal(unicode)
  20. grepRequested = pyqtSignal(unicode, dict)
  21. revisionSelected = pyqtSignal(int)
  22. def __init__(self, repo):
  23. QWidget.__init__(self)
  24. self.repo = repo
  25. self.splitternames = []
  26. self._deschtmlize = descriptionhtmlizer(repo.ui)
  27. repo.configChanged.connect(self._updatedeschtmlizer)
  28. # these are used to know where to go after a reload
  29. self._last_rev = None
  30. self._reload_file = None
  31. self.setupUi()
  32. self.createActions()
  33. self.setupModels()
  34. self.fileview.setFont(getfont('fontdiff').font())
  35. self.fileview.showMessage.connect(self.showMessage)
  36. self.fileview.grepRequested.connect(self.grepRequested)
  37. self.fileview.revisionSelected.connect(self.revisionSelected)
  38. self.restoreSettings()
  39. def setRepo(self, repo):
  40. self.repo = repo
  41. def setupUi(self):
  42. SP = QSizePolicy
  43. sp = SP(SP.Preferred, SP.Expanding)
  44. sp.setHorizontalStretch(0)
  45. sp.setVerticalStretch(0)
  46. sp.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
  47. self.setSizePolicy(sp)
  48. # + revisiondetails_layout -----------------------------------------+
  49. # |+ filelist_splitter ........ |
  50. # | + tbarFileListFrame (vbox)| + cset_and_file_details_frame (vbox)|
  51. # | + mergeToolbar | + revpanel |
  52. # +---------------------------+-------------------------------------+
  53. # | + filelist | + message_splitter |
  54. # | | :+ message |
  55. # | | :----------------------------------+
  56. # | | + fileview |
  57. # +---------------------------+-------------------------------------+
  58. revisiondetails_layout = QVBoxLayout(self)
  59. revisiondetails_layout.setSpacing(0)
  60. revisiondetails_layout.setMargin(0)
  61. revisiondetails_layout.setContentsMargins(2, 2, 2, 2)
  62. self.filelist_splitter = QSplitter(self)
  63. self.splitternames.append('filelist_splitter')
  64. sp = SP(SP.Expanding, SP.Expanding)
  65. sp.setHorizontalStretch(0)
  66. sp.setVerticalStretch(0)
  67. sp.setHeightForWidth(self.filelist_splitter.sizePolicy().hasHeightForWidth())
  68. self.filelist_splitter.setSizePolicy(sp)
  69. self.filelist_splitter.setOrientation(Qt.Horizontal)
  70. self.filelist_splitter.setChildrenCollapsible(False)
  71. self.mergeToolBar = QToolBar(_('Merge Toolbar'))
  72. self.mergeToolBar.setIconSize(QSize(16,16))
  73. self.filelist = HgFileListView()
  74. self.tbarFileListFrame = QFrame(self.filelist_splitter)
  75. sp = SP(SP.Preferred, SP.Preferred)
  76. sp.setHorizontalStretch(3)
  77. sp.setVerticalStretch(0)
  78. sp.setHeightForWidth(
  79. self.tbarFileListFrame.sizePolicy().hasHeightForWidth())
  80. self.tbarFileListFrame.setSizePolicy(sp)
  81. self.tbarFileListFrame.setFrameShape(QFrame.NoFrame)
  82. vbox = QVBoxLayout()
  83. vbox.setSpacing(0)
  84. vbox.setMargin(0)
  85. vbox.addWidget(self.mergeToolBar)
  86. vbox.addWidget(self.filelist)
  87. self.tbarFileListFrame.setLayout(vbox)
  88. self.cset_and_file_details_frame = QFrame(self.filelist_splitter)
  89. sp = SP(SP.Preferred, SP.Preferred)
  90. sp.setHorizontalStretch(7)
  91. sp.setVerticalStretch(0)
  92. sp.setHeightForWidth(
  93. self.cset_and_file_details_frame.sizePolicy().hasHeightForWidth())
  94. self.cset_and_file_details_frame.setSizePolicy(sp)
  95. self.cset_and_file_details_frame.setFrameShape(QFrame.NoFrame)
  96. vbox = QVBoxLayout(self.cset_and_file_details_frame)
  97. vbox.setSpacing(0)
  98. vbox.setSizeConstraint(QLayout.SetDefaultConstraint)
  99. vbox.setMargin(0)
  100. cset_and_file_details_layout = vbox
  101. self.message_splitter = QSplitter(self.cset_and_file_details_frame)
  102. self.splitternames.append('message_splitter')
  103. sp = SP(SP.Preferred, SP.Expanding)
  104. sp.setHorizontalStretch(0)
  105. sp.setVerticalStretch(0)
  106. sp.setHeightForWidth(self.message_splitter.sizePolicy().hasHeightForWidth())
  107. self.message_splitter.setSizePolicy(sp)
  108. self.message_splitter.setMinimumSize(QSize(50, 50))
  109. self.message_splitter.setFrameShape(QFrame.NoFrame)
  110. self.message_splitter.setLineWidth(0)
  111. self.message_splitter.setMidLineWidth(0)
  112. self.message_splitter.setOrientation(Qt.Vertical)
  113. self.message_splitter.setOpaqueResize(True)
  114. self.message = QTextBrowser(self.message_splitter,
  115. lineWrapMode=QTextEdit.NoWrap,
  116. openLinks=False)
  117. self.message.minimumSizeHint = lambda: QSize(0, 25)
  118. self.message.anchorClicked.connect(
  119. lambda url: self.linkActivated.emit(url.toString()))
  120. sp = SP(SP.Expanding, SP.Expanding)
  121. sp.setHorizontalStretch(0)
  122. sp.setVerticalStretch(2)
  123. sp.setHeightForWidth(self.message.sizePolicy().hasHeightForWidth())
  124. self.message.setSizePolicy(sp)
  125. self.message.setMinimumSize(QSize(0, 0))
  126. f = getfont('fontcomment')
  127. self.message.setFont(f.font())
  128. f.changed.connect(lambda font: self.message.setFont(font))
  129. self.fileview = HgFileView(self.repo, self.message_splitter)
  130. sp = SP(SP.Expanding, SP.Expanding)
  131. sp.setHorizontalStretch(0)
  132. sp.setVerticalStretch(5)
  133. sp.setHeightForWidth(self.fileview.sizePolicy().hasHeightForWidth())
  134. self.fileview.setSizePolicy(sp)
  135. self.fileview.setMinimumSize(QSize(0, 0))
  136. self.revpanel = RevPanelWidget(self.repo)
  137. self.revpanel.linkActivated.connect(self.linkActivated)
  138. cset_and_file_details_layout.addWidget(self.revpanel)
  139. cset_and_file_details_layout.addWidget(self.message_splitter)
  140. revisiondetails_layout.addWidget(self.filelist_splitter)
  141. self.filelist.fileRevSelected.connect(self.onFileRevSelected)
  142. self.filelist.clearDisplay.connect(self.fileview.clearDisplay)
  143. def createActions(self):
  144. def fileActivated():
  145. idx = self.filelist.currentIndex()
  146. self.filelist.fileActivated(idx, alternate=True)
  147. self.actionActivateFileAlt = QAction('Activate alt. file', self)
  148. self.actionActivateFileAlt.setShortcuts([Qt.ALT+Qt.Key_Return,
  149. Qt.ALT+Qt.Key_Enter])
  150. self.actionActivateFileAlt.triggered.connect(fileActivated)
  151. self.mergeToolBar.addAction(self.filelist.actionShowAllMerge)
  152. def create_models(self):
  153. self.filelistmodel = HgFileListModel(self.repo, self)
  154. def setupModels(self):
  155. self.create_models()
  156. self.filelist.setModel(self.filelistmodel)
  157. @pyqtSlot(object, object, object)
  158. def onFileRevSelected(self, file, rev, status):
  159. self.fileview.displayFile(file, rev, status)
  160. def revision_selected(self, rev):
  161. self._last_rev = rev
  162. ctx = self.repo.changectx(rev)
  163. self.revpanel.set_revision(rev)
  164. self.revpanel.update(repo = self.repo)
  165. self.message.setHtml('<pre>%s</pre>'
  166. % self._deschtmlize(ctx.description()))
  167. self.fileview.setContext(ctx)
  168. self.filelistmodel.setContext(ctx)
  169. @pyqtSlot()
  170. def _updatedeschtmlizer(self):
  171. self._deschtmlize = descriptionhtmlizer(self.repo.ui)
  172. self.revision_selected(self._last_rev) # regenerate desc html
  173. def record(self):
  174. 'Repo widget is reloading, record current file'
  175. self._reload_file = self.filelist.currentFile()
  176. def finishReload(self):
  177. 'Finish reload by re-selecting previous file'
  178. if self._reload_file:
  179. self.filelist.selectFile(self._reload_file)
  180. elif not self.filelist.selectedIndexes():
  181. self.filelist.selectRow(0)
  182. def reload(self):
  183. 'Task tab is reloaded, or repowidget is refreshed'
  184. if len(self.repo) <= self._last_rev:
  185. self._last_rev = '.'
  186. f = self.filelist.currentFile()
  187. self.revision_selected(self._last_rev)
  188. self.filelist.selectFile(f)
  189. def storeSettings(self):
  190. s = QSettings()
  191. wb = "RevDetailsWidget/"
  192. for n in self.splitternames:
  193. s.setValue(wb + n, getattr(self, n).saveState())
  194. s.setValue(wb + 'revpanel.expanded', self.revpanel.is_expanded())
  195. self.fileview.saveSettings(s, 'revpanel/fileview')
  196. def restoreSettings(self):
  197. s = QSettings()
  198. wb = "RevDetailsWidget/"
  199. for n in self.splitternames:
  200. getattr(self, n).restoreState(s.value(wb + n).toByteArray())
  201. expanded = s.value(wb + 'revpanel.expanded', False).toBool()
  202. self.revpanel.set_expanded(expanded)
  203. self.fileview.loadSettings(s, 'revpanel/fileview')