summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2022-06-14 16:01:16 +0200
committerFlorian Bruhin <me@the-compiler.org>2022-06-14 17:05:40 +0200
commitd576a8d88f7141e2037137a423fc4714c4ef4e41 (patch)
tree3cf887c10f34ca582429d38924117c616ed68bfd
parent5616a99eff34f7074641d1391ed77d6b4b743529 (diff)
downloadqutebrowser-d576a8d88f7141e2037137a423fc4714c4ef4e41.tar.gz
qutebrowser-d576a8d88f7141e2037137a423fc4714c4ef4e41.zip
Don't render messages at Qt rich text by default
Closes #7246
-rw-r--r--qutebrowser/browser/webengine/notification.py2
-rw-r--r--qutebrowser/mainwindow/messageview.py21
-rw-r--r--qutebrowser/utils/message.py21
-rw-r--r--tests/unit/mainwindow/test_messageview.py43
4 files changed, 80 insertions, 7 deletions
diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py
index 3571bb24d..2ebe99e33 100644
--- a/qutebrowser/browser/webengine/notification.py
+++ b/qutebrowser/browser/webengine/notification.py
@@ -519,7 +519,7 @@ class MessagesNotificationAdapter(AbstractNotificationAdapter):
markup = self._format_message(qt_notification)
new_id = replaces_id if replaces_id is not None else next(self._id_gen)
- message.info(markup, replace=f'notifications-{new_id}')
+ message.info(markup, replace=f'notifications-{new_id}', rich=True)
# Faking closing, timing might not be 100% accurate
QTimer.singleShot(
diff --git a/qutebrowser/mainwindow/messageview.py b/qutebrowser/mainwindow/messageview.py
index 482d9f5e7..752cc9db7 100644
--- a/qutebrowser/mainwindow/messageview.py
+++ b/qutebrowser/mainwindow/messageview.py
@@ -37,6 +37,7 @@ class Message(QLabel):
level: usertypes.MessageLevel,
text: str,
replace: Optional[str],
+ text_format: Qt.TextFormat,
parent: QWidget = None,
) -> None:
super().__init__(text, parent)
@@ -44,6 +45,7 @@ class Message(QLabel):
self.level = level
self.setAttribute(Qt.WA_StyledBackground, True)
self.setWordWrap(True)
+ self.setTextFormat(text_format)
qss = """
padding-top: 2px;
padding-bottom: 2px;
@@ -74,15 +76,31 @@ class Message(QLabel):
raise ValueError("Invalid level {!r}".format(level))
stylesheet.set_register(self, qss, update=False)
+ @staticmethod
+ def _text_format(info: message.MessageInfo) -> Qt.TextFormat:
+ """The Qt.TextFormat to use based on the given MessageInfo."""
+ return Qt.TextFormat.RichText if info.rich else Qt.TextFormat.PlainText
+
@classmethod
def from_info(cls, info: message.MessageInfo, parent: QWidget = None) -> "Message":
return cls(
level=info.level,
text=info.text,
replace=info.replace,
+ text_format=cls._text_format(info),
parent=parent,
)
+ def update_from_info(self, info: message.MessageInfo) -> None:
+ """Update the text from the given info.
+
+ Both the message this gets called on and the given MessageInfo need to have
+ the same level.
+ """
+ assert self.level == info.level, (self, info)
+ self.setTextFormat(self._text_format(info))
+ self.setText(info.text)
+
class MessageView(QWidget):
@@ -138,8 +156,7 @@ class MessageView(QWidget):
existing = [msg for msg in self._messages if msg.replace == info.replace]
if existing:
assert len(existing) == 1, existing
- assert existing[0].level == info.level, (existing, info)
- existing[0].setText(info.text)
+ existing[0].update_from_info(info)
self.update_geometry.emit()
return
diff --git a/qutebrowser/utils/message.py b/qutebrowser/utils/message.py
index 48dcc9945..682382dc8 100644
--- a/qutebrowser/utils/message.py
+++ b/qutebrowser/utils/message.py
@@ -38,6 +38,7 @@ class MessageInfo:
level: usertypes.MessageLevel
text: str
replace: Optional[str] = None
+ rich: bool = False
def _log_stack(typ: str, stack: str) -> None:
@@ -52,13 +53,19 @@ def _log_stack(typ: str, stack: str) -> None:
log.message.debug("Stack for {} message:\n{}".format(typ, stack_text))
-def error(message: str, *, stack: str = None, replace: str = None) -> None:
+def error(
+ message: str, *,
+ stack: str = None,
+ replace: str = None,
+ rich: bool = False,
+) -> None:
"""Display an error message.
Args:
message: The message to show.
stack: The stack trace to show (if any).
replace: Replace existing messages which are still being shown.
+ rich: Show message as rich text.
"""
if stack is None:
stack = ''.join(traceback.format_stack())
@@ -71,15 +78,17 @@ def error(message: str, *, stack: str = None, replace: str = None) -> None:
level=usertypes.MessageLevel.error,
text=message,
replace=replace,
+ rich=rich,
)
-def warning(message: str, *, replace: str = None) -> None:
+def warning(message: str, *, replace: str = None, rich: bool = False) -> None:
"""Display a warning message.
Args:
message: The message to show.
replace: Replace existing messages which are still being shown.
+ rich: Show message as rich text.
"""
_log_stack('warning', ''.join(traceback.format_stack()))
log.message.warning(message)
@@ -87,21 +96,24 @@ def warning(message: str, *, replace: str = None) -> None:
level=usertypes.MessageLevel.warning,
text=message,
replace=replace,
+ rich=rich,
)
-def info(message: str, *, replace: str = None) -> None:
+def info(message: str, *, replace: str = None, rich: bool = False) -> None:
"""Display an info message.
Args:
message: The message to show.
replace: Replace existing messages which are still being shown.
+ rich: Show message as rich text.
"""
log.message.info(message)
global_bridge.show(
level=usertypes.MessageLevel.info,
text=message,
replace=replace,
+ rich=rich,
)
@@ -263,9 +275,10 @@ class GlobalMessageBridge(QObject):
level: usertypes.MessageLevel,
text: str,
replace: str = None,
+ rich: bool = False,
) -> None:
"""Show the given message."""
- info = MessageInfo(level=level, text=text, replace=replace)
+ info = MessageInfo(level=level, text=text, replace=replace, rich=rich)
if self._connected:
self.show_message.emit(info)
else:
diff --git a/tests/unit/mainwindow/test_messageview.py b/tests/unit/mainwindow/test_messageview.py
index 0f9dc9ea9..32bd638c7 100644
--- a/tests/unit/mainwindow/test_messageview.py
+++ b/tests/unit/mainwindow/test_messageview.py
@@ -17,6 +17,8 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
+import contextlib
+
import pytest
from PyQt5.QtCore import Qt
@@ -63,6 +65,7 @@ def test_word_wrap(view, qtbot):
"""A long message should be wrapped."""
with qtbot.wait_signal(view._clear_timer.timeout):
view.show_message(message.MessageInfo(usertypes.MessageLevel.info, 'short'))
+ assert len(view._messages) == 1
height1 = view.sizeHint().height()
assert height1 > 0
@@ -73,12 +76,52 @@ def test_word_wrap(view, qtbot):
"island deep in the sea.")
view.show_message(message.MessageInfo(usertypes.MessageLevel.info, text))
+ assert len(view._messages) == 1
height2 = view.sizeHint().height()
assert height2 > height1
assert view._messages[0].wordWrap()
+@pytest.mark.parametrize("rich, higher, expected_format", [
+ (True, True, Qt.TextFormat.RichText),
+ (False, False, Qt.TextFormat.PlainText),
+ (None, False, Qt.TextFormat.PlainText),
+])
+@pytest.mark.parametrize("replace", ["test", None])
+def test_rich_text(view, qtbot, rich, higher, expected_format, replace):
+ """Rich text should be rendered appropriately."""
+ level = usertypes.MessageLevel.info
+ text = 'with <h1>markup</h1>'
+ text2 = 'with <h1>markup</h1> 2'
+
+ info1 = message.MessageInfo(level, text, replace=replace)
+ info2 = message.MessageInfo(level, text2, replace=replace, rich=rich)
+
+ ctx = (
+ qtbot.wait_signal(view._clear_timer.timeout) if replace is None
+ else contextlib.nullcontext()
+ )
+ with ctx:
+ view.show_message(info1)
+ assert len(view._messages) == 1
+
+ height1 = view.sizeHint().height()
+ assert height1 > 0
+
+ assert view._messages[0].textFormat() == Qt.TextFormat.PlainText # default
+
+ view.show_message(info2)
+ height2 = view.sizeHint().height()
+ assert len(view._messages) == 1
+
+ assert view._messages[0].textFormat() == expected_format
+ if higher:
+ assert height2 > height1
+ else:
+ assert height2 == height1
+
+
def test_show_message_twice(view):
"""Show the same message twice -> only one should be shown."""
view.show_message(message.MessageInfo(usertypes.MessageLevel.info, 'test'))