Skip to content

Commit 535dd57

Browse files
committed
messagewidget: Implement and use IconWidget
Better styling w.r.t enabled/active state.
1 parent bdc9085 commit 535dd57

File tree

2 files changed

+84
-14
lines changed

2 files changed

+84
-14
lines changed

Orange/widgets/utils/messagewidget.py

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
)
1717
from AnyQt.QtWidgets import (
1818
QWidget, QLabel, QSizePolicy, QStyle, QHBoxLayout, QMessageBox,
19-
QMenu, QWidgetAction, QStyleOption, QApplication
19+
QMenu, QWidgetAction, QStyleOption, QStylePainter, QApplication
2020
)
2121
from AnyQt.QtCore import pyqtSignal as Signal
2222

@@ -308,8 +308,8 @@ def __init__(self, parent=None, openExternalLinks=False, **kwargs):
308308
#: short
309309
self.__popuptext = ""
310310
#: Leading icon
311-
self.__iconlabel = QLabel(
312-
sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed),
311+
self.__iconwidget = IconWidget(
312+
sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
313313
)
314314
#: Inline message text
315315
self.__textlabel = QLabel(
@@ -330,7 +330,7 @@ def __init__(self, parent=None, openExternalLinks=False, **kwargs):
330330
self.setLayout(QHBoxLayout())
331331
self.layout().setContentsMargins(2, 1, 2, 1)
332332
self.layout().setSpacing(0)
333-
self.layout().addWidget(self.__iconlabel)
333+
self.layout().addWidget(self.__iconwidget)
334334
self.layout().addSpacing(4)
335335
self.layout().addWidget(self.__textlabel)
336336
self.layout().addWidget(self.__popupicon)
@@ -423,16 +423,10 @@ def __update(self):
423423
Update the current display state.
424424
"""
425425
self.ensurePolished()
426-
style = self.style()
427426
summary = self.summarize()
428427
icon = message_icon(summary)
429-
if not summary.isEmpty() and not icon.isNull():
430-
size = style.pixelMetric(QStyle.PM_SmallIconSize)
431-
pm = icon.pixmap(size, size)
432-
else:
433-
pm = QPixmap()
434-
self.__iconlabel.setPixmap(pm)
435-
self.__iconlabel.setVisible(not pm.isNull())
428+
self.__iconwidget.setIcon(icon)
429+
self.__iconwidget.setVisible(not icon.isNull())
436430
self.__textlabel.setTextFormat(summary.textFormat)
437431
self.__textlabel.setText(summary.text)
438432
messages = [m for m in self.__messages.values() if not m.isEmpty()]
@@ -453,6 +447,7 @@ def is_short(m):
453447
else:
454448
self.__popuptext = fulltext
455449
self.__popupicon.setVisible(bool(self.__popuptext))
450+
self.layout().activate()
456451

457452
def mousePressEvent(self, event):
458453
if event.button() == Qt.LeftButton:
@@ -521,6 +516,65 @@ def paintEvent(self, event):
521516
p.drawRect(opt.rect.adjusted(0, 0, -1, -1))
522517

523518

519+
class IconWidget(QWidget):
520+
"""
521+
A widget displaying an `QIcon`
522+
"""
523+
def __init__(self, parent=None, icon=QIcon(), iconSize=QSize(), **kwargs):
524+
sizePolicy = kwargs.pop("sizePolicy", QSizePolicy(QSizePolicy.Fixed,
525+
QSizePolicy.Fixed))
526+
super().__init__(parent, **kwargs)
527+
self.__icon = QIcon(icon)
528+
self.__iconSize = QSize(iconSize)
529+
self.setSizePolicy(sizePolicy)
530+
531+
def setIcon(self, icon):
532+
# type: (QIcon) -> None
533+
if self.__icon != icon:
534+
self.__icon = QIcon(icon)
535+
self.updateGeometry()
536+
self.update()
537+
538+
def icon(self):
539+
# type: () -> QIcon
540+
return QIcon(self.__icon)
541+
542+
def iconSize(self):
543+
# type: () -> QSize
544+
if not self.__iconSize.isValid():
545+
size = self.style().pixelMetric(QStyle.PM_ButtonIconSize)
546+
return QSize(size, size)
547+
else:
548+
return QSize(self.__iconSize)
549+
550+
def setIconSize(self, iconSize):
551+
# type: (QSize) -> None
552+
if self.__iconSize != iconSize:
553+
self.__iconSize = QSize(iconSize)
554+
self.updateGeometry()
555+
self.update()
556+
557+
def sizeHint(self):
558+
sh = self.iconSize()
559+
m = self.contentsMargins()
560+
return QSize(sh.width() + m.left() + m.right(),
561+
sh.height() + m.top() + m.bottom())
562+
563+
def paintEvent(self, event):
564+
painter = QStylePainter(self)
565+
opt = QStyleOption()
566+
opt.initFrom(self)
567+
painter.drawPrimitive(QStyle.PE_Widget, opt)
568+
if not self.__icon.isNull():
569+
rect = self.contentsRect()
570+
if opt.state & QStyle.State_Active:
571+
mode = QIcon.Active
572+
else:
573+
mode = QIcon.Disabled
574+
self.__icon.paint(painter, rect, Qt.AlignCenter, mode, QIcon.Off)
575+
painter.end()
576+
577+
524578
def main(argv=None): # pragma: no cover
525579
from AnyQt.QtWidgets import QVBoxLayout, QCheckBox, QStatusBar
526580
app = QApplication(list(argv) if argv else [])

Orange/widgets/utils/tests/test_messagewidget.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
from AnyQt.QtCore import Qt
1+
from AnyQt.QtCore import Qt, QSize
22

33
from Orange.widgets.tests.base import GuiTest
4-
from Orange.widgets.utils.messagewidget import MessagesWidget, Message
4+
from Orange.widgets.utils.messagewidget import (
5+
MessagesWidget, Message, IconWidget
6+
)
57

68

79
class TestMessageWidget(GuiTest):
@@ -36,3 +38,17 @@ def test_widget(self):
3638
assert w.openExternalLinks()
3739
self.assertEqual(len(w.messages()), 0)
3840
self.assertTrue(w.summarize().isEmpty())
41+
42+
43+
class TestIconWidget(GuiTest):
44+
def test_widget(self):
45+
w = IconWidget()
46+
s = w.style()
47+
icon = s.standardIcon(s.SP_BrowserStop)
48+
w.setIcon(icon)
49+
self.assertEqual(w.icon().cacheKey(), icon.cacheKey())
50+
w.setIconSize(QSize(42, 42))
51+
self.assertEqual(w.iconSize(), QSize(42, 42))
52+
self.assertGreaterEqual(w.sizeHint().width(), 42)
53+
self.assertGreaterEqual(w.sizeHint().height(), 42)
54+
w.setIconSize(QSize())

0 commit comments

Comments
 (0)