diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 9132f9717..b8b8bdb6f 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -29,6 +29,7 @@ Changed - Scrolling with the scrollwheel while holding shift now scrolls sideways - New way of clicking hints with which solves various small issues - When yanking a mailto: link via hints, the mailto: prefix is now stripped +- Zoom level messages are now not stacked on top of each other anymore. Fixed ----- diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index adcd2e9e2..2a1988f3b 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -755,7 +755,7 @@ class CommandDispatcher: perc = tab.zoom.offset(count) except ValueError as e: raise cmdexc.CommandError(e) - message.info("Zoom level: {}%".format(perc)) + message.info("Zoom level: {}%".format(perc), replace=True) @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('count', count=True) @@ -770,7 +770,7 @@ class CommandDispatcher: perc = tab.zoom.offset(-count) except ValueError as e: raise cmdexc.CommandError(e) - message.info("Zoom level: {}%".format(perc)) + message.info("Zoom level: {}%".format(perc), replace=True) @cmdutils.register(instance='command-dispatcher', scope='window') @cmdutils.argument('count', count=True) @@ -794,7 +794,7 @@ class CommandDispatcher: tab.zoom.set_factor(float(level) / 100) except ValueError: raise cmdexc.CommandError("Can't zoom {}%!".format(level)) - message.info("Zoom level: {}%".format(level)) + message.info("Zoom level: {}%".format(level), replace=True) @cmdutils.register(instance='command-dispatcher', scope='window') def tab_only(self, prev=False, next_=False): diff --git a/qutebrowser/browser/mouse.py b/qutebrowser/browser/mouse.py index 19e37ad97..d608db466 100644 --- a/qutebrowser/browser/mouse.py +++ b/qutebrowser/browser/mouse.py @@ -124,7 +124,7 @@ class MouseEventFilter(QObject): if factor < 0: return False perc = int(100 * factor) - message.info("Zoom level: {}%".format(perc)) + message.info("Zoom level: {}%".format(perc), replace=True) self._tab.zoom.set_factor(factor) elif e.modifiers() & Qt.ShiftModifier: if e.angleDelta().y() > 0: diff --git a/qutebrowser/mainwindow/messageview.py b/qutebrowser/mainwindow/messageview.py index 3afbff102..86178716f 100644 --- a/qutebrowser/mainwindow/messageview.py +++ b/qutebrowser/mainwindow/messageview.py @@ -31,8 +31,9 @@ class Message(QLabel): """A single error/warning/info message.""" - def __init__(self, level, text, parent=None): + def __init__(self, level, text, replace, parent=None): super().__init__(text, parent) + self.replace = replace self.setAttribute(Qt.WA_StyledBackground, True) stylesheet = """ padding-top: 2px; @@ -111,13 +112,17 @@ class MessageView(QWidget): self.hide() self._clear_timer.stop() - @pyqtSlot(usertypes.MessageLevel, str) - def show_message(self, level, text): + @pyqtSlot(usertypes.MessageLevel, str, bool) + def show_message(self, level, text, replace=False): """Show the given message with the given MessageLevel.""" if text == self._last_text: return - widget = Message(level, text, parent=self) + if replace and self._messages and self._messages[-1].replace: + old = self._messages.pop() + old.hide() + + widget = Message(level, text, replace=replace, parent=self) self._vbox.addWidget(widget) widget.show() self._clear_timer.start() diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py index 368bb8289..82fe74f04 100644 --- a/qutebrowser/utils/message.py +++ b/qutebrowser/utils/message.py @@ -46,12 +46,13 @@ def _log_stack(typ, stack): log.message.debug("Stack for {} message:\n{}".format(typ, stack_text)) -def error(message, *, stack=None): +def error(message, *, stack=None, replace=False): """Convenience function to display an error message in the statusbar. Args: message: The message to show stack: The stack trace to show. + replace: Replace existing messages with replace=True """ if stack is None: stack = traceback.format_stack() @@ -60,20 +61,33 @@ def error(message, *, stack=None): typ = 'error (from exception)' _log_stack(typ, stack) log.message.error(message) - global_bridge.show_message.emit(usertypes.MessageLevel.error, message) + global_bridge.show_message.emit(usertypes.MessageLevel.error, message, + replace) -def warning(message): - """Convenience function to display a warning message in the statusbar.""" +def warning(message, *, replace=False): + """Convenience function to display a warning message in the statusbar. + + Args: + message: The message to show + replace: Replace existing messages with replace=True + """ _log_stack('warning', traceback.format_stack()) log.message.warning(message) - global_bridge.show_message.emit(usertypes.MessageLevel.warning, message) + global_bridge.show_message.emit(usertypes.MessageLevel.warning, message, + replace) -def info(message): - """Convenience function to display an info message in the statusbar.""" +def info(message, *, replace=False): + """Convenience function to display an info message in the statusbar. + + Args: + message: The message to show + replace: Replace existing messages with replace=True + """ log.message.info(message) - global_bridge.show_message.emit(usertypes.MessageLevel.info, message) + global_bridge.show_message.emit(usertypes.MessageLevel.info, message, + replace) def _build_question(title, text=None, *, mode, default=None, abort_on=()): @@ -163,6 +177,8 @@ class GlobalMessageBridge(QObject): show_message: Show a message arg 0: A MessageLevel member arg 1: The text to show + arg 2: Whether to replace other messages with + replace=True. prompt_done: Emitted when a prompt was answered somewhere. ask_question: Ask a question to the user. arg 0: The Question object to ask. @@ -173,7 +189,7 @@ class GlobalMessageBridge(QObject): mode_left: Emitted when a keymode was left in any window. """ - show_message = pyqtSignal(usertypes.MessageLevel, str) + show_message = pyqtSignal(usertypes.MessageLevel, str, bool) prompt_done = pyqtSignal(usertypes.KeyMode) ask_question = pyqtSignal(usertypes.Question, bool) mode_left = pyqtSignal(usertypes.KeyMode) diff --git a/tests/unit/mainwindow/test_messageview.py b/tests/unit/mainwindow/test_messageview.py index 310ea7180..740c090b6 100644 --- a/tests/unit/mainwindow/test_messageview.py +++ b/tests/unit/mainwindow/test_messageview.py @@ -101,3 +101,16 @@ def test_changing_timer_with_messages_shown(qtbot, view, config_stub): view.show_message(usertypes.MessageLevel.info, 'test') with qtbot.waitSignal(view._clear_timer.timeout): config_stub.set('ui', 'message-timeout', 100) + + +@pytest.mark.parametrize('replace1, replace2, length', [ + (False, False, 2), # Two stacked messages + (True, True, 1), # Two replaceable messages + (False, True, 2), # Stacked and replaceable + (True, False, 2), # Replaceable and stacked +]) +def test_replaced_messages(view, replace1, replace2, length): + """Show two stack=False messages which should replace each other.""" + view.show_message(usertypes.MessageLevel.info, 'test', replace=replace1) + view.show_message(usertypes.MessageLevel.info, 'test 2', replace=replace2) + assert len(view._messages) == length