Skip to content

Commit 375585f

Browse files
committed
- adds plus non-standard bean label formatting
- fixes some drag-event corner cases
1 parent a13553d commit 375585f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+26870
-26174
lines changed

src/artisanlib/background.py

+1
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ def readChecks(self) -> None:
765765
self.aw.qmc.backgroundETcurve = bool(self.backgroundETflag.isChecked())
766766
self.aw.qmc.backgroundBTcurve = bool(self.backgroundBTflag.isChecked())
767767
self.aw.qmc.backgroundShowFullflag = bool(self.backgroundFullflag.isChecked())
768+
self.aw.qmc.l_annotations_dict = {}
768769
self.aw.qmc.redraw_keep_view(recomputeAllDeltas=True)
769770

770771
@pyqtSlot(int)

src/artisanlib/canvas.py

+193-115
Large diffs are not rendered by default.

src/artisanlib/devices.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4241,9 +4241,10 @@ def okEvent(self) -> None: # pyright: ignore [reportGeneralTypeIssues] # Code is
42414241
self.aw.LCD7frame.setVisible(False)
42424242
self.aw.qmc.ETfunction = str(self.ETfunctionedit.text())
42434243
self.aw.qmc.BTfunction = str(self.BTfunctionedit.text())
4244-
if self.aw.qmc.BTcurve != self.BTcurve.isChecked():
4244+
if self.aw.qmc.BTcurve != self.BTcurve.isChecked() or self.aw.qmc.ETcurve != self.ETcurve.isChecked():
42454245
# we reset the cached main event annotation positions as those annotations are now rendered on the other curve
42464246
self.aw.qmc.l_annotations_dict = {}
4247+
self.aw.qmc.l_event_flags_dict = {}
42474248
self.aw.qmc.ETcurve = self.ETcurve.isChecked()
42484249
self.aw.qmc.BTcurve = self.BTcurve.isChecked()
42494250
self.aw.qmc.ETlcd = self.ETlcd.isChecked()

src/artisanlib/main.py

+4
Original file line numberDiff line numberDiff line change
@@ -4469,6 +4469,7 @@ def toggleBTCurve(self) -> None:
44694469
self.qmc.BTcurve = not self.qmc.BTcurve
44704470
# we reset the cached main event annotation positions as those annotations are now rendered on the other curve
44714471
self.qmc.l_annotations_dict = {}
4472+
self.qmc.l_event_flags_dict = {}
44724473
# and redraw
44734474
self.qmc.redraw_keep_view(recomputeAllDeltas=False)
44744475

@@ -4478,6 +4479,7 @@ def toggleETCurve(self) -> None:
44784479
self.qmc.ETcurve = not self.qmc.ETcurve
44794480
# we reset the cached main event annotation positions as those annotations are now rendered on the other curve
44804481
self.qmc.l_annotations_dict = {}
4482+
self.qmc.l_event_flags_dict = {}
44814483
self.qmc.redraw_keep_view(recomputeAllDeltas=False)
44824484

44834485
@pyqtSlot()
@@ -17366,6 +17368,7 @@ def settingsLoad(self, filename:Optional[str] = None, theme:bool = False, machin
1736617368
self.plus_language = settings.value('plus_language',self.plus_language)
1736717369
self.plus_user_id = settings.value('plus_user_id',self.plus_user_id)
1736817370
self.plus_account_id = settings.value('plus_account_id',self.plus_account_id)
17371+
plus.stock.coffee_label_normal_order = settings.value('standard_bean_labels',plus.stock.coffee_label_normal_order)
1736917372
#remember swaplcds and swapdeltalcds
1737017373
old_swaplcds = self.qmc.swaplcds
1737117374
old_swapdeltalcds = self.qmc.swapdeltalcds
@@ -19355,6 +19358,7 @@ def saveAllSettings(self, settings:QSettings, default_settings:Optional[Dict[str
1935519358
self.settingsSetValue(settings, default_settings, 'plus_language', self.plus_language, read_defaults)
1935619359
self.settingsSetValue(settings, default_settings, 'plus_user_id', self.plus_user_id, read_defaults)
1935719360
self.settingsSetValue(settings, default_settings, 'plus_account_id', self.plus_account_id, read_defaults)
19361+
self.settingsSetValue(settings, default_settings, 'standard_bean_labels', plus.stock.coffee_label_normal_order, read_defaults)
1935819362

1935919363
if not read_defaults: # we don't add those to the cache forcing those settings to be saved always
1936019364
#save window geometry if not in fullscreen mode

src/artisanlib/roast_properties.py

+47-33
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@
5959
from PyQt6.QtWidgets import (QApplication, QWidget, QCheckBox, QComboBox, QDialogButtonBox, QGridLayout, # @UnusedImport @Reimport @UnresolvedImport
6060
QHBoxLayout, QVBoxLayout, QHeaderView, QLabel, QLineEdit, QTextEdit, QListView, # @UnusedImport @Reimport @UnresolvedImport
6161
QPushButton, QSpinBox, QTableWidget, QTableWidgetItem, QTabWidget, QSizePolicy, # @UnusedImport @Reimport @UnresolvedImport
62-
QGroupBox, QToolButton) # @UnusedImport @Reimport @UnresolvedImport
62+
QGroupBox, QToolButton, QFrame) # @UnusedImport @Reimport @UnresolvedImport
6363
# from PyQt6 import sip # @UnusedImport @Reimport @UnresolvedImport
6464
except ImportError:
6565
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, QRegularExpression, QSettings, QTimer, QEvent, QLocale, QSignalBlocker # type: ignore # @UnusedImport @Reimport @UnresolvedImport
6666
from PyQt5.QtGui import QColor, QIntValidator, QRegularExpressionValidator, QKeySequence, QPalette # type: ignore # @UnusedImport @Reimport @UnresolvedImport
6767
from PyQt5.QtWidgets import (QApplication, QWidget, QCheckBox, QComboBox, QDialogButtonBox, QGridLayout, # type: ignore # @UnusedImport @Reimport @UnresolvedImport
6868
QHBoxLayout, QVBoxLayout, QHeaderView, QLabel, QLineEdit, QTextEdit, QListView, # @UnusedImport @Reimport @UnresolvedImport
6969
QPushButton, QSpinBox, QTableWidget, QTableWidgetItem, QTabWidget, QSizePolicy, # @UnusedImport @Reimport @UnresolvedImport
70-
QGroupBox, QToolButton) # @UnusedImport @Reimport @UnresolvedImport
70+
QGroupBox, QToolButton, QFrame) # @UnusedImport @Reimport @UnresolvedImport
7171
# try:
7272
# from PyQt5 import sip # type: ignore # @Reimport @UnresolvedImport @UnusedImport
7373
# except ImportError:
@@ -983,11 +983,13 @@ def __init__(self, parent:QWidget, aw:'ApplicationWindow', activeTab:int = 0) ->
983983
self.addRecentButton = QPushButton('+')
984984
self.addRecentButton.clicked.connect(self.addRecentRoast)
985985
self.addRecentButton.setFocusPolicy(Qt.FocusPolicy.NoFocus)
986+
self.addRecentButton.setToolTip(QApplication.translate('Tooltip','Add roast properties to list of recent roasts'))
986987

987988
# delete from recent
988989
self.delRecentButton = QPushButton('-')
989990
self.delRecentButton.clicked.connect(self.delRecentRoast)
990991
self.delRecentButton.setFocusPolicy(Qt.FocusPolicy.NoFocus)
992+
self.delRecentButton.setToolTip(QApplication.translate('Tooltip','Remove roast properties from list of recent roasts'))
991993

992994
self.recentRoastEnabled()
993995

@@ -1299,26 +1301,49 @@ def __init__(self, parent:QWidget, aw:'ApplicationWindow', activeTab:int = 0) ->
12991301
self.plus_coffees_combo.setMinimumContentsLength(15)
13001302
self.plus_blends_combo.setMinimumContentsLength(10)
13011303
self.plus_stores_combo.setMinimumContentsLength(10)
1302-
self.plus_stores_combo.setMaximumWidth(120)
1304+
self.plus_stores_combo.setMaximumWidth(130)
13031305
self.plus_coffees_combo.setSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Maximum)
13041306
self.plus_coffees_combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
13051307
self.plus_blends_combo.setSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Maximum)
13061308
self.plus_blends_combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
13071309
self.plus_stores_combo.setSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Maximum)
13081310
self.plus_stores_combo.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
13091311
# plus widget row
1312+
1313+
plusLineStores = QHBoxLayout()
1314+
plusLineStores.addSpacing(10)
1315+
plusLineStores.addWidget(self.plusStoreslabel)
1316+
plusLineStores.addSpacing(5)
1317+
plusLineStores.addWidget(self.plus_stores_combo)
1318+
plusLineStores.setContentsMargins(0, 0, 0, 0) # left, top, right, bottom
1319+
plusLineStores.setSpacing(5)
1320+
1321+
self.plusLineStoresFrame = QFrame()
1322+
self.plusLineStoresFrame.setLayout(plusLineStores)
1323+
13101324
plusLine = QHBoxLayout()
13111325
plusLine.addWidget(self.plus_coffees_combo)
1312-
plusLine.addSpacing(15)
1326+
plusLine.addSpacing(10)
13131327
plusLine.addWidget(self.plusBlendslabel)
1314-
plusLine.addSpacing(5)
1328+
plusLine.addSpacing(4)
13151329
plusLine.addWidget(self.plus_blends_combo)
13161330
plusLine.addWidget(self.plus_custom_blend_button)
1317-
plusLine.addSpacing(15)
1318-
plusLine.addWidget(self.plusStoreslabel)
1319-
plusLine.addSpacing(5)
1320-
plusLine.addWidget(self.plus_stores_combo)
1321-
textLayout.addWidget(self.plus_selected_line,4,1)
1331+
plusLine.addWidget(self.plusLineStoresFrame)
1332+
1333+
plusLine.setStretch(0, 3)
1334+
plusLine.setStretch(4, 3)
1335+
plusLine.setStretch(6, 1)
1336+
1337+
self.label_origin_flag = QCheckBox(QApplication.translate('CheckBox','Standard bean labels'))
1338+
self.label_origin_flag.setToolTip(QApplication.translate('Tooltip',"Beans are listed as 'origin, name' if ticked, otherwise as 'name, origin'"))
1339+
self.label_origin_flag.setChecked(bool(plus.stock.coffee_label_normal_order))
1340+
self.label_origin_flag.stateChanged.connect(self.labelOriginFlagChanged)
1341+
1342+
selectedLineLayout = QHBoxLayout()
1343+
selectedLineLayout.addWidget(self.plus_selected_line)
1344+
selectedLineLayout.addStretch()
1345+
selectedLineLayout.addWidget(self.label_origin_flag)
1346+
textLayout.addLayout(selectedLineLayout,4,1)
13221347
textLayout.addWidget(plusCoffeeslabel,5,0)
13231348
textLayout.addLayout(plusLine,5,1)
13241349
textLayoutPlusOffset = 2 # to insert the plus widget row, we move the remaining ones one step lower
@@ -1901,19 +1926,13 @@ def populatePlusCoffeeBlendCombos(self, storeIndex:Optional[int] = None) -> None
19011926
if len(self.plus_stores) == 1:
19021927
self.plus_default_store = plus.stock.getStoreId(self.plus_stores[0])
19031928
if len(self.plus_stores) < 2:
1904-
#self.plusStoreslabel.setVisible(False)
1905-
if self.plusStoreslabel.isVisible():
1906-
self.plusStoreslabel.hide()
1907-
#self.plus_stores_combo.setVisible(False)
1908-
if self.plus_stores_combo.isVisible():
1909-
self.plus_stores_combo.hide()
1929+
# self.plusStoreslabel.hide()
1930+
# self.plus_stores_combo.hide()
1931+
self.plusLineStoresFrame.hide()
19101932
else:
1911-
#self.plusStoreslabel.setVisible(True)
1912-
if not self.plusStoreslabel.isVisible():
1913-
self.plusStoreslabel.show()
1914-
#self.plus_stores_combo.setVisible(True)
1915-
if not self.plus_stores_combo.isVisible():
1916-
self.plus_stores_combo.show()
1933+
# self.plusStoreslabel.show()
1934+
# self.plus_stores_combo.show()
1935+
self.plusLineStoresFrame.show()
19171936
except Exception as e: # pylint: disable=broad-except
19181937
_log.exception(e)
19191938
self.plus_stores_combo.blockSignals(True)
@@ -2221,17 +2240,7 @@ def coffeeSelectionChanged(self, n:int) -> None:
22212240
self.plus_store_selected_label = sd['location_label']
22222241
cd = plus.stock.getCoffeeCoffeeDict(selected_coffee)
22232242
self.plus_coffee_selected = cd.get('hr_id','')
2224-
origin = ''
2225-
if 'origin' in cd and cd['origin'] is not None:
2226-
origin = cd['origin']
2227-
picked = ''
2228-
if 'crop_date' in cd and 'picked' in cd['crop_date'] and len(cd['crop_date']['picked']) > 0 and cd['crop_date']['picked'][0] is not None and plus.stock.has_duplicate_origin_label(cd):
2229-
picked = f"{cd['crop_date']['picked'][0]}, "
2230-
if origin:
2231-
origin = f'{origin} '
2232-
elif origin:
2233-
picked = ', '
2234-
self.plus_coffee_selected_label = f"{origin}{picked}{cd.get('label','')}"
2243+
self.plus_coffee_selected_label = plus.stock.coffeeLabel(cd)
22352244
self.plus_blend_selected_label = None
22362245
self.plus_blend_selected_spec = None
22372246
self.plus_blend_selected_spec_labels = None
@@ -4168,6 +4177,11 @@ def roastpropertiesChanged(self, _:int = 0) -> None:
41684177
else:
41694178
self.aw.qmc.roastpropertiesflag = 0
41704179

4180+
@pyqtSlot(int)
4181+
def labelOriginFlagChanged(self, _:int = 0) -> None:
4182+
plus.stock.coffee_label_normal_order = self.label_origin_flag.isChecked()
4183+
self.populatePlusCoffeeBlendCombos() # update the plus stock popups to display the correct bean label format
4184+
41714185
@pyqtSlot(int)
41724186
def roastpropertiesAutoOpenChanged(self, _:int = 0) -> None:
41734187
if self.roastpropertiesAutoOpen.isChecked():

src/plus/stock.py

+50-53
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252

5353
stock_cache_path = getDirectory(config.stock_cache)
5454

55+
# coffee label format is either
56+
# "<origin> <picked>, <label>" (if coffee_label_normal_order=True)
57+
# "<label>, <origin> <picked>" (if coffee_label_normal_order=False)
58+
# NOTE: picked is only added if needed to discriminate to other coffees within this stock
59+
coffee_label_normal_order:bool = True # defaults to origin first if True
60+
5561

5662
# stock data structures
5763

@@ -511,7 +517,6 @@ def getCoffeeId(coffee:Tuple[str, Tuple[Coffee, StockItem]]) -> str:
511517
def getCoffeesLabels(coffees:List[Tuple[str, Tuple[Coffee, StockItem]]]) -> List[str]:
512518
return [getCoffeeLabel(c) for c in coffees]
513519

514-
515520
def coffee2beans(c:Coffee) -> str:
516521
origin = ''
517522
try:
@@ -520,12 +525,7 @@ def coffee2beans(c:Coffee) -> str:
520525
origin = QApplication.translate('Countries', origin_str)
521526
except Exception: # pylint: disable=broad-except
522527
pass
523-
if 'label' in c:
524-
label = c['label']
525-
if origin:
526-
label = f' {label}'
527-
else:
528-
label = ''
528+
label = c.get('label', '')
529529
processing = ''
530530
try:
531531
processing_str = c['processing'].strip() # pyright:ignore[reportTypedDictNotRequiredAccess]
@@ -581,18 +581,32 @@ def coffee2beans(c:Coffee) -> str:
581581
except Exception: # pylint: disable=broad-except
582582
pass
583583
if picked is not None and not bool(landed):
584-
year = f', {picked:d}'
584+
year = f'{picked:d}'
585585
elif landed is not None and not bool(picked):
586-
year = f', {landed:d}'
586+
year = f'{landed:d}'
587587
elif picked is not None and landed is not None:
588588
if picked == landed or landed <= picked:
589-
year = f', {picked:d}'
589+
year = f'{picked:d}'
590590
else:
591-
year = f', {picked:d}/{landed:d}'
591+
year = f'{picked:d}/{landed:d}'
592592
except Exception: # pylint: disable=broad-except
593593
pass
594-
return f'{origin}{label}{bean}{year}'
595-
594+
if origin == '':
595+
if year == '':
596+
return f'{label}{bean}'
597+
return f'{label}{bean}, {year}'
598+
if coffee_label_normal_order:
599+
if year == '':
600+
return f'{origin} {label}{bean}'
601+
return f'{origin} {label}{bean}, {year}'
602+
if year == '':
603+
return f'{label}{bean}, {origin}'
604+
return f'{label}{bean}, {origin} {year}'
605+
606+
# returns coffee label in the form
607+
# "<origin> <picked>, <label>" (if coffee_label_normal_order=True)
608+
# "<label>, <origin> <picked>" (if coffee_label_normal_order=False)
609+
# NOTE: picked is only added if needed to discriminate to other coffees within this stock
596610
def coffeeLabel(c:Coffee) -> str:
597611
origin = ''
598612
try:
@@ -603,23 +617,28 @@ def coffeeLabel(c:Coffee) -> str:
603617
)
604618
except Exception: # pylint: disable=broad-except
605619
pass
606-
if origin != '':
607-
try:
608-
if 'crop_date' in c and has_duplicate_origin_label(c):
609-
cy = c['crop_date']
610-
if (
611-
'picked' in cy
612-
and len(cy['picked']) > 0
613-
and cy['picked'][0] is not None
614-
):
615-
origin += f" {cy['picked'][0]:d}"
616-
except Exception as e: # pylint: disable=broad-except
617-
_log.exception(e)
618-
origin = f'{origin}, '
619-
return f"{origin}{c.get('label', '')}"
620-
621-
# returns a dict with all coffees with stock associated as string of the form "<origin> <picked>, <label>"
620+
try:
621+
if 'crop_date' in c and has_duplicate_origin_label(c):
622+
cy = c['crop_date']
623+
if (
624+
'picked' in cy
625+
and len(cy['picked']) > 0
626+
and cy['picked'][0] is not None
627+
):
628+
origin += f" {cy['picked'][0]:d}"
629+
except Exception as e: # pylint: disable=broad-except
630+
_log.exception(e)
631+
if origin == '':
632+
return c.get('label', '')
633+
if coffee_label_normal_order:
634+
return f"{origin}, {c.get('label', '')}"
635+
return f"{c.get('label', '')}, {origin}"
636+
637+
# returns a dict with all coffees with stock associated as string of the form
638+
# "<origin> <picked>, <label>" (if coffee_label_normal_order=True)
639+
# "<label>, <origin> <picked>" (if coffee_label_normal_order=False)
622640
# associated to their hr_id
641+
# NOTE: picked is only added if needed to discriminate to other coffees within this stock
623642
def getCoffeeLabels() -> Dict[str, str]:
624643
try:
625644
stock_semaphore.acquire(1)
@@ -663,29 +682,7 @@ def getCoffees(weight_unit_idx:int, store:Optional[str]=None) -> List[Tuple[str,
663682
res = {}
664683
for c in stock['coffees']:
665684
try:
666-
origin = ''
667-
try:
668-
origin_str = c['origin'].strip() # pyright:ignore[reportTypedDictNotRequiredAccess]
669-
if len(origin_str) > 0 and origin_str != 'null':
670-
origin = QApplication.translate(
671-
'Countries', origin_str
672-
)
673-
except Exception: # pylint: disable=broad-except
674-
pass
675-
if origin != '':
676-
try:
677-
if 'crop_date' in c and has_duplicate_origin_label(c):
678-
cy = c['crop_date']
679-
if (
680-
'picked' in cy
681-
and len(cy['picked']) > 0
682-
and cy['picked'][0] is not None
683-
):
684-
origin += f" {cy['picked'][0]:d}"
685-
except Exception as e: # pylint: disable=broad-except
686-
_log.exception(e)
687-
origin = f'{origin}, '
688-
label = c.get('label', '')
685+
coffee_label = coffeeLabel(c)
689686
default_unit = c.get('default_unit', None)
690687
if 'stock' in c:
691688
for s in c['stock']:
@@ -703,7 +700,7 @@ def getCoffees(weight_unit_idx:int, store:Optional[str]=None) -> List[Tuple[str,
703700
# is available in several locations
704701
loc = '' if store else f'{location}, '
705702
res[
706-
f'{origin}{label} [{loc}{renderAmount(amount,default_unit,weight_unit_idx)}]'
703+
f'{coffee_label} [{loc}{renderAmount(amount,default_unit,weight_unit_idx)}]'
707704
] = (c, s)
708705
except Exception as e: # pylint: disable=broad-except
709706
_log.exception(e)

0 commit comments

Comments
 (0)