Factor combobox logic into a new `Selection` subtype
parent
6a31c4e160
commit
75e1bf3f6e
|
@ -42,12 +42,10 @@ from PyQt5.QtWidgets import (
|
||||||
QStyledItemDelegate,
|
QStyledItemDelegate,
|
||||||
QStyleOptionViewItem,
|
QStyleOptionViewItem,
|
||||||
)
|
)
|
||||||
# import pydantic
|
|
||||||
|
|
||||||
from ._event import open_handlers
|
from ._event import open_handlers
|
||||||
from ._style import hcolor, _font, _font_small, DpiAwareFont
|
from ._style import hcolor, _font, _font_small, DpiAwareFont
|
||||||
from ._label import FormatLabel
|
from ._label import FormatLabel
|
||||||
from .. import config
|
|
||||||
|
|
||||||
|
|
||||||
class FontAndChartAwareLineEdit(QLineEdit):
|
class FontAndChartAwareLineEdit(QLineEdit):
|
||||||
|
@ -71,17 +69,21 @@ class FontAndChartAwareLineEdit(QLineEdit):
|
||||||
|
|
||||||
if width_in_chars:
|
if width_in_chars:
|
||||||
self._chars = int(width_in_chars)
|
self._chars = int(width_in_chars)
|
||||||
|
x_size_policy = QSizePolicy.Fixed
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# chart count which will be used to calculate
|
# chart count which will be used to calculate
|
||||||
# width of input field.
|
# 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)
|
super().__init__(parent)
|
||||||
|
|
||||||
# size it as we specify
|
# size it as we specify
|
||||||
# https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
|
# https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum
|
||||||
self.setSizePolicy(
|
self.setSizePolicy(
|
||||||
QSizePolicy.Expanding,
|
x_size_policy,
|
||||||
QSizePolicy.Fixed,
|
QSizePolicy.Fixed,
|
||||||
)
|
)
|
||||||
self.setFont(font.font)
|
self.setFont(font.font)
|
||||||
|
@ -99,11 +101,11 @@ class FontAndChartAwareLineEdit(QLineEdit):
|
||||||
dpi_font = self.dpi_font
|
dpi_font = self.dpi_font
|
||||||
psh.setHeight(dpi_font.px_size)
|
psh.setHeight(dpi_font.px_size)
|
||||||
|
|
||||||
# space for ``._chars: int``
|
# make space for ``._chars: int`` for of characters in view
|
||||||
char_w_pxs = dpi_font.boundingRect(self.text()).width()
|
# TODO: somehow this math ain't right?
|
||||||
chars_w = char_w_pxs + 6 # * dpi_font.scale() * self._chars
|
chars_w_pxs = dpi_font.boundingRect('0'*self._chars).width()
|
||||||
psh.setWidth(chars_w)
|
scale = round(dpi_font.scale())
|
||||||
|
psh.setWidth(chars_w_pxs * scale)
|
||||||
return psh
|
return psh
|
||||||
|
|
||||||
def set_width_in_chars(
|
def set_width_in_chars(
|
||||||
|
@ -167,23 +169,93 @@ class FontScaledDelegate(QStyledItemDelegate):
|
||||||
# QStyledItemDelegate.paint(self, painter, option, index)
|
# QStyledItemDelegate.paint(self, painter, option, index)
|
||||||
|
|
||||||
|
|
||||||
# NOTE: in theory we can put icons on the RHS side with this hackery:
|
class Selection(QComboBox):
|
||||||
# https://stackoverflow.com/a/64256969
|
|
||||||
# class ComboBox(QComboBox):
|
|
||||||
# def __init__(
|
|
||||||
# self,
|
|
||||||
# parent=None,
|
|
||||||
# ) -> None:
|
|
||||||
# super().__init__(parent=parent)
|
|
||||||
|
|
||||||
# def showPopup(self):
|
def __init__(
|
||||||
# print('show')
|
self,
|
||||||
# QComboBox.showPopup(self)
|
parent=None,
|
||||||
|
|
||||||
# def hidePopup(self):
|
) -> None:
|
||||||
# # self.setItemDelegate(FontScaledDelegate(self.parent()))
|
|
||||||
# print('hide')
|
self._items: dict[str, int] = {}
|
||||||
# QComboBox.hidePopup(self)
|
|
||||||
|
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:
|
# slew of resources which helped get this where it is:
|
||||||
|
@ -279,6 +351,7 @@ class FieldsForm(QWidget):
|
||||||
|
|
||||||
edit = FontAndChartAwareLineEdit(
|
edit = FontAndChartAwareLineEdit(
|
||||||
parent=self,
|
parent=self,
|
||||||
|
# width_in_chars=6,
|
||||||
)
|
)
|
||||||
edit.setStyleSheet(
|
edit.setStyleSheet(
|
||||||
f"""QLineEdit {{
|
f"""QLineEdit {{
|
||||||
|
@ -301,66 +374,23 @@ class FieldsForm(QWidget):
|
||||||
label_name: str,
|
label_name: str,
|
||||||
values: list[str],
|
values: list[str],
|
||||||
|
|
||||||
) -> QComboBox:
|
) -> Selection:
|
||||||
|
|
||||||
# TODO: maybe a distint layout per "field" item?
|
# TODO: maybe a distint layout per "field" item?
|
||||||
label = self.add_field_label(label_name)
|
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._key = key
|
||||||
select._items: dict[str, int] = {}
|
select.set_items(values)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
self.setSizePolicy(
|
self.setSizePolicy(
|
||||||
QSizePolicy.Fixed,
|
QSizePolicy.Fixed,
|
||||||
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()
|
select.show()
|
||||||
|
|
||||||
self.form.addRow(label, select)
|
self.form.addRow(label, select)
|
||||||
|
|
||||||
self.fields[key] = select
|
self.fields[key] = select
|
||||||
|
|
||||||
return select
|
return select
|
||||||
|
|
||||||
|
|
||||||
|
@ -669,7 +699,6 @@ def mk_order_pane_layout(
|
||||||
) -> FieldsForm:
|
) -> FieldsForm:
|
||||||
|
|
||||||
font_size: int = _font.px_size - 1
|
font_size: int = _font.px_size - 1
|
||||||
accounts = config.load_accounts()
|
|
||||||
|
|
||||||
# TODO: maybe just allocate the whole fields form here
|
# TODO: maybe just allocate the whole fields form here
|
||||||
# and expect an async ctx entry?
|
# and expect an async ctx entry?
|
||||||
|
@ -679,7 +708,7 @@ def mk_order_pane_layout(
|
||||||
'account': {
|
'account': {
|
||||||
'label': '**account**:',
|
'label': '**account**:',
|
||||||
'type': 'select',
|
'type': 'select',
|
||||||
'default_value': accounts.keys(),
|
'default_value': ['paper'],
|
||||||
},
|
},
|
||||||
'size_unit': {
|
'size_unit': {
|
||||||
'label': '**allocate**:',
|
'label': '**allocate**:',
|
||||||
|
@ -721,7 +750,6 @@ def mk_order_pane_layout(
|
||||||
form,
|
form,
|
||||||
pane_vbox=vbox,
|
pane_vbox=vbox,
|
||||||
label_font_size=font_size,
|
label_font_size=font_size,
|
||||||
|
|
||||||
)
|
)
|
||||||
# TODO: would be nice to have some better way of reffing these over
|
# TODO: would be nice to have some better way of reffing these over
|
||||||
# monkey patching...
|
# monkey patching...
|
||||||
|
|
Loading…
Reference in New Issue