2021-07-23 16:01:09 +00:00
|
|
|
# piker: trading gear for hackers
|
|
|
|
# Copyright (C) Tyler Goodlet (in stewardship for pikers)
|
|
|
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
'''
|
2021-07-25 03:15:44 +00:00
|
|
|
Text entry "forms" widgets (mostly for configuration and UI user input).
|
2021-07-23 16:01:09 +00:00
|
|
|
|
|
|
|
'''
|
2021-07-30 14:50:05 +00:00
|
|
|
from contextlib import asynccontextmanager
|
2021-07-25 19:43:41 +00:00
|
|
|
from functools import partial
|
2021-07-30 14:50:05 +00:00
|
|
|
from textwrap import dedent
|
|
|
|
import math
|
2021-07-24 20:04:58 +00:00
|
|
|
from typing import Optional
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
import trio
|
2021-07-23 16:01:09 +00:00
|
|
|
from PyQt5 import QtCore, QtGui
|
2021-07-25 19:43:41 +00:00
|
|
|
from PyQt5.QtCore import QSize, QModelIndex, Qt, QEvent
|
2021-07-25 03:15:44 +00:00
|
|
|
from PyQt5.QtWidgets import (
|
|
|
|
QWidget,
|
2021-07-25 19:43:41 +00:00
|
|
|
QLabel,
|
2021-07-25 03:15:44 +00:00
|
|
|
QComboBox,
|
|
|
|
QLineEdit,
|
|
|
|
QProgressBar,
|
|
|
|
QSizePolicy,
|
2021-07-25 16:14:03 +00:00
|
|
|
QStyledItemDelegate,
|
|
|
|
QStyleOptionViewItem,
|
2021-07-25 03:15:44 +00:00
|
|
|
)
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
from ._event import open_handlers
|
2021-07-26 15:32:54 +00:00
|
|
|
from ._style import hcolor, _font, _font_small, DpiAwareFont
|
2021-07-24 20:04:58 +00:00
|
|
|
|
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
class FontAndChartAwareLineEdit(QLineEdit):
|
2021-07-24 20:04:58 +00:00
|
|
|
|
|
|
|
def __init__(
|
|
|
|
|
|
|
|
self,
|
|
|
|
parent: QWidget,
|
|
|
|
# parent_chart: QWidget, # noqa
|
|
|
|
font: DpiAwareFont = _font,
|
|
|
|
width_in_chars: int = None,
|
|
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
|
|
# self.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
|
|
# self.customContextMenuRequested.connect(self.show_menu)
|
|
|
|
# self.setStyleSheet(f"font: 18px")
|
|
|
|
|
|
|
|
self.dpi_font = font
|
|
|
|
# self.godwidget = parent_chart
|
|
|
|
|
|
|
|
if width_in_chars:
|
|
|
|
self._chars = int(width_in_chars)
|
|
|
|
|
|
|
|
else:
|
|
|
|
# chart count which will be used to calculate
|
|
|
|
# width of input field.
|
|
|
|
self._chars: int = 9
|
|
|
|
|
|
|
|
super().__init__(parent)
|
|
|
|
# size it as we specify
|
|
|
|
# https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
|
|
|
|
self.setSizePolicy(
|
2021-07-25 03:15:44 +00:00
|
|
|
QSizePolicy.Expanding,
|
|
|
|
QSizePolicy.Fixed,
|
2021-07-24 20:04:58 +00:00
|
|
|
)
|
|
|
|
self.setFont(font.font)
|
|
|
|
|
|
|
|
# witty bit of margin
|
|
|
|
self.setTextMargins(2, 2, 2, 2)
|
|
|
|
|
2021-07-25 16:14:03 +00:00
|
|
|
def sizeHint(self) -> QSize:
|
2021-07-24 20:04:58 +00:00
|
|
|
"""
|
|
|
|
Scale edit box to size of dpi aware font.
|
|
|
|
|
|
|
|
"""
|
|
|
|
psh = super().sizeHint()
|
|
|
|
|
|
|
|
dpi_font = self.dpi_font
|
|
|
|
psh.setHeight(dpi_font.px_size + 2)
|
|
|
|
|
|
|
|
# space for ``._chars: int``
|
|
|
|
char_w_pxs = dpi_font.boundingRect(self.text()).width()
|
|
|
|
chars_w = char_w_pxs + 6 # * dpi_font.scale() * self._chars
|
|
|
|
psh.setWidth(chars_w)
|
|
|
|
|
|
|
|
return psh
|
|
|
|
|
|
|
|
def set_width_in_chars(
|
|
|
|
self,
|
|
|
|
chars: int,
|
2021-07-23 16:01:09 +00:00
|
|
|
|
2021-07-24 20:04:58 +00:00
|
|
|
) -> None:
|
|
|
|
self._chars = chars
|
|
|
|
self.sizeHint()
|
|
|
|
self.update()
|
|
|
|
|
|
|
|
def focus(self) -> None:
|
|
|
|
self.selectAll()
|
|
|
|
self.show()
|
|
|
|
self.setFocus()
|
2021-07-23 16:01:09 +00:00
|
|
|
|
|
|
|
|
2021-07-25 16:14:03 +00:00
|
|
|
class FontScaledDelegate(QStyledItemDelegate):
|
2021-07-25 19:07:02 +00:00
|
|
|
'''
|
2021-07-25 16:14:03 +00:00
|
|
|
Super simple view delegate to render text in the same
|
|
|
|
font size as the search widget.
|
|
|
|
|
2021-07-25 19:07:02 +00:00
|
|
|
'''
|
2021-07-25 16:14:03 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
|
|
|
|
parent=None,
|
|
|
|
font: DpiAwareFont = _font,
|
|
|
|
|
|
|
|
) -> None:
|
|
|
|
|
|
|
|
super().__init__(parent)
|
|
|
|
self.dpi_font = font
|
|
|
|
|
|
|
|
def sizeHint(
|
|
|
|
self,
|
|
|
|
|
|
|
|
option: QStyleOptionViewItem,
|
|
|
|
index: QModelIndex,
|
|
|
|
|
|
|
|
) -> QSize:
|
|
|
|
|
|
|
|
# value = index.data()
|
|
|
|
# br = self.dpi_font.boundingRect(value)
|
|
|
|
# w, h = br.width(), br.height()
|
2021-07-25 19:07:02 +00:00
|
|
|
parent = self.parent()
|
|
|
|
|
|
|
|
if getattr(parent, '_max_item_size', None):
|
|
|
|
return QSize(*self.parent()._max_item_size)
|
|
|
|
|
|
|
|
else:
|
|
|
|
return super().sizeHint(option, index)
|
2021-07-25 16:14:03 +00:00
|
|
|
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
class FieldsForm(QWidget):
|
2021-07-23 16:01:09 +00:00
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-26 15:32:54 +00:00
|
|
|
godwidget: 'GodWidget', # type: ignore # noqa
|
2021-07-23 16:01:09 +00:00
|
|
|
parent=None,
|
|
|
|
|
|
|
|
) -> None:
|
2021-07-26 15:32:54 +00:00
|
|
|
|
|
|
|
super().__init__(parent or godwidget)
|
|
|
|
self.godwidget = godwidget
|
2021-07-23 16:01:09 +00:00
|
|
|
|
|
|
|
# size it as we specify
|
|
|
|
self.setSizePolicy(
|
2021-07-30 14:50:05 +00:00
|
|
|
QSizePolicy.Expanding,
|
|
|
|
QSizePolicy.Expanding,
|
2021-07-23 16:01:09 +00:00
|
|
|
)
|
2021-07-26 15:32:54 +00:00
|
|
|
# self.setMaximumHeight(30)
|
2021-07-30 14:50:05 +00:00
|
|
|
# self.setMaximumWidth(166)
|
2021-07-23 16:01:09 +00:00
|
|
|
|
2021-07-26 15:32:54 +00:00
|
|
|
self.vbox = QtGui.QVBoxLayout(self)
|
2021-07-26 19:38:15 +00:00
|
|
|
self.vbox.setAlignment(Qt.AlignTop)
|
2021-07-30 14:50:05 +00:00
|
|
|
self.vbox.setContentsMargins(0, 4, 4, 0)
|
|
|
|
self.vbox.setSpacing(0)
|
|
|
|
|
|
|
|
# split layout for the (<label>: |<widget>|) parameters entry
|
|
|
|
self.form = QtGui.QFormLayout(self)
|
|
|
|
self.form.setAlignment(Qt.AlignCenter | Qt.AlignLeft)
|
|
|
|
self.form.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.form.setSpacing(4)
|
|
|
|
self.form.setHorizontalSpacing(0)
|
2021-07-26 15:32:54 +00:00
|
|
|
# self.vbox.addStretch()
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
self.vbox.addLayout(self.form)
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
self.labels: dict[str, QLabel] = {}
|
|
|
|
self.fields: dict[str, QWidget] = {}
|
|
|
|
|
2021-07-26 19:38:15 +00:00
|
|
|
self._font_size = _font_small.px_size - 2
|
2021-07-30 14:50:05 +00:00
|
|
|
self.vbox.addSpacing(0.375 * self._font_size)
|
2021-07-26 15:32:54 +00:00
|
|
|
self._max_item_width: (float, float) = 0, 0
|
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
def add_field_label(
|
2021-07-24 20:04:58 +00:00
|
|
|
self,
|
|
|
|
name: str,
|
2021-07-26 15:32:54 +00:00
|
|
|
font_size: Optional[int] = None,
|
2021-07-26 19:38:15 +00:00
|
|
|
font_color: str = 'default_lightest',
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-27 10:11:47 +00:00
|
|
|
**vbox_kwargs,
|
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
) -> QtGui.QLabel:
|
2021-07-23 16:01:09 +00:00
|
|
|
|
|
|
|
# add label to left of search bar
|
2021-07-30 14:50:05 +00:00
|
|
|
self.label = label = QtGui.QLabel()
|
2021-07-26 15:32:54 +00:00
|
|
|
font_size = font_size or self._font_size - 3
|
2021-07-23 16:01:09 +00:00
|
|
|
label.setStyleSheet(
|
2021-07-26 15:32:54 +00:00
|
|
|
f"""QLabel {{
|
|
|
|
color : {hcolor(font_color)};
|
|
|
|
font-size : {font_size}px;
|
|
|
|
}}
|
|
|
|
"""
|
2021-07-23 16:01:09 +00:00
|
|
|
)
|
2021-07-30 14:50:05 +00:00
|
|
|
label.setFont(_font.font)
|
|
|
|
label.setTextFormat(Qt.MarkdownText) # markdown
|
|
|
|
label.setMargin(0)
|
2021-07-24 20:04:58 +00:00
|
|
|
|
|
|
|
label.setText(name)
|
|
|
|
|
2021-07-23 16:01:09 +00:00
|
|
|
label.setAlignment(
|
|
|
|
QtCore.Qt.AlignVCenter
|
|
|
|
| QtCore.Qt.AlignLeft
|
|
|
|
)
|
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
# self.vbox.addWidget(label, **vbox_kwargs)
|
2021-07-25 19:43:41 +00:00
|
|
|
self.labels[name] = label
|
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
return label
|
|
|
|
|
|
|
|
def add_edit_field(
|
|
|
|
self,
|
|
|
|
|
|
|
|
name: str,
|
|
|
|
value: str,
|
|
|
|
|
|
|
|
widget: Optional[QWidget] = None,
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
) -> FontAndChartAwareLineEdit:
|
2021-07-25 03:15:44 +00:00
|
|
|
|
|
|
|
# TODO: maybe a distint layout per "field" item?
|
2021-07-30 14:50:05 +00:00
|
|
|
label = self.add_field_label(name)
|
2021-07-23 16:01:09 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
edit = FontAndChartAwareLineEdit(
|
2021-07-23 16:01:09 +00:00
|
|
|
parent=self,
|
|
|
|
)
|
2021-07-25 19:43:41 +00:00
|
|
|
edit.setStyleSheet(
|
2021-07-26 15:32:54 +00:00
|
|
|
f"""QLineEdit {{
|
|
|
|
color : {hcolor('gunmetal')};
|
|
|
|
font-size : {self._font_size}px;
|
|
|
|
}}
|
|
|
|
"""
|
2021-07-24 20:04:58 +00:00
|
|
|
)
|
2021-07-25 19:43:41 +00:00
|
|
|
edit.setText(str(value))
|
2021-07-30 14:50:05 +00:00
|
|
|
# self.vbox.addWidget(edit)
|
|
|
|
self.form.addRow(label, edit)
|
2021-07-25 19:43:41 +00:00
|
|
|
|
|
|
|
self.fields[name] = edit
|
|
|
|
|
|
|
|
return edit
|
2021-07-23 16:01:09 +00:00
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
def add_select_field(
|
|
|
|
self,
|
|
|
|
|
|
|
|
name: str,
|
|
|
|
values: list[str],
|
|
|
|
|
|
|
|
) -> QComboBox:
|
|
|
|
|
|
|
|
# TODO: maybe a distint layout per "field" item?
|
2021-07-30 14:50:05 +00:00
|
|
|
label = self.add_field_label(name)
|
2021-07-25 03:15:44 +00:00
|
|
|
|
|
|
|
select = QComboBox(self)
|
|
|
|
|
|
|
|
for i, value in enumerate(values):
|
2021-07-25 16:14:03 +00:00
|
|
|
select.insertItem(i, str(value))
|
2021-07-25 03:15:44 +00:00
|
|
|
|
|
|
|
select.setStyleSheet(
|
2021-07-26 15:32:54 +00:00
|
|
|
f"""QComboBox {{
|
|
|
|
color : {hcolor('gunmetal')};
|
|
|
|
font-size : {self._font_size}px;
|
|
|
|
}}
|
|
|
|
"""
|
2021-07-25 03:15:44 +00:00
|
|
|
)
|
2021-07-25 16:14:03 +00:00
|
|
|
select.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
|
|
|
select.setIconSize(QSize(0, 0))
|
|
|
|
self.setSizePolicy(
|
|
|
|
QSizePolicy.Fixed,
|
|
|
|
QSizePolicy.Fixed,
|
|
|
|
)
|
|
|
|
view = select.view()
|
2021-07-25 19:07:02 +00:00
|
|
|
view.setUniformItemSizes(True)
|
2021-07-25 16:14:03 +00:00
|
|
|
view.setItemDelegate(FontScaledDelegate(view))
|
|
|
|
|
|
|
|
# compute maximum item size so that the weird
|
|
|
|
# "style item delegate" thing can then specify
|
|
|
|
# that size on each item...
|
|
|
|
values.sort()
|
|
|
|
br = _font.boundingRect(str(values[-1]))
|
|
|
|
w, h = br.width(), br.height()
|
2021-07-25 19:07:02 +00:00
|
|
|
|
|
|
|
# TODO: something better then this monkey patch
|
2021-07-25 16:14:03 +00:00
|
|
|
view._max_item_size = w, h
|
|
|
|
|
|
|
|
# limit to 6 items?
|
|
|
|
view.setMaximumHeight(6*h)
|
2021-07-26 15:32:54 +00:00
|
|
|
# one entry in view
|
|
|
|
select.setMinimumHeight(h)
|
|
|
|
|
2021-07-25 03:15:44 +00:00
|
|
|
select.show()
|
2021-07-25 19:07:02 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
# self.vbox.addWidget(select)
|
|
|
|
self.form.addRow(label, select)
|
2021-07-25 03:15:44 +00:00
|
|
|
|
|
|
|
return select
|
|
|
|
|
2021-07-23 16:01:09 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
async def handle_field_input(
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
widget: QWidget,
|
2021-07-30 14:50:05 +00:00
|
|
|
# last_widget: QWidget, # had focus prior
|
2021-07-25 19:43:41 +00:00
|
|
|
recv_chan: trio.abc.ReceiveChannel,
|
|
|
|
form: FieldsForm,
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
) -> None:
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
async for event, etype, key, mods, txt in recv_chan:
|
|
|
|
print(f'key: {key}, mods: {mods}, txt: {txt}')
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
# default controls set
|
2021-07-25 19:43:41 +00:00
|
|
|
ctl = False
|
|
|
|
if mods == Qt.ControlModifier:
|
|
|
|
ctl = True
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
if ctl and key in { # cancel and refocus
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
Qt.Key_C,
|
2021-07-30 14:50:05 +00:00
|
|
|
Qt.Key_Space, # i feel like this is the "native" one
|
2021-07-25 19:43:41 +00:00
|
|
|
Qt.Key_Alt,
|
|
|
|
}:
|
2021-07-30 14:50:05 +00:00
|
|
|
# kill the widget focus and go back to main chart
|
2021-07-26 15:32:54 +00:00
|
|
|
widget.clearFocus()
|
|
|
|
form.godwidget.linkedsplits.focus()
|
2021-07-25 19:43:41 +00:00
|
|
|
continue
|
2021-07-24 20:04:58 +00:00
|
|
|
|
|
|
|
|
2021-07-25 19:43:41 +00:00
|
|
|
@asynccontextmanager
|
2021-07-26 00:32:29 +00:00
|
|
|
async def open_form(
|
2021-07-24 20:04:58 +00:00
|
|
|
|
2021-07-26 15:32:54 +00:00
|
|
|
godwidget: QWidget,
|
2021-07-24 20:04:58 +00:00
|
|
|
parent: QWidget,
|
|
|
|
fields: dict,
|
|
|
|
# orientation: str = 'horizontal',
|
|
|
|
|
|
|
|
) -> FieldsForm:
|
|
|
|
|
|
|
|
form = FieldsForm(parent)
|
|
|
|
|
2021-07-26 00:32:29 +00:00
|
|
|
for name, config in fields.items():
|
|
|
|
wtype = config['type']
|
|
|
|
key = str(config['key'])
|
2021-07-25 03:15:44 +00:00
|
|
|
|
2021-07-26 00:32:29 +00:00
|
|
|
# plain (line) edit field
|
|
|
|
if wtype == 'edit':
|
|
|
|
form.add_edit_field(key, config['default_value'])
|
|
|
|
|
|
|
|
# drop-down selection
|
|
|
|
elif wtype == 'select':
|
|
|
|
values = list(config['default_value'])
|
|
|
|
form.add_select_field(key, values)
|
2021-07-25 03:15:44 +00:00
|
|
|
|
2021-07-27 10:11:47 +00:00
|
|
|
async with open_handlers(
|
|
|
|
|
|
|
|
list(form.fields.values()),
|
|
|
|
event_types={QEvent.KeyPress},
|
|
|
|
|
|
|
|
async_handler=partial(
|
|
|
|
handle_field_input,
|
|
|
|
form=form,
|
|
|
|
),
|
|
|
|
|
|
|
|
# block key repeats?
|
|
|
|
filter_auto_repeats=True,
|
|
|
|
):
|
|
|
|
yield form
|
|
|
|
|
|
|
|
|
|
|
|
def mk_health_bar(
|
2021-07-30 14:50:05 +00:00
|
|
|
fields: FieldsForm,
|
2021-07-27 10:11:47 +00:00
|
|
|
|
|
|
|
) -> FieldsForm:
|
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
# fh = form.form.sizeHint().height()
|
|
|
|
|
|
|
|
w, h = fields.width(), fields.height()
|
|
|
|
print(f'w, h: {w, h}')
|
|
|
|
|
|
|
|
# TODO: spec this based on remaining space?
|
|
|
|
# fields.vbox.addSpacing(36)
|
|
|
|
fields.vbox.addSpacing((5/8) * h)
|
|
|
|
|
|
|
|
# title label
|
|
|
|
pps_label = fields.add_field_label(
|
|
|
|
'pps',
|
|
|
|
font_size=_font_small.px_size,
|
|
|
|
)
|
|
|
|
|
|
|
|
# indent = 18
|
|
|
|
bracket_val = 0.375 * w
|
|
|
|
indent = bracket_val / 1.625
|
|
|
|
|
|
|
|
section_hbox = QtGui.QHBoxLayout(fields)
|
|
|
|
section_hbox.addSpacing(indent - 2) # pair with bar indent
|
|
|
|
section_hbox.addWidget(
|
|
|
|
pps_label,
|
|
|
|
alignment=Qt.AlignLeft | Qt.AlignTop,
|
|
|
|
)
|
|
|
|
|
|
|
|
# fields.vbox.addWidget(
|
|
|
|
# label,
|
|
|
|
# alignment=Qt.AlignLeft | Qt.AlignTop
|
|
|
|
# )
|
|
|
|
fields.vbox.addLayout(section_hbox)
|
|
|
|
|
|
|
|
# TODO: spec this based on remaining space?
|
|
|
|
fields.vbox.addSpacing(6)
|
2021-07-26 19:38:15 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
hbox = QtGui.QHBoxLayout(fields)
|
|
|
|
|
|
|
|
hbox.addSpacing(indent) # push to right a bit
|
|
|
|
|
|
|
|
# config
|
|
|
|
hbox.setSpacing(indent * 0.375)
|
|
|
|
hbox.setAlignment(Qt.AlignTop | Qt.AlignLeft)
|
|
|
|
hbox.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
# info label on RHS
|
|
|
|
# {30}% PnL\n
|
|
|
|
|
|
|
|
# TODO: use percentage str formatter:
|
|
|
|
#https://docs.python.org/3/library/string.html#grammar-token-precision
|
|
|
|
|
|
|
|
top_label = fields.add_field_label(
|
|
|
|
dedent(f"""
|
|
|
|
{3.32:.1f}% port
|
|
|
|
"""),
|
|
|
|
font_size=_font.px_size - 5,
|
|
|
|
)
|
|
|
|
|
|
|
|
bottom_label = fields.add_field_label(
|
|
|
|
dedent(f"""
|
|
|
|
{5e3/4/1e3:.1f}k step\n
|
|
|
|
"""),
|
|
|
|
font_size=_font.px_size - 5,
|
|
|
|
)
|
|
|
|
|
|
|
|
bar = QProgressBar(fields)
|
|
|
|
hbox.addWidget(bar, alignment=Qt.AlignLeft | Qt.AlignTop)
|
|
|
|
|
|
|
|
bar_label_vbox = QtGui.QVBoxLayout(fields)
|
|
|
|
bar_label_vbox.addWidget(
|
|
|
|
top_label,
|
|
|
|
alignment=Qt.AlignLeft | Qt.AlignTop
|
|
|
|
)
|
|
|
|
bar_label_vbox.addWidget(
|
|
|
|
bottom_label,
|
|
|
|
alignment=Qt.AlignLeft | Qt.AlignBottom
|
|
|
|
)
|
|
|
|
|
|
|
|
hbox.addLayout(bar_label_vbox)
|
|
|
|
|
|
|
|
fields.vbox.addLayout(hbox) # add status bar to form
|
|
|
|
|
|
|
|
fields.vbox.addSpacing(36) # add status bar to form
|
|
|
|
|
|
|
|
feed_label = fields.add_field_label(
|
|
|
|
dedent("""
|
|
|
|
brokerd.ib\n
|
|
|
|
|_@localhost:8509\n
|
|
|
|
|_consumers: 4\n
|
|
|
|
|_streams: 9\n
|
|
|
|
"""),
|
|
|
|
font_size=_font.px_size - 5,
|
|
|
|
)
|
|
|
|
fields.vbox.addSpacing(3/8 * h)
|
|
|
|
|
|
|
|
# add feed info label
|
|
|
|
fields.vbox.addWidget(
|
|
|
|
feed_label,
|
|
|
|
alignment=Qt.AlignBottom,
|
|
|
|
)
|
|
|
|
|
|
|
|
# compute "chunk" sizes for fill-status-bar based on some static height
|
2021-07-26 19:38:15 +00:00
|
|
|
slots = 4
|
|
|
|
border_size_px = 2
|
2021-07-30 14:50:05 +00:00
|
|
|
slot_margin_px = 2
|
|
|
|
|
|
|
|
# TODO: compute "used height" thus far and mostly fill the rest
|
|
|
|
h = 200
|
|
|
|
slot_height_px = math.floor(
|
|
|
|
(h - 2*border_size_px)/slots
|
|
|
|
) - slot_margin_px*1
|
2021-07-26 19:38:15 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
bar.setOrientation(Qt.Vertical)
|
|
|
|
bar.setStyleSheet(
|
2021-07-26 19:38:15 +00:00
|
|
|
f"""
|
|
|
|
QProgressBar {{
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
font-size : {fields._font_size - 2}px;
|
2021-07-26 19:38:15 +00:00
|
|
|
|
2021-07-26 15:32:54 +00:00
|
|
|
background-color: {hcolor('papas_special')};
|
2021-07-26 19:38:15 +00:00
|
|
|
color : {hcolor('papas_special')};
|
|
|
|
|
|
|
|
border: {border_size_px}px solid {hcolor('default_light')};
|
|
|
|
border-radius: 2px;
|
2021-07-26 15:32:54 +00:00
|
|
|
}}
|
2021-07-26 19:38:15 +00:00
|
|
|
|
|
|
|
QProgressBar::chunk {{
|
|
|
|
|
|
|
|
background-color: {hcolor('default_lightest')};
|
|
|
|
color: {hcolor('papas_special')};
|
|
|
|
|
|
|
|
border-radius: 2px;
|
|
|
|
|
|
|
|
margin: {slot_margin_px}px;
|
|
|
|
height: {slot_height_px}px;
|
|
|
|
|
|
|
|
}}
|
2021-07-26 15:32:54 +00:00
|
|
|
"""
|
|
|
|
)
|
2021-07-26 19:38:15 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
# margin-bottom: {slot_margin_px*2}px;
|
|
|
|
# margin-top: {slot_margin_px*2}px;
|
|
|
|
# color: #19232D;
|
|
|
|
# width: 10px;
|
|
|
|
|
|
|
|
bar.setRange(0, slots)
|
|
|
|
bar.setValue(slots)
|
|
|
|
bar.setFormat('')
|
|
|
|
bar.setMinimumHeight(h)
|
|
|
|
bar.setMaximumHeight(h + slots*slot_margin_px)
|
|
|
|
bar.setMinimumWidth(bracket_val)
|
|
|
|
bar.setMaximumWidth(bracket_val)
|
2021-07-25 03:15:44 +00:00
|
|
|
|
2021-07-30 14:50:05 +00:00
|
|
|
return fields
|