Nice position independent next and previous change buttons

This commit is contained in:
Kovid Goyal 2014-01-29 19:08:05 +05:30
parent 9ad290dcd9
commit 848ce1ce7c
2 changed files with 50 additions and 35 deletions

View File

@ -154,22 +154,37 @@ class Diff(Dialog):
self.view = v = DiffView(self) self.view = v = DiffView(self)
l.addWidget(v, l.rowCount(), 0, 1, -1) l.addWidget(v, l.rowCount(), 0, 1, -1)
r = l.rowCount()
self.bn = b = QToolButton(self)
b.setIcon(QIcon(I('arrow-down.png')))
b.clicked.connect(partial(self.view.next_change, 1))
b.setToolTip(_('Go to next change'))
b.setText(_('&Next change')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
l.addWidget(b, r, l.columnCount(), 1, 1)
self.bp = b = QToolButton(self)
b.setIcon(QIcon(I('arrow-up.png')))
b.clicked.connect(partial(self.view.next_change, -1))
b.setToolTip(_('Go to previous change'))
b.setText(_('&Previous change')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
l.addWidget(b, r, l.columnCount(), 1, 1)
self.search = s = HistoryLineEdit2(self) self.search = s = HistoryLineEdit2(self)
s.initialize('diff_search_history') s.initialize('diff_search_history')
l.addWidget(s, l.rowCount(), 0, 1, 1) l.addWidget(s, r, l.columnCount(), 1, 1)
s.setPlaceholderText(_('Search')) s.setPlaceholderText(_('Search for text'))
s.returnPressed.connect(partial(self.do_search, False)) s.returnPressed.connect(partial(self.do_search, False))
self.sbn = b = QToolButton(self) self.sbn = b = QToolButton(self)
b.setIcon(QIcon(I('arrow-down.png'))) b.setIcon(QIcon(I('arrow-down.png')))
b.clicked.connect(partial(self.do_search, False)) b.clicked.connect(partial(self.do_search, False))
b.setToolTip(_('Find next match')) b.setToolTip(_('Find next match'))
b.setText(_('&Next')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) b.setText(_('Next &match')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
l.addWidget(b, l.rowCount() - 1, l.columnCount(), 1, 1) l.addWidget(b, l.rowCount() - 1, l.columnCount(), 1, 1)
self.sbp = b = QToolButton(self) self.sbp = b = QToolButton(self)
b.setIcon(QIcon(I('arrow-up.png'))) b.setIcon(QIcon(I('arrow-up.png')))
b.clicked.connect(partial(self.do_search, True)) b.clicked.connect(partial(self.do_search, True))
b.setToolTip(_('Find previous match')) b.setToolTip(_('Find previous match'))
b.setText(_('&Previous')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) b.setText(_('P&revious match')), b.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
l.addWidget(b, l.rowCount() - 1, l.columnCount(), 1, 1) l.addWidget(b, l.rowCount() - 1, l.columnCount(), 1, 1)
self.lb = b = QRadioButton(_('Left panel'), self) self.lb = b = QRadioButton(_('Left panel'), self)
b.setToolTip(_('Perform search in the left panel')) b.setToolTip(_('Perform search in the left panel'))

View File

@ -68,7 +68,7 @@ class TextBrowser(PlainTextEdit): # {{{
resized = pyqtSignal() resized = pyqtSignal()
wheel_event = pyqtSignal(object) wheel_event = pyqtSignal(object)
goto_change = pyqtSignal(object) next_change = pyqtSignal(object)
scrolled = pyqtSignal() scrolled = pyqtSignal()
def __init__(self, right=False, parent=None): def __init__(self, right=False, parent=None):
@ -141,27 +141,8 @@ class TextBrowser(PlainTextEdit): # {{{
a(QIcon(I('edit-copy.png')), _('Copy to clipboard'), self.copy).setShortcut(QKeySequence.Copy) a(QIcon(I('edit-copy.png')), _('Copy to clipboard'), self.copy).setShortcut(QKeySequence.Copy)
if len(self.changes) > 0: if len(self.changes) > 0:
try: a(QIcon(I('arrow-up.png')), _('Previous change'), partial(self.next_change.emit, -1))
b = self.cursorForPosition(pos).block().blockNumber() a(QIcon(I('arrow-down.png')), _('Next change'), partial(self.next_change.emit, 1))
except Exception:
b = -1
if b > -1:
pc = nc = None
for i, (top, bot, kind) in enumerate(self.changes):
if top <= b and bot >= b:
if len(self.changes) == 1:
break
pc = (i - 1) % len(self.changes)
nc = (i + 1) % len(self.changes)
if bot < b:
pc = i
if top > b:
nc = i
break
if pc is not None:
a(QIcon(I('arrow-up.png')), _('Previous change'), partial(self.goto_change.emit, pc))
if nc is not None:
a(QIcon(I('arrow-down.png')), _('Next change'), partial(self.goto_change.emit, nc))
if len(m.actions()) > 0: if len(m.actions()) > 0:
m.exec_(self.mapToGlobal(pos)) m.exec_(self.mapToGlobal(pos))
@ -877,17 +858,36 @@ class DiffView(QWidget): # {{{
for i, v in enumerate((self.view.left, self.view.right, self.view.handle(1))): for i, v in enumerate((self.view.left, self.view.right, self.view.handle(1))):
v.wheel_event.connect(self.scrollbar.wheelEvent) v.wheel_event.connect(self.scrollbar.wheelEvent)
if i < 2: if i < 2:
v.goto_change.connect(self.goto_change) v.next_change.connect(self.next_change)
v.scrolled.connect(partial(self.scrolled, i + 1)) v.scrolled.connect(partial(self.scrolled, i + 1))
def goto_change(self, change): def next_change(self, delta):
for v in (self.view.left, self.view.right): assert delta in (1, -1)
c = QTextCursor(v.document().findBlockByNumber(v.changes[change][0])) position = self.get_position_from_scrollbar(0)
v.setTextCursor(c) if position[0] == 'in':
v.centerCursor() p = n = position[1]
with self: else:
self.scroll_to(0, self.get_position_from_scrollbar(1)) p, n = position[1], position[1] + 1
self.view.handle(1).update() if p < 0:
p = None
if n >= len(self.changes[0]):
n = None
if p == n:
nc = p + delta
if nc < 0 or nc >= len(self.changes[0]):
nc = None
else:
nc = {1:n, -1:p}[delta]
if nc is None:
self.scrollbar.setValue(0 if delta == -1 else self.scrollbar.maximum())
else:
val = self.scrollbar.value()
self.scroll_to(0, ('in', nc, 0))
nval = self.scrollbar.value()
if nval == val:
nval += 5 * delta
if 0 <= nval <= self.scrollbar.maximum():
self.scrollbar.setValue(nval)
def resized(self): def resized(self):
self.resize_timer.start(300) self.resize_timer.start(300)