Skip to content

Commit 8f0ed3d

Browse files
authored
fix GammaInfoWidget to use qt font awesome (#425)
1 parent f26eced commit 8f0ed3d

8 files changed

Lines changed: 66 additions & 33 deletions

File tree

build_utils/minimal-req.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
PartSegCore_compiled_backend==0.13.11
33
PartSegData==0.10.0
44
PyOpenGL-accelerate==3.1.5
5+
QtAwesome==1.0.3
56
QtPy==1.7.0
67
SimpleITK==1.1.0
78
appdirs==1.4.4

package/PartSeg/_roi_analysis/image_view.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from typing import Optional
22

3-
import qtawesome as qta
43
from qtpy.QtCore import QObject, QSignalBlocker, Slot
54
from qtpy.QtGui import QResizeEvent
6-
from qtpy.QtWidgets import QCheckBox, QComboBox, QDoubleSpinBox, QLabel, QPushButton
5+
from qtpy.QtWidgets import QCheckBox, QComboBox, QDoubleSpinBox, QLabel
76

87
from PartSegCore.roi_info import ROIInfo
98
from PartSegImage import Image
@@ -36,10 +35,8 @@ def __init__(self, settings: PartSettings, channel_property: ChannelProperty, na
3635
self.label2 = QLabel("Opacity:")
3736
self.roi_alternative_select = QComboBox()
3837
self.roi_alternative_select.currentTextChanged.connect(self.image_state.set_roi_presented)
39-
self.search_btn = QPushButton(qta.icon("fa5s.search"), "")
4038
self.stretch = None
4139

42-
self.btn_layout.insertWidget(self.channel_control_index, self.search_btn)
4340
self.btn_layout.insertWidget(self.channel_control_index + 1, self.label1)
4441
self.btn_layout.insertWidget(self.channel_control_index + 2, self.only_border)
4542
self.btn_layout.insertWidget(self.channel_control_index + 3, self.label2)
@@ -88,7 +85,7 @@ def update_alternatives(self):
8885
def resizeEvent(self, event: QResizeEvent):
8986
if event.size().width() > 700 and not self._channel_control_top:
9087
w = self.btn_layout2.takeAt(0).widget()
91-
channel_control_index = self.btn_layout.indexOf(self.search_btn) + 1
88+
channel_control_index = self.btn_layout.indexOf(self.search_roi_btn) + 1
9289
self.btn_layout.takeAt(channel_control_index)
9390
# noinspection PyArgumentList
9491
self.btn_layout.insertWidget(channel_control_index, w)

package/PartSeg/common_backend/base_settings.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
22
import os
33
import os.path
4+
import re
45
import sys
56
import warnings
7+
from argparse import Namespace
68
from datetime import datetime
79
from pathlib import Path
810
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, Optional, Tuple, Union
@@ -33,10 +35,12 @@
3335

3436
else: # pragma: no cover
3537

36-
def get_theme(name: str) -> dict:
38+
def get_theme(name: str, as_dict=True) -> Union[dict, Namespace]:
3739
theme = napari.utils.theme.palettes[name]
3840
theme["canvas"] = "black"
39-
return theme
41+
if as_dict:
42+
return theme
43+
return Namespace(**{k: Color(v) if isinstance(v, str) and v.startswith("rgb") else v for k, v in theme.items()})
4044

4145

4246
try:
@@ -280,6 +284,16 @@ def __init__(self):
280284
def theme_name(self) -> str:
281285
return self.get_from_profile("theme", "light")
282286

287+
@property
288+
def theme(self):
289+
try:
290+
return get_theme(self.theme_name, as_dict=False)
291+
except TypeError:
292+
theme = get_theme(self.theme_name)
293+
return Namespace(
294+
**{k: Color(v) if isinstance(v, str) and v.startswith("rgb") else v for k, v in theme.items()}
295+
)
296+
283297
@property
284298
def style_sheet(self):
285299
with warnings.catch_warnings():
@@ -727,3 +741,12 @@ class TimeAndStackException(Exception):
727741
Exception which inform that current image has both time
728742
and stack dat which is not supported
729743
"""
744+
745+
746+
class Color: # pragma: no cover
747+
def __init__(self, text):
748+
color_re = re.compile(r"rgb\((\d+), (\d+), (\d+)\)")
749+
self.colors = tuple(map(int, color_re.match(text).groups()))
750+
751+
def as_rgb_tuple(self):
752+
return self.colors

package/PartSeg/common_gui/channel_control.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
import qtawesome as qta
55
from napari.utils import Colormap
6-
from qtpy.QtCore import QEvent, QMargins, QModelIndex, QPoint, QRect, QRectF, QSize, Qt, Signal
7-
from qtpy.QtGui import QColor, QIcon, QMouseEvent, QPainter, QPainterPath, QPaintEvent, QPen, QPolygonF, QShowEvent
6+
from qtpy.QtCore import QEvent, QMargins, QModelIndex, QPoint, QRect, QSize, Qt, Signal
7+
from qtpy.QtGui import QColor, QIcon, QMouseEvent, QPainter, QPaintEvent, QPen, QPolygonF, QShowEvent
88
from qtpy.QtWidgets import (
99
QCheckBox,
1010
QComboBox,
@@ -601,6 +601,7 @@ def __init__(self, size=25, margin=1):
601601
self.margin = QMargins(margin, margin, margin, margin)
602602
self.setFixedWidth(size)
603603
self.setFixedHeight(size)
604+
self.setToolTip("Fixed range")
604605

605606
def paintEvent(self, a0: QPaintEvent) -> None:
606607
super().paintEvent(a0)
@@ -624,6 +625,7 @@ def __init__(self, size=25, margin=1):
624625
self.margin = QMargins(margin, margin, margin, margin)
625626
self.setFixedWidth(size)
626627
self.setFixedHeight(size)
628+
self.setToolTip("Filtered")
627629

628630
def paintEvent(self, a0: QPaintEvent) -> None:
629631
super().paintEvent(a0)
@@ -640,29 +642,18 @@ def paintEvent(self, a0: QPaintEvent) -> None:
640642
class GammaInfoWidget(QWidget):
641643
def __init__(self, size=25, margin=2):
642644
super().__init__()
643-
self.margin = margin
645+
self.margin = QMargins(margin, margin, margin, margin)
644646
self.setFixedWidth(size)
645647
self.setFixedHeight(size)
648+
self.setToolTip("Gamma translated")
646649

647650
def paintEvent(self, a0: QPaintEvent) -> None:
648-
649651
super().paintEvent(a0)
650652
painter = QPainter(self)
651653
painter.save()
652-
painter.setRenderHint(QPainter.Antialiasing)
653-
rect = QRectF(self.margin, self.margin, self.width() - self.margin * 2, self.height() - 2 * self.margin)
654-
painter.setBrush(Qt.white)
655-
painter.setPen(Qt.white)
656-
painter.drawRect(rect)
657-
painter.restore()
658-
painter.save()
659-
painter.setRenderHint(QPainter.Antialiasing)
660-
pen = QPen()
661-
pen.setWidth(3)
662-
painter.setPen(pen)
663-
path = QPainterPath()
664-
height, width = rect.height() + self.margin, rect.width() + self.margin
665-
path.moveTo(self.margin, height)
666-
path.cubicTo(height * 0.5, width * 0.9, height * 0.9, width * 0.5, height, self.margin)
667-
painter.drawPath(path)
654+
painter.setPen(QColor("white"))
655+
painter.setBrush(QColor("white"))
656+
painter.drawRect(self.rect() - self.margin)
657+
icon: QIcon = qta.icon("mdi.chart-bell-curve-cumulative")
658+
icon.paint(painter, self.rect())
668659
painter.restore()

package/PartSeg/common_gui/collapse_checkbox.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ def hide_element(self, a0: int):
4848

4949
def paintEvent(self, event: QtGui.QPaintEvent):
5050
painter = QPainter(self)
51+
color = painter.pen().color()
5152
painter.save()
5253
rect = self.rect()
5354
top = int(rect.height() - (self.text_size.height() / 2))
5455
painter.drawText(rect.height() + 5, top, self.info_text)
5556
if self.isChecked():
56-
icon = qta.icon("fa5s.caret-right")
57+
icon = qta.icon("fa5s.caret-right", color=color)
5758
else:
58-
icon = qta.icon("fa5s.caret-down")
59+
icon = qta.icon("fa5s.caret-down", color=color)
5960
icon.paint(painter, QRect(0, -self.height() / 4, self.height(), self.height()))
6061
painter.restore()
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import qtawesome as qta
2-
from qtpy.QtGui import QIcon, QPainter, QPaintEvent
2+
from qtpy.QtGui import QPainter, QPaintEvent
33
from qtpy.QtWidgets import QCheckBox
44

55

66
class LockCheckBox(QCheckBox):
77
def paintEvent(self, event: QPaintEvent):
88
rect = event.rect()
99
painter = QPainter(self)
10-
lock: QIcon = qta.icon("fa5s.lock") if self.isChecked() else qta.icon("fa5s.lock-open")
10+
color = painter.pen().color()
11+
lock = qta.icon("fa5s.lock", color=color) if self.isChecked() else qta.icon("fa5s.lock-open", color=color)
1112
lock.paint(painter, rect)

package/PartSeg/common_gui/napari_image_view.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,16 @@
1414
except ImportError:
1515
from napari._qt.widgets.qt_viewer_buttons import QtViewerPushButton
1616

17+
import qtawesome as qta
1718
from napari.components import ViewerModel as Viewer
1819
from napari.layers import Layer, Points
1920
from napari.layers.image import Image as NapariImage
2021
from napari.layers.labels import Labels
2122
from napari.qt import QtStateButton, QtViewer
2223
from napari.qt.threading import thread_worker
2324
from qtpy.QtCore import QEvent, QObject, QPoint, Qt, Signal
24-
from qtpy.QtWidgets import QCheckBox, QHBoxLayout, QLabel, QMenu, QToolTip, QVBoxLayout, QWidget
25+
from qtpy.QtGui import QColor
26+
from qtpy.QtWidgets import QCheckBox, QHBoxLayout, QLabel, QMenu, QPushButton, QToolTip, QVBoxLayout, QWidget
2527
from vispy.color import Color, Colormap
2628
from vispy.scene import BaseCamera
2729

@@ -190,6 +192,8 @@ def __init__(
190192
self.points_view_button = QtViewerPushButton(
191193
self.viewer, "new_points", "Show points", self.toggle_points_visibility
192194
)
195+
self.search_roi_btn = SearchROIButton(self)
196+
self.search_roi_btn.setHidden(True)
193197
self.roll_dim_button = QtViewerPushButton(self.viewer, "roll", "Roll dimension", self._rotate_dim)
194198
self.roll_dim_button.setContextMenuPolicy(Qt.CustomContextMenu)
195199
self.roll_dim_button.customContextMenuRequested.connect(self._dim_order_menu)
@@ -201,6 +205,7 @@ def __init__(
201205
self.btn_layout.addWidget(self.ndim_btn)
202206
self.btn_layout.addWidget(self.roll_dim_button)
203207
self.btn_layout.addWidget(self.points_view_button)
208+
self.btn_layout.addWidget(self.search_roi_btn)
204209
self.btn_layout.addWidget(self.channel_control, 1)
205210
self.btn_layout.addWidget(self.mask_label)
206211
self.btn_layout.addWidget(self.mask_chk)
@@ -750,7 +755,8 @@ def close(self):
750755
self.dockConsole.deleteLater()
751756
self.dockLayerList.deleteLater()
752757
self.dockLayerControls.deleteLater()
753-
self.activityDock.deleteLater()
758+
if hasattr(self, "activityDock"):
759+
self.activityDock.deleteLater()
754760
return super().close()
755761

756762
def closeEvent(self, event):
@@ -768,6 +774,18 @@ class ImageParameters:
768774
layers: int = 0
769775

770776

777+
class SearchROIButton(QPushButton):
778+
def __init__(self, image_view: ImageView):
779+
super().__init__(qta.icon("fa5s.search"), "")
780+
self.image_view = image_view
781+
image_view.settings.theme_changed.connect(self._theme_changed)
782+
self._theme_changed()
783+
784+
def _theme_changed(self):
785+
color = self.image_view.settings.theme.text
786+
self.setIcon(qta.icon("fa5s.search", color=QColor(*color.as_rgb_tuple())))
787+
788+
771789
def _prepare_layers(image: Image, param: ImageParameters, replace: bool) -> Tuple[ImageInfo, bool]:
772790
image_layers = []
773791
for i in range(image.channels):

requirements/requirements_pyinstaller.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ PartSegCore-compiled-backend
1818
PyInstaller!=4.4
1919
PyOpenGL-accelerate
2020
PyQt5
21+
QtAwesome
2122
QtPy
2223
requests
2324
scipy

0 commit comments

Comments
 (0)