Skip to content

Commit

Permalink
Work around problems with Qt stylesheet handling in widget hierarchy
Browse files Browse the repository at this point in the history
Simply setting the stylesheet on ReplyWidget has stopped working;
styles are not being applied to children. My working theory is that it
might be due to changes in the Debian package qtbase-opensource-src at
5.11.3+dfsg1-1+deb10u2, which incorporated upstream changes that
changed how stylesheets are applied to children. That theory is a bit
shaky, though, because with the same system packages installed,
installing the same version of PyQt5 in a virtualenv results in the
old approach working fine. That's unfortunately not an option for us
at this time, as it would be a huge addition to the production
requirements, and potentially painful to keep in sync with the system
Qt packages.

At any rate, the workaround in this change, to explicitly apply the
CSS to the children, seems to solve the problem of reply widgets not
being updated correctly for their status.
  • Loading branch information
rmol authored and sssoleileraaa committed Mar 3, 2020
1 parent 3593869 commit 53b123f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 24 deletions.
44 changes: 22 additions & 22 deletions securedrop_client/gui/widgets.py
Expand Up @@ -1657,8 +1657,7 @@ class ReplyWidget(SpeechBubble):
Represents a reply to a source.
"""

CSS_REPLY_FAILED = '''
#message {
CSS_MESSAGE_REPLY_FAILED = '''
min-width: 540px;
max-width: 540px;
font-family: 'Source Sans Pro';
Expand All @@ -1667,23 +1666,23 @@ class ReplyWidget(SpeechBubble):
background-color: #fff;
color: #3b3b3b;
padding: 16px;
}
#color_bar {
'''

CSS_COLOR_BAR_REPLY_FAILED = '''
min-height: 5px;
max-height: 5px;
background-color: #ff3366;
border: 0px;
}
#error_message {
'''

CSS_ERROR_MESSAGE_REPLY_FAILED = '''
font-family: 'Source Sans Pro';
font-weight: 500;
font-size: 13px;
color: #ff3366;
}
'''

CSS_REPLY_SUCCEEDED = '''
#message {
CSS_MESSAGE_REPLY_SUCCEEDED = '''
min-width: 540px;
max-width: 540px;
font-family: 'Source Sans Pro';
Expand All @@ -1692,19 +1691,16 @@ class ReplyWidget(SpeechBubble):
background-color: #fff;
color: #3b3b3b;
padding: 16px;
}
#color_bar {
'''

CSS_COLOR_BAR_REPLY_SUCCEEDED = '''
min-height: 5px;
max-height: 5px;
background-color: #0065db;
border: 0px;
}
'''

# Custom pending CSS styling simulates the effect of opacity which is only
# supported by tooltips for QSS.
CSS_REPLY_PENDING = '''
#message {
CSS_MESSAGE_REPLY_PENDING = '''
min-width: 540px;
max-width: 540px;
font-family: 'Source Sans Pro';
Expand All @@ -1713,13 +1709,13 @@ class ReplyWidget(SpeechBubble):
color: #A9AAAD;
background-color: #F7F8FC;
padding: 16px;
}
#color_bar {
'''

CSS_COLOR_BAR_REPLY_PENDING = '''
min-height: 5px;
max-height: 5px;
background-color: #0065db;
border: 0px;
}
'''

def __init__(
Expand All @@ -1740,6 +1736,7 @@ def __init__(
error_icon.setFixedWidth(12)
error_message = SecureQLabel('Failed to send')
error_message.setObjectName('error_message')
error_message.setStyleSheet(self.CSS_ERROR_MESSAGE_REPLY_FAILED)

self.error = QWidget()
error_layout = QHBoxLayout()
Expand All @@ -1760,13 +1757,16 @@ def __init__(

def _set_reply_state(self, status: str) -> None:
if status == 'SUCCEEDED':
self.setStyleSheet(self.CSS_REPLY_SUCCEEDED)
self.message.setStyleSheet(self.CSS_MESSAGE_REPLY_SUCCEEDED)
self.color_bar.setStyleSheet(self.CSS_COLOR_BAR_REPLY_SUCCEEDED)
self.error.hide()
elif status == 'FAILED':
self.setStyleSheet(self.CSS_REPLY_FAILED)
self.message.setStyleSheet(self.CSS_MESSAGE_REPLY_FAILED)
self.color_bar.setStyleSheet(self.CSS_COLOR_BAR_REPLY_FAILED)
self.error.show()
elif status == 'PENDING':
self.setStyleSheet(self.CSS_REPLY_PENDING)
self.message.setStyleSheet(self.CSS_MESSAGE_REPLY_PENDING)
self.color_bar.setStyleSheet(self.CSS_COLOR_BAR_REPLY_PENDING)

@pyqtSlot(str, str, str)
def _on_reply_success(self, source_id: str, message_id: str, content: str) -> None:
Expand Down
4 changes: 2 additions & 2 deletions tests/gui/test_widgets.py
Expand Up @@ -1465,14 +1465,14 @@ class Thing(QObject):
)

assert rw.message.text() == original_text
assert rw.styleSheet() == rw.CSS_REPLY_FAILED
assert rw.message.styleSheet() == rw.CSS_MESSAGE_REPLY_FAILED
assert not rw.error.isHidden()

new_text = 'updated text'
thing.reply_ready.emit(source_id, reply_id, new_text)

assert rw.message.text() == new_text
assert rw.styleSheet() == rw.CSS_REPLY_SUCCEEDED
assert rw.message.styleSheet() == rw.CSS_MESSAGE_REPLY_SUCCEEDED
assert rw.error.isHidden()


Expand Down

0 comments on commit 53b123f

Please sign in to comment.