Don't stack zoom level messages

Fixes #1980
This commit is contained in:
Florian Bruhin 2017-02-04 23:42:55 +01:00
parent 2c46f8ecdb
commit 021b3645cc
6 changed files with 52 additions and 17 deletions

View File

@ -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
-----

View File

@ -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):

View File

@ -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:

View File

@ -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()

View File

@ -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)

View File

@ -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