repofilter.py 6.33 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
# repofilter.py - TortoiseHg toolbar for filtering changesets
#
# Copyright (C) 2007-2010 Logilab. All rights reserved.
# Copyright (C) 2010 Yuya Nishihara <yuya@tcha.org>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

Yuya Nishihara's avatar
Yuya Nishihara committed
12
from tortoisehg.hgqt.i18n import _
13
from tortoisehg.hgqt import revset, qtlib
Yuya Nishihara's avatar
Yuya Nishihara committed
14

15
16
17
class RepoFilterBar(QToolBar):
    """Toolbar for RepoWidget to filter changesets"""

18
19
    revisionSet = pyqtSignal(object)
    clearSet = pyqtSignal()
20
    filterToggled = pyqtSignal(bool)
21
22
23
24

    showMessage = pyqtSignal(QString)
    progress = pyqtSignal(QString, object, QString, QString, object)

25
26
27
    branchChanged = pyqtSignal(unicode, bool)
    """Emitted (branch, allparents) when branch selection changed"""

28
    def __init__(self, repo, parent):
29
30
        super(RepoFilterBar, self).__init__(parent)
        self.layout().setContentsMargins(0, 0, 0, 0)
31
32
33
        self.setIconSize(QSize(16,16))
        self.setFloatable(False)
        self.setMovable(False)
34
35
        self._repo = repo

36
37
38
39
40
41
        closeact = QAction('Close', self)
        closeact.setIcon(qtlib.geticon('close'))
        closeact.setShortcut(Qt.Key_Escape)
        closeact.triggered.connect(self.hide)
        self.addAction(closeact)

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        self.entrydlg = revset.RevisionSetQuery(repo, self)
        self.entrydlg.progress.connect(self.progress)
        self.entrydlg.showMessage.connect(self.showMessage)
        self.entrydlg.queryIssued.connect(self.dialogQuery)
        self.entrydlg.hide()

        self.clear = QPushButton(_('clear'))
        self.addWidget(self.clear)

        self.editor = QPushButton(_('editor'))
        self.editor.clicked.connect(self.openEditor)
        self.addWidget(self.editor)

        s = QSettings()
        self.entrydlg.restoreGeometry(s.value('revset/geom').toByteArray())
        self.revsethist = list(s.value('revset-queries').toStringList())
        self.revsetle = le = QLineEdit()
        le.setCompleter(QCompleter(self.revsethist))
        le.returnPressed.connect(self.returnPressed)
61
62
        if hasattr(self.revsetle, 'setPlaceholderText'): # Qt >= 4.7 
            self.revsetle.setPlaceholderText('### revision set query ###')
63
64
65
66
67
        self.addWidget(le)

        self.clear.clicked.connect(le.clear)
        self.clear.clicked.connect(self.clearSet)

68
69
70
71
72
        self.filtercb = f = QCheckBox(_('filter'))
        f.setChecked(s.value('revset-filter').toBool())
        f.toggled.connect(self.filterToggled)
        self.addWidget(f)

73
74
75
76
77
        self.store = store = QPushButton(_('store'))
        store.clicked.connect(self.saveQuery)
        le.textChanged.connect(lambda t: store.setEnabled(False))
        store.setEnabled(False)
        self.addWidget(store)
78
79
80
81

        self._initbranchfilter()
        self.refresh()

82
83
84
    def showEvent(self, event):
        self.revsetle.setFocus()

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    def openEditor(self):
        query = self.revsetle.text().simplified()
        self.entrydlg.entry.setText(query)
        self.entrydlg.entry.setCursorPosition(0, len(query))
        self.entrydlg.entry.setFocus()
        self.entrydlg.setShown(True)

    def dialogQuery(self, query, revset):
        self.revsetle.setText(query)
        self.store.setEnabled(True)
        self.revisionSet.emit(revset)

    def returnPressed(self):
        'Return pressed on revset line entry, forward to dialog'
        query = self.revsetle.text().simplified()
        if query:
            self.entrydlg.entry.setText(query)
            self.entrydlg.runQuery()

    def saveQuery(self):
        query = self.revsetle.text()
        if query in self.revsethist:
            self.revsethist.remove(query)
        self.revsethist.insert(0, query)
        self.revsetle.setCompleter(QCompleter(self.revsethist))
        self.store.setEnabled(False)
        self.showMessage.emit(_('Revision set query saved'))

    def storeConfigs(self, s):
        s.setValue('revset/geom', self.entrydlg.saveGeometry())
        s.setValue('revset-queries', self.revsethist)
116
        s.setValue('revset-filter', self.filtercb.isChecked())
117

118
    def _initbranchfilter(self):
119
        self._branchLabel = QToolButton(
120
121
            text=_('Branch'), popupMode=QToolButton.InstantPopup,
            statusTip=_('Display graph the named branch only'))
122
123
        self._branchMenu = QMenu(self._branchLabel)
        self._cbranchAction = self._branchMenu.addAction(
124
            _('Display closed branches'), self.refresh)
125
126
        self._cbranchAction.setCheckable(True)
        self._allparAction = self._branchMenu.addAction(
127
            _('Include all ancestors'), self._emitBranchChanged)
128
129
        self._allparAction.setCheckable(True)
        self._branchLabel.setMenu(self._branchMenu)
130

131
132
        self._branchCombo = QComboBox()
        self._branchCombo.currentIndexChanged.connect(self._emitBranchChanged)
133

134
135
        self.addWidget(self._branchLabel)
        self.addWidget(self._branchCombo)
136
137
138
139
140

    def _updatebranchfilter(self):
        """Update the list of branches"""
        curbranch = self.branch()

141
142
143
144
145
146
147
148
        def iterbranches(all=False):
            allbranches = self._repo.branchtags()
            if all:
                return sorted(allbranches.keys())

            openbrnodes = []
            for br in allbranches.iterkeys():
                openbrnodes.extend(self._repo.branchheads(br, closed=False))
149
            dead = self._repo.deadbranches
150
            return sorted(br for br, n in allbranches.iteritems()
151
                          if n in openbrnodes and br not in dead)
152

153
154
155
156
157
        branches = list(iterbranches(all=self._cbranchAction.isChecked()))
        self._branchCombo.clear()
        self._branchCombo.addItems([''] + branches)
        self._branchLabel.setEnabled(len(branches) > 1)
        self._branchCombo.setEnabled(len(branches) > 1)
158
159
160
161
162
163

        self.setBranch(curbranch)

    @pyqtSlot(unicode)
    def setBranch(self, branch):
        """Change the current branch by name [unicode]"""
164
        self._branchCombo.setCurrentIndex(self._branchCombo.findText(branch))
165
166
167

    def branch(self):
        """Return the current branch name [unicode]"""
168
        return unicode(self._branchCombo.currentText())
169
170
171
172

    @pyqtSlot()
    def _emitBranchChanged(self):
        self.branchChanged.emit(self.branch(),
173
                                self._allparAction.isChecked())
174
175
176
177

    @pyqtSlot()
    def refresh(self):
        self._updatebranchfilter()