Factor combobox logic into a new `Selection` subtype
parent
6a31c4e160
commit
75e1bf3f6e
|
@ -42,12 +42,10 @@ from PyQt5.QtWidgets import (
|
|||
QStyledItemDelegate,
|
||||
QStyleOptionViewItem,
|
||||
)
|
||||
# import pydantic
|
||||
|
||||
from ._event import open_handlers
|
||||
from ._style import hcolor, _font, _font_small, DpiAwareFont
|
||||
from ._label import FormatLabel
|
||||
from .. import config
|
||||
|
||||
|
||||
class FontAndChartAwareLineEdit(QLineEdit):
|
||||
|
@ -71,17 +69,21 @@ class FontAndChartAwareLineEdit(QLineEdit):
|
|||
|
||||
if width_in_chars:
|
||||
self._chars = int(width_in_chars)
|
||||
x_size_policy = QSizePolicy.Fixed
|
||||
|
||||
else:
|
||||
# chart count which will be used to calculate
|
||||
# width of input field.
|
||||
self._chars: int = 9
|
||||
self._chars: int = 6
|
||||
# fit to surroundingn frame width
|
||||
x_size_policy = QSizePolicy.Expanding
|
||||
|
||||
super().__init__(parent)
|
||||
|
||||
# size it as we specify
|
||||
# https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
|
||||
self.setSizePolicy(
|
||||
QSizePolicy.Expanding,
|
||||
x_size_policy,
|
||||
QSizePolicy.Fixed,
|
||||
)
|
||||
self.setFont(font.font)
|
||||
|
@ -99,11 +101,11 @@ class FontAndChartAwareLineEdit(QLineEdit):
|
|||
dpi_font = self.dpi_font
|
||||
psh.setHeight(dpi_font.px_size)
|
||||
|
||||
# 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)
|
||||
|
||||
# make space for ``._chars: int`` for of characters in view
|
||||
# TODO: somehow this math ain't right?
|
||||
chars_w_pxs = dpi_font.boundingRect('0'*self._chars).width()
|
||||
scale = round(dpi_font.scale())
|
||||
psh.setWidth(chars_w_pxs * scale)
|
||||
return psh
|
||||
|
||||
def set_width_in_chars(
|
||||
|
@ -167,23 +169,93 @@ class FontScaledDelegate(QStyledItemDelegate):
|
|||
# QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
||||
|
||||
# NOTE: in theory we can put icons on the RHS side with this hackery:
|
||||
# https://stackoverflow.com/a/64256969
|
||||
# class ComboBox(QComboBox):
|
||||
# def __init__(
|
||||
# self,
|
||||
# parent=None,
|
||||
# ) -> None:
|
||||
# super().__init__(parent=parent)
|
||||
class Selection(QComboBox):
|
||||
|
||||
# def showPopup(self):
|
||||
# print('show')
|
||||
# QComboBox.showPopup(self)
|
||||
def __init__(
|
||||
self,
|
||||
parent=None,
|
||||
|
||||
# def hidePopup(self):
|
||||
# # self.setItemDelegate(FontScaledDelegate(self.parent()))
|
||||
# print('hide')
|
||||
# QComboBox.hidePopup(self)
|
||||
) -> None:
|
||||
|
||||
self._items: dict[str, int] = {}
|
||||
|
||||
super().__init__(parent=parent)
|
||||
self.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
||||
# make line edit expand to surrounding frame
|
||||
self.setSizePolicy(
|
||||
QSizePolicy.Expanding,
|
||||
QSizePolicy.Fixed,
|
||||
)
|
||||
view = self.view()
|
||||
view.setUniformItemSizes(True)
|
||||
|
||||
# TODO: this doesn't seem to work for the currently selected item?
|
||||
self.setItemDelegate(FontScaledDelegate(self))
|
||||
|
||||
def set_style(
|
||||
self,
|
||||
|
||||
color: str,
|
||||
font_size: int,
|
||||
|
||||
) -> None:
|
||||
|
||||
self.setStyleSheet(
|
||||
f"""QComboBox {{
|
||||
color : {hcolor(color)};
|
||||
font-size : {font_size}px;
|
||||
}}
|
||||
"""
|
||||
)
|
||||
|
||||
def set_items(
|
||||
self,
|
||||
keys: list[str],
|
||||
|
||||
) -> None:
|
||||
'''Write keys to the selection verbatim.
|
||||
|
||||
All other items are cleared beforehand.
|
||||
'''
|
||||
self.clear()
|
||||
self._items.clear()
|
||||
|
||||
for i, key in enumerate(keys):
|
||||
strkey = str(key)
|
||||
self.insertItem(i, strkey)
|
||||
|
||||
# store map of entry keys to row indexes
|
||||
self._items[strkey] = i
|
||||
|
||||
# compute max item size so that the weird
|
||||
# "style item delegate" thing can then specify
|
||||
# that size on each item...
|
||||
keys.sort()
|
||||
br = _font.boundingRect(str(keys[-1]))
|
||||
_, h = br.width(), br.height()
|
||||
|
||||
# TODO: something better then this monkey patch
|
||||
view = self.view()
|
||||
|
||||
# XXX: see size policy settings of line edit
|
||||
# view._max_item_size = w, h
|
||||
|
||||
self.setMinimumHeight(h) # at least one entry in view
|
||||
view.setMaximumHeight(6*h) # limit to 6 items max in view
|
||||
|
||||
icon_size = round(h * 0.75)
|
||||
self.setIconSize(QSize(icon_size, icon_size))
|
||||
|
||||
# # NOTE: in theory we can put icons on the RHS side with this hackery:
|
||||
# # https://stackoverflow.com/a/64256969
|
||||
# def showPopup(self):
|
||||
# print('show')
|
||||
# QComboBox.showPopup(self)
|
||||
|
||||
# def hidePopup(self):
|
||||
# # self.setItemDelegate(FontScaledDelegate(self.parent()))
|
||||
# print('hide')
|
||||
# QComboBox.hidePopup(self)
|
||||
|
||||
|
||||
# slew of resources which helped get this where it is:
|
||||
|
@ -279,6 +351,7 @@ class FieldsForm(QWidget):
|
|||
|
||||
edit = FontAndChartAwareLineEdit(
|
||||
parent=self,
|
||||
# width_in_chars=6,
|
||||
)
|
||||
edit.setStyleSheet(
|
||||
f"""QLineEdit {{
|
||||
|
@ -301,66 +374,23 @@ class FieldsForm(QWidget):
|
|||
label_name: str,
|
||||
values: list[str],
|
||||
|
||||
) -> QComboBox:
|
||||
) -> Selection:
|
||||
|
||||
# TODO: maybe a distint layout per "field" item?
|
||||
label = self.add_field_label(label_name)
|
||||
|
||||
select = QComboBox(self)
|
||||
select = Selection(self)
|
||||
select.set_style(color='gunmetal', font_size=self._font_size)
|
||||
select._key = key
|
||||
select._items: dict[str, int] = {}
|
||||
|
||||
for i, value in enumerate(values):
|
||||
strkey = str(value)
|
||||
select.insertItem(i, strkey)
|
||||
|
||||
# store map of entry keys to row indexes
|
||||
select._items[strkey] = i
|
||||
|
||||
select.setStyleSheet(
|
||||
f"""QComboBox {{
|
||||
color : {hcolor('gunmetal')};
|
||||
font-size : {self._font_size}px;
|
||||
}}
|
||||
"""
|
||||
)
|
||||
select.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
||||
select.set_items(values)
|
||||
|
||||
self.setSizePolicy(
|
||||
QSizePolicy.Fixed,
|
||||
QSizePolicy.Fixed,
|
||||
)
|
||||
view = select.view()
|
||||
view.setUniformItemSizes(True)
|
||||
|
||||
# TODO: this doesn't seem to work for the currently selected item?
|
||||
select.setItemDelegate(FontScaledDelegate(self))
|
||||
|
||||
# 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]))
|
||||
_, h = br.width(), br.height()
|
||||
|
||||
icon_size = round(h * 0.75)
|
||||
select.setIconSize(QSize(icon_size, icon_size))
|
||||
|
||||
# TODO: something better then this monkey patch
|
||||
# view._max_item_size = w, h
|
||||
|
||||
# limit to 6 items?
|
||||
view.setMaximumHeight(6*h)
|
||||
|
||||
# one entry in view
|
||||
select.setMinimumHeight(h)
|
||||
|
||||
select.show()
|
||||
|
||||
self.form.addRow(label, select)
|
||||
|
||||
self.fields[key] = select
|
||||
|
||||
return select
|
||||
|
||||
|
||||
|
@ -669,7 +699,6 @@ def mk_order_pane_layout(
|
|||
) -> FieldsForm:
|
||||
|
||||
font_size: int = _font.px_size - 1
|
||||
accounts = config.load_accounts()
|
||||
|
||||
# TODO: maybe just allocate the whole fields form here
|
||||
# and expect an async ctx entry?
|
||||
|
@ -679,7 +708,7 @@ def mk_order_pane_layout(
|
|||
'account': {
|
||||
'label': '**account**:',
|
||||
'type': 'select',
|
||||
'default_value': accounts.keys(),
|
||||
'default_value': ['paper'],
|
||||
},
|
||||
'size_unit': {
|
||||
'label': '**allocate**:',
|
||||
|
@ -721,7 +750,6 @@ def mk_order_pane_layout(
|
|||
form,
|
||||
pane_vbox=vbox,
|
||||
label_font_size=font_size,
|
||||
|
||||
)
|
||||
# TODO: would be nice to have some better way of reffing these over
|
||||
# monkey patching...
|
||||
|
|
Loading…
Reference in New Issue