From 848ce1ce7c0d661d8cdb7e709fa23f7b46e98b53 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 29 Jan 2014 19:08:05 +0530 Subject: [PATCH] Nice position independent next and previous change buttons --- src/calibre/gui2/tweak_book/diff/main.py | 23 +++++++-- src/calibre/gui2/tweak_book/diff/view.py | 62 ++++++++++++------------ 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/calibre/gui2/tweak_book/diff/main.py b/src/calibre/gui2/tweak_book/diff/main.py index f2c9b3f5ef..04c9c3fb4f 100644 --- a/src/calibre/gui2/tweak_book/diff/main.py +++ b/src/calibre/gui2/tweak_book/diff/main.py @@ -154,22 +154,37 @@ class Diff(Dialog): self.view = v = DiffView(self) 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) s.initialize('diff_search_history') - l.addWidget(s, l.rowCount(), 0, 1, 1) - s.setPlaceholderText(_('Search')) + l.addWidget(s, r, l.columnCount(), 1, 1) + s.setPlaceholderText(_('Search for text')) s.returnPressed.connect(partial(self.do_search, False)) self.sbn = b = QToolButton(self) b.setIcon(QIcon(I('arrow-down.png'))) b.clicked.connect(partial(self.do_search, False)) 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) self.sbp = b = QToolButton(self) b.setIcon(QIcon(I('arrow-up.png'))) b.clicked.connect(partial(self.do_search, True)) 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) self.lb = b = QRadioButton(_('Left panel'), self) b.setToolTip(_('Perform search in the left panel')) diff --git a/src/calibre/gui2/tweak_book/diff/view.py b/src/calibre/gui2/tweak_book/diff/view.py index 95047a170a..34733f640f 100644 --- a/src/calibre/gui2/tweak_book/diff/view.py +++ b/src/calibre/gui2/tweak_book/diff/view.py @@ -68,7 +68,7 @@ class TextBrowser(PlainTextEdit): # {{{ resized = pyqtSignal() wheel_event = pyqtSignal(object) - goto_change = pyqtSignal(object) + next_change = pyqtSignal(object) scrolled = pyqtSignal() 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) if len(self.changes) > 0: - try: - b = self.cursorForPosition(pos).block().blockNumber() - 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)) + a(QIcon(I('arrow-up.png')), _('Previous change'), partial(self.next_change.emit, -1)) + a(QIcon(I('arrow-down.png')), _('Next change'), partial(self.next_change.emit, 1)) if len(m.actions()) > 0: 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))): v.wheel_event.connect(self.scrollbar.wheelEvent) 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)) - def goto_change(self, change): - for v in (self.view.left, self.view.right): - c = QTextCursor(v.document().findBlockByNumber(v.changes[change][0])) - v.setTextCursor(c) - v.centerCursor() - with self: - self.scroll_to(0, self.get_position_from_scrollbar(1)) - self.view.handle(1).update() + def next_change(self, delta): + assert delta in (1, -1) + position = self.get_position_from_scrollbar(0) + if position[0] == 'in': + p = n = position[1] + else: + p, n = position[1], position[1] + 1 + 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): self.resize_timer.start(300)