Read about our upcoming Code of Conduct on this issue

revdetails.py 9.66 KB
Newer Older
1
2
3
4
5
6
7
8
# repowidget.py - TortoiseHg repository widget
#
# Copyright (C) 2007-2010 Logilab. All rights reserved.
# Copyright (C) 2010 Adrian Buehlmann <adrian@cadifra.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

9
from tortoisehg.hgqt.qtlib import getfont, geticon, descriptionhtmlizer
10
11
from tortoisehg.hgqt.i18n import _
from tortoisehg.hgqt.filelistmodel import HgFileListModel
12
13
from tortoisehg.hgqt.filelistview import HgFileListView
from tortoisehg.hgqt.fileview import HgFileView
14
from tortoisehg.hgqt.revpanel import RevPanelWidget
15
from tortoisehg.hgqt import thgrepo, qscilib
16

17
18
19
20
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class RevDetailsWidget(QWidget):
21

22
    showMessage = pyqtSignal(QString)
23
    linkActivated = pyqtSignal(unicode)
24
25
    grepRequested = pyqtSignal(unicode, dict)
    revForDiffChanged = pyqtSignal(int)
26

27
    def __init__(self, repo):
28
29
        QWidget.__init__(self)

30
        self.repo = repo
31
        self.splitternames = []
32

33
        self._deschtmlize = descriptionhtmlizer(repo.ui)
34
        repo.configChanged.connect(self._updatedeschtmlizer)
35

36
        # these are used to know where to go after a reload
37
        self._last_rev = None
38
39
40
41
        self._reload_file = None

        self.setupUi()
        self.createActions()
42
        self.setupModels()
43

44
        self.fileview.setFont(getfont('fontdiff').font())
45
        self.fileview.showMessage.connect(self.showMessage)
46
47
        self.fileview.grepRequested.connect(self.grepRequested)
        self.fileview.revForDiffChanged.connect(self.revForDiffChanged)
48
49
        self.restoreSettings()

50
51
52
    def setRepo(self, repo):
        self.repo = repo

53
    def setupUi(self):
54
        SP = QSizePolicy
55
56
57
        sp = SP(SP.Preferred, SP.Expanding)
        sp.setHorizontalStretch(0)
        sp.setVerticalStretch(0)
58
59
        sp.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sp)
60

61
62
63
        # + revisiondetails_layout -----------------------------------------+
        # |+ filelist_splitter ........                                     |
        # | + tbarFileListFrame (vbox)| + cset_and_file_details_frame (vbox)|
64
        # |  + mergeToolbar           |  + revpanel                         |
65
66
67
68
69
70
71
        # +---------------------------+-------------------------------------+
        # |  + filelist               |  + message_splitter                 |
        # |                           |  :+ message                         |
        # |                           |  :----------------------------------+
        # |                           |   + fileview                        |
        # +---------------------------+-------------------------------------+

72
        revisiondetails_layout = QVBoxLayout(self)
73
74
        revisiondetails_layout.setSpacing(0)
        revisiondetails_layout.setMargin(0)
75
        revisiondetails_layout.setContentsMargins(2, 2, 2, 2)
76

77
        self.filelist_splitter = QSplitter(self)
78
79
80
81
82
83
84
        self.splitternames.append('filelist_splitter')

        sp = SP(SP.Expanding, SP.Expanding)
        sp.setHorizontalStretch(0)
        sp.setVerticalStretch(0)
        sp.setHeightForWidth(self.filelist_splitter.sizePolicy().hasHeightForWidth())
        self.filelist_splitter.setSizePolicy(sp)
85
        self.filelist_splitter.setOrientation(Qt.Horizontal)
86
87
        self.filelist_splitter.setChildrenCollapsible(False)

88
89
        self.mergeToolBar = QToolBar(_('Merge Toolbar'))
        self.mergeToolBar.setIconSize(QSize(16,16))
90
91
92
93
        self.filelist = HgFileListView()

        self.tbarFileListFrame = QFrame(self.filelist_splitter)
        sp = SP(SP.Preferred, SP.Preferred)
94
        sp.setHorizontalStretch(3)
95
96
97
98
99
100
101
102
        sp.setVerticalStretch(0)
        sp.setHeightForWidth(
            self.tbarFileListFrame.sizePolicy().hasHeightForWidth())
        self.tbarFileListFrame.setSizePolicy(sp)
        self.tbarFileListFrame.setFrameShape(QFrame.NoFrame)
        vbox = QVBoxLayout()
        vbox.setSpacing(0)
        vbox.setMargin(0)
103
        vbox.addWidget(self.mergeToolBar)
104
105
        vbox.addWidget(self.filelist)
        self.tbarFileListFrame.setLayout(vbox)
106

107
        self.cset_and_file_details_frame = QFrame(self.filelist_splitter)
108
        sp = SP(SP.Preferred, SP.Preferred)
109
        sp.setHorizontalStretch(7)
110
111
112
113
        sp.setVerticalStretch(0)
        sp.setHeightForWidth(
            self.cset_and_file_details_frame.sizePolicy().hasHeightForWidth())
        self.cset_and_file_details_frame.setSizePolicy(sp)
114
        self.cset_and_file_details_frame.setFrameShape(QFrame.NoFrame)
115

116
        vbox = QVBoxLayout(self.cset_and_file_details_frame)
117
        vbox.setSpacing(0)
118
        vbox.setSizeConstraint(QLayout.SetDefaultConstraint)
119
120
121
        vbox.setMargin(0)
        cset_and_file_details_layout = vbox

122
        self.message_splitter = QSplitter(self.cset_and_file_details_frame)
123
124
125
126
127
128
        self.splitternames.append('message_splitter')
        sp = SP(SP.Preferred, SP.Expanding)
        sp.setHorizontalStretch(0)
        sp.setVerticalStretch(0)
        sp.setHeightForWidth(self.message_splitter.sizePolicy().hasHeightForWidth())
        self.message_splitter.setSizePolicy(sp)
129
130
        self.message_splitter.setMinimumSize(QSize(50, 50))
        self.message_splitter.setFrameShape(QFrame.NoFrame)
131
132
133
134
        self.message_splitter.setLineWidth(0)
        self.message_splitter.setMidLineWidth(0)
        self.message_splitter.setOrientation(Qt.Vertical)
        self.message_splitter.setOpaqueResize(True)
135
136
137
138
139
140
        self.message = QTextBrowser(self.message_splitter,
                                    lineWrapMode=QTextEdit.NoWrap,
                                    openLinks=False)
        self.message.minimumSizeHint = lambda: QSize(0, 25)
        self.message.anchorClicked.connect(
            lambda url: self.linkActivated.emit(url.toString()))
141
142
143

        sp = SP(SP.Expanding, SP.Expanding)
        sp.setHorizontalStretch(0)
144
        sp.setVerticalStretch(2)
145
146
        sp.setHeightForWidth(self.message.sizePolicy().hasHeightForWidth())
        self.message.setSizePolicy(sp)
147
        self.message.setMinimumSize(QSize(0, 0))
148
149
150
        f = getfont('fontcomment')
        self.message.setFont(f.font())
        f.changed.connect(lambda font: self.message.setFont(font))
151

152
        self.fileview = HgFileView(self.repo, self.message_splitter)
153
154
        sp = SP(SP.Expanding, SP.Expanding)
        sp.setHorizontalStretch(0)
155
        sp.setVerticalStretch(5)
156
157
        sp.setHeightForWidth(self.fileview.sizePolicy().hasHeightForWidth())
        self.fileview.setSizePolicy(sp)
158
        self.fileview.setMinimumSize(QSize(0, 0))
159

160
        self.revpanel = RevPanelWidget(self.repo)
161
        self.revpanel.linkActivated.connect(self.linkActivated)
162
163
164
165
166
167

        cset_and_file_details_layout.addWidget(self.revpanel)
        cset_and_file_details_layout.addWidget(self.message_splitter)

        revisiondetails_layout.addWidget(self.filelist_splitter)

168
        self.filelist.fileRevSelected.connect(self.onFileRevSelected)
169
        self.filelist.clearDisplay.connect(self.fileview.clearDisplay)
170

171
    def createActions(self):
172
173
174
        def fileActivated():
            idx = self.filelist.currentIndex()
            self.filelist.fileActivated(idx, alternate=True)
175
        self.actionActivateFileAlt = QAction('Activate alt. file', self)
176
177
        self.actionActivateFileAlt.setShortcuts([Qt.ALT+Qt.Key_Return,
                                                 Qt.ALT+Qt.Key_Enter])
178
179
        self.actionActivateFileAlt.triggered.connect(fileActivated)
        self.mergeToolBar.addAction(self.filelist.actionShowAllMerge)
180
181

    def create_models(self):
182
        self.filelistmodel = HgFileListModel(self.repo, self)
183

184
    def setupModels(self):
185
        self.create_models()
186
        self.filelist.setModel(self.filelistmodel)
187

188
    @pyqtSlot(object, object, object)
189
    def onFileRevSelected(self, file, rev, status):
190
        self.fileview.displayFile(file, rev, status)
191

192
    def revision_selected(self, rev):
193
        self._last_rev = rev
194
        ctx = self.repo.changectx(rev)
195
        self.revpanel.set_revision(rev)
196
        self.revpanel.update(repo = self.repo)
197
198
        self.message.setHtml('<pre>%s</pre>'
                             % self._deschtmlize(ctx.description()))
Steve Borho's avatar
Steve Borho committed
199
        self.fileview.setContext(ctx)
200
201
        self.filelistmodel.setContext(ctx)

202
203
204
205
206
    @pyqtSlot()
    def _updatedeschtmlizer(self):
        self._deschtmlize = descriptionhtmlizer(self.repo.ui)
        self.revision_selected(self._last_rev)  # regenerate desc html

207
208
    def record(self):
        'Repo widget is reloading, record current file'
209
        self._reload_file = self.filelist.currentFile()
210
211
212

    def finishReload(self):
        'Finish reload by re-selecting previous file'
213
214
215
216
        if self._reload_file:
            self.filelist.selectFile(self._reload_file)
        elif not self.filelist.selectedIndexes():
            self.filelist.selectRow(0)
217
218
219

    def reload(self):
        'Task tab is reloaded, or repowidget is refreshed'
220
221
222
223
224
        if len(self.repo) <= self._last_rev:
            self._last_rev = '.'
        f = self.filelist.currentFile()
        self.revision_selected(self._last_rev)
        self.filelist.selectFile(f)
225
226

    def storeSettings(self):
227
        s = QSettings()
228
229
230
231
        wb = "RevDetailsWidget/"
        for n in self.splitternames:
            s.setValue(wb + n, getattr(self, n).saveState())
        s.setValue(wb + 'revpanel.expanded', self.revpanel.is_expanded())
232
        self.fileview.saveSettings(s, 'revpanel/fileview')
233
234

    def restoreSettings(self):
235
        s = QSettings()
236
237
238
        wb = "RevDetailsWidget/"
        for n in self.splitternames:
            getattr(self, n).restoreState(s.value(wb + n).toByteArray())
239
        expanded = s.value(wb + 'revpanel.expanded', False).toBool()
240
        self.revpanel.set_expanded(expanded)
241
        self.fileview.loadSettings(s, 'revpanel/fileview')