Source code for stytra.gui.status_display

from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout
from PyQt5.QtGui import QPalette
from collections import OrderedDict
from datetime import datetime
from queue import Empty
import numpy as np


def _hex_to_rgb(hex):
    hex = hex.lstrip("#")
    return np.array(tuple(int(hex[i * 2 : i * 2 + 2], 16) for i in range(3)))


color_dict = dict(I=(25, 35, 44), P=(25, 35, 44), E=(143, 0, 1), W=(19, 76, 80))


[docs]class DisplayedMessage(QLabel): """A label for status messages which can optionally fade out""" def __init__(self, message, persist=0, end_color=(0, 0, 0)): super().__init__(message[2:]) self.type = message[0] self.started = datetime.now() if self.type == "P": self.persist = -1 else: self.persist = persist self.start_color = np.array(color_dict.get(self.type, (143, 0, 1))) self.text_start_color = np.array((255,) * 3) self.end_color = np.array(end_color)
[docs] def is_expired(self, t): if (t - self.started).total_seconds() > self.persist > 0: return True return False
[docs] def refresh(self): self.started = datetime.now()
[docs] def update_t(self, t): if self.persist <= 0: return passed = (t - self.started).total_seconds() / self.persist color_bg = (self.end_color * passed + (1 - passed) * self.start_color).astype( np.uint8 ) color_txt = ( self.end_color * passed + (1 - passed) * self.text_start_color ).astype(np.uint8) self.setStyleSheet( "background-color: rgb({},{},{});" " color: rgb({},{},{});".format(*color_bg, *color_txt) )
[docs]class StatusMessageDisplay(QWidget): def __init__(self): super().__init__() self.setLayout(QHBoxLayout()) self.queues = [] self.current_messages = OrderedDict() self.new_messages = []
[docs] def addMessageQueue(self, queue): self.queues.append(queue)
[docs] def addMessage(self, message, persist=3): end_color = _hex_to_rgb(self.palette().color(QPalette.Background).name()) if not message or len(message) < 2: return if message in self.current_messages.keys(): self.current_messages[message].refresh() else: self.current_messages[message] = DisplayedMessage( message, persist=persist, end_color=end_color ) self.new_messages.append(self.current_messages[message])
[docs] def refresh(self): for queue in self.queues: while True: try: msg = queue.get(timeout=0.001) self.addMessage(msg) except Empty: break t = datetime.now() while len(self.new_messages) > 0: msg = self.new_messages.pop() self.layout().addWidget(msg) all_keys = list(self.current_messages.keys()) for key in all_keys: if self.current_messages[key].is_expired(t): wid = self.current_messages.pop(key) self.layout().removeWidget(wid) wid.deleteLater() else: self.current_messages[key].update_t(t)