From e8f3613773b9b80e9e045ef221043ab00de0cd36 Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Thu, 4 Jul 2024 16:28:36 -0400 Subject: [PATCH 01/11] test --- src/main/python/main/ayab/knitprogress.py | 111 +++++++++++++--------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index b295b0e3..baab6326 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -19,9 +19,10 @@ # https://github.com/AllYarnsAreBeautiful/ayab-desktop from __future__ import annotations -from PySide6.QtCore import QCoreApplication, QRect, QSize +from PySide6.QtCore import QCoreApplication, QRect, QSize, Qt from PySide6.QtWidgets import QTableWidget, QTableWidgetItem, QLabel, QHeaderView -from typing import TYPE_CHECKING, Optional, cast +from PySide6.QtGui import QBrush, QColor +from typing import TYPE_CHECKING, Optional, cast, List if TYPE_CHECKING: from .ayab import GuiMain @@ -48,7 +49,7 @@ def __init__(self, parent: GuiMain): self.verticalHeader().setSectionResizeMode( QHeaderView.ResizeMode.ResizeToContents ) - self.verticalHeader().setVisible(False) + # self.verticalHeader().setVisible(False) self.setColumnCount(6) for r in range(6): blank = QTableWidgetItem() @@ -61,7 +62,7 @@ def start(self) -> None: self.clearContents() self.clearSelection() self.setRowCount(0) - self.horizontalHeader().setSectionHidden(5, False) + # self.horizontalHeader().setSectionHidden(5, False) self.setCurrentCell(-1, -1) self.color = True @@ -99,59 +100,73 @@ def update_progress( tr_ = QCoreApplication.translate row, swipe = divmod(status.line_number, row_multiplier) - columns = [] + columns: List[QTableWidgetItem] = [] + info_text = "" + info_header = QTableWidgetItem() + # row "Row [1]" + info_text= (tr_("KnitProgress", "Row") + " " + str(status.current_row)) - # row - columns.append(tr_("KnitProgress", "Row") + " " + str(status.current_row)) - - # pass - columns.append(tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) + # pass, see Mode object. "Pass [1,2,3]" + if row_multiplier == 1: + info_text= info_text+(" "+tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) - # color + # color "Color [A,B,C,D]" if status.color_symbol == "": self.color = False else: self.color = True - coltext = tr_("KnitProgress", "Color") + " " + status.color_symbol - columns.append(coltext) - + info_text = info_text + " " + tr_("KnitProgress", "Color") + " " + status.color_symbol + bgColor = QColor(f"#{status.color:06x}") + # Ensure text is readable + if bgColor.lightness() > 128: + bgColor.setHsl(bgColor.hslHue(),bgColor.hslSaturation(),128) + info_header.setForeground(QBrush(bgColor)) + + # Carriage & Direction "[K,L,G] [<-,->]" carriage = status.carriage_type direction = status.carriage_direction - columns.append(carriage.symbol + " " + direction.symbol) + info_text= info_text +(" "+carriage.symbol + " " + direction.symbol) + + print(info_text) + info_header.setText(info_text) # graph line of stitches midline = len(status.bits) - midline - table_text = ( - "" - ) for c in range(0, midline): - table_text += self.__stitch( - status.color, cast(bool, status.bits[c]), status.alt_color - ) - table_text += "
" - left_side = QLabel(table_text) - - table_text = ( - "" - ) - for c in range(midline, len(status.bits)): - table_text += self.__stitch( - status.color, cast(bool, status.bits[c]), status.alt_color - ) - table_text += "
" - right_side = QLabel(table_text) + columns.append(self.__stitch( + status.color, cast(bool, status.bits[c]), status.alt_color, self.orange + )) + + # if we are only working on the right side, midline is negative. + green_start= midline + if green_start < 0: + green_start=0 + for c in range(green_start, len(status.bits)): + columns.append(self.__stitch( + status.color, cast(bool, status.bits[c]), status.alt_color, self.green + )) self.insertRow(0) + if self.columnCount() != len(columns): + self.setColumnCount(len(columns)) + self.setVerticalHeaderItem(0,info_header) for i, col in enumerate(columns): - self.setItem(0, i, self.__item(col)) + self.setItem(0, i, col) + if i < midline: + header = QTableWidgetItem(f"{(midline)-(i)}") + header.font().setBold(True) + header.setForeground(QBrush(QColor(f"#{self.orange:06x}"))) + header.setTextAlignment(Qt.AlignmentFlag.AlignCenter) + self.setHorizontalHeaderItem(i,header) + else: + header = QTableWidgetItem(f"{(i+1)-(midline)}") + header.setForeground(QBrush(QColor(f"#{self.green:06x}"))) + header.setTextAlignment(Qt.AlignmentFlag.AlignCenter) + self.setHorizontalHeaderItem(i,header) + # self.horizontalHeaderItem(i).setText((i)-(midline+info_columns)) n_cols = len(columns) - self.setCellWidget(0, n_cols, left_side) - self.setCellWidget(0, n_cols + 1, right_side) - if row_multiplier == 1: - self.hideColumn(1) + print(n_cols) if n_cols < 4: self.hideColumn(5) self.resizeColumnsToContents() @@ -165,13 +180,15 @@ def __item(self, text: str) -> QTableWidgetItem: item = QTableWidgetItem(text) return item - def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None) -> str: - # FIXME: borders are not visible - text = "" + if bg_color is not None: + stitch.setBackground(QBrush(QColor(f"#{bg_color:06x}"))) + # text += "dotted;" + return stitch From 92c9380b8cd53413654e78a6d7349e4b549dbbcf Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Thu, 4 Jul 2024 17:42:53 -0400 Subject: [PATCH 02/11] bg coloring for current color label --- src/main/python/main/ayab/engine/control.py | 1 + src/main/python/main/ayab/engine/engine.py | 10 +++----- src/main/python/main/ayab/engine/status.py | 2 ++ src/main/python/main/ayab/progressbar.py | 26 ++++++++++++-------- src/main/python/main/ayab/signal_receiver.py | 2 +- src/main/python/main/ayab/signal_sender.py | 4 +-- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/main/python/main/ayab/engine/control.py b/src/main/python/main/ayab/engine/control.py index 6c9fb694..0f290f1a 100644 --- a/src/main/python/main/ayab/engine/control.py +++ b/src/main/python/main/ayab/engine/control.py @@ -243,6 +243,7 @@ def cnf_line_API6(self, line_number: int) -> bool: return True # pattern finished def __update_status(self, line_number: int, color: int, bits: bitarray) -> None: + self.status.total_rows = self.pat_height self.status.current_row = self.pat_row + 1 self.status.line_number = line_number if self.inf_repeat: diff --git a/src/main/python/main/ayab/engine/engine.py b/src/main/python/main/ayab/engine/engine.py index 3ae3bea2..805d712b 100644 --- a/src/main/python/main/ayab/engine/engine.py +++ b/src/main/python/main/ayab/engine/engine.py @@ -142,9 +142,9 @@ def knit_config(self, image: Image.Image) -> None: self.pattern.alignment = self.config.alignment # update progress bar - self.emit_progress_bar_updater( - self.config.start_row + 1, self.pattern.pat_height, 0, "" - ) + data = Status() + data.copy(self.status) + self.emit_progress_bar_updater(data) # switch to status tab # if self.config.continuous_reporting: @@ -214,9 +214,7 @@ def __handle_status(self) -> None: self.control.midline, self.config.auto_mirror, ) - self.emit_progress_bar_updater( - data.current_row, self.pattern.pat_height, data.repeats, data.color_symbol - ) + self.emit_progress_bar_updater(data) def cancel(self) -> None: self.__canceled = True diff --git a/src/main/python/main/ayab/engine/status.py b/src/main/python/main/ayab/engine/status.py index f8b11c4b..511e5812 100644 --- a/src/main/python/main/ayab/engine/status.py +++ b/src/main/python/main/ayab/engine/status.py @@ -165,6 +165,8 @@ def copy(self, status: Status) -> None: self.carriage_type = status.carriage_type self.carriage_position = status.carriage_position self.carriage_direction = status.carriage_direction + self.total_rows = status.total_rows + self.mirror = status.mirror def parse_device_state_API6(self, state: Any, msg: bytes) -> None: if not (self.active): diff --git a/src/main/python/main/ayab/progressbar.py b/src/main/python/main/ayab/progressbar.py index e45543c6..3530c573 100644 --- a/src/main/python/main/ayab/progressbar.py +++ b/src/main/python/main/ayab/progressbar.py @@ -20,10 +20,11 @@ from __future__ import annotations from typing import TYPE_CHECKING +from PySide6.QtGui import QColor if TYPE_CHECKING: from .ayab import GuiMain - from .engine.status import ColorSymbolType + from .engine.status import Status class ProgressBar(object): @@ -40,23 +41,22 @@ def reset(self) -> None: self.total = -1 self.repeats = -1 self.color = "" + self.backgroundColor = 0xFFFFFF self.__row_label.setText("") self.__color_label.setText("") self.__status_label.setText("") def update( self, - row: int, - total: int = 0, - repeats: int = 0, - color_symbol: ColorSymbolType = "", + status: Status ) -> bool: - if row < 0: + if status.current_row < 0: return False - self.row = row - self.total = total - self.repeats = repeats - self.color = color_symbol + self.row = status.current_row + self.total = status.total_rows + self.repeats = status.repeats + self.color = status.color_symbol + self.backgroundColor = status.color self.refresh() return True @@ -69,6 +69,12 @@ def refresh(self) -> None: color_text = "" else: color_text = "Color " + self.color + bgColor = QColor.fromRgb(self.backgroundColor) + if bgColor.lightness() < 128: + fgColor = 0xffffff + else: fgColor = 0x000000 + self.__color_label.setStyleSheet("QLabel {background-color: "+f"#{self.backgroundColor:06x}"+f";color:#{fgColor:06x}"+";}") + self.__color_label.setText(color_text) # Update labels diff --git a/src/main/python/main/ayab/signal_receiver.py b/src/main/python/main/ayab/signal_receiver.py index 187392ef..226645cb 100644 --- a/src/main/python/main/ayab/signal_receiver.py +++ b/src/main/python/main/ayab/signal_receiver.py @@ -43,7 +43,7 @@ class SignalReceiver(QObject): # signals are defined as class attributes which are # over-ridden by instance attributes with the same name start_row_updater = Signal(int) - progress_bar_updater = Signal(int, int, int, str) + progress_bar_updater = Signal(Status) knit_progress_updater = Signal(Status, int, int, bool) notifier = Signal(str, bool) # statusbar_updater = Signal('QString', bool) diff --git a/src/main/python/main/ayab/signal_sender.py b/src/main/python/main/ayab/signal_sender.py index 973eab38..064caf1e 100644 --- a/src/main/python/main/ayab/signal_sender.py +++ b/src/main/python/main/ayab/signal_sender.py @@ -50,10 +50,10 @@ def emit_start_row_updater(self, start_row: int) -> None: self.__signal_receiver.start_row_updater.emit(start_row) def emit_progress_bar_updater( - self, row: int, total: int, repeats: int, color_symbol: ColorSymbolType + self, status: Status ) -> None: self.__signal_receiver.progress_bar_updater.emit( - row, total, repeats, color_symbol + status ) def emit_knit_progress_updater( From 8ca4b01d118076f621977a60ee9a64e66ccf9c50 Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Mon, 8 Jul 2024 08:49:27 -0400 Subject: [PATCH 03/11] clean up test code --- src/main/python/main/ayab/knitprogress.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index baab6326..9306589b 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -49,12 +49,6 @@ def __init__(self, parent: GuiMain): self.verticalHeader().setSectionResizeMode( QHeaderView.ResizeMode.ResizeToContents ) - # self.verticalHeader().setVisible(False) - self.setColumnCount(6) - for r in range(6): - blank = QTableWidgetItem() - blank.setSizeHint(QSize(0, 0)) - self.setHorizontalHeaderItem(r, blank) self.previousStatus: Optional[Status] = None self.scene = parent.scene @@ -62,7 +56,6 @@ def start(self) -> None: self.clearContents() self.clearSelection() self.setRowCount(0) - # self.horizontalHeader().setSectionHidden(5, False) self.setCurrentCell(-1, -1) self.color = True @@ -164,9 +157,7 @@ def update_progress( header.setForeground(QBrush(QColor(f"#{self.green:06x}"))) header.setTextAlignment(Qt.AlignmentFlag.AlignCenter) self.setHorizontalHeaderItem(i,header) - # self.horizontalHeaderItem(i).setText((i)-(midline+info_columns)) n_cols = len(columns) - print(n_cols) if n_cols < 4: self.hideColumn(5) self.resizeColumnsToContents() @@ -190,5 +181,4 @@ def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_co else: if bg_color is not None: stitch.setBackground(QBrush(QColor(f"#{bg_color:06x}"))) - # text += "dotted;" return stitch From bb92a2c0b2ed0929bf8e2e292b38d892d16b8765 Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Mon, 8 Jul 2024 09:05:12 -0400 Subject: [PATCH 04/11] remove unused imports --- src/main/python/main/ayab/knitprogress.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index 9306589b..663cb0ba 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -19,8 +19,8 @@ # https://github.com/AllYarnsAreBeautiful/ayab-desktop from __future__ import annotations -from PySide6.QtCore import QCoreApplication, QRect, QSize, Qt -from PySide6.QtWidgets import QTableWidget, QTableWidgetItem, QLabel, QHeaderView +from PySide6.QtCore import QCoreApplication, QRect, Qt +from PySide6.QtWidgets import QTableWidget, QTableWidgetItem, QHeaderView from PySide6.QtGui import QBrush, QColor from typing import TYPE_CHECKING, Optional, cast, List From 9fcfa3804f5cc2a1fabccf7072f9c674e30f9280 Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Mon, 8 Jul 2024 09:19:00 -0400 Subject: [PATCH 05/11] make status update consistent --- src/main/python/main/ayab/ayab.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/python/main/ayab/ayab.py b/src/main/python/main/ayab/ayab.py index 49ca5e4b..010c0ecc 100644 --- a/src/main/python/main/ayab/ayab.py +++ b/src/main/python/main/ayab/ayab.py @@ -176,9 +176,7 @@ def set_image_dimensions(self) -> None: width, height = self.scene.ayabimage.image.size self.engine.config.update_needles() # in case machine width changed self.engine.config.set_image_dimensions(width, height) - self.progbar.row = self.scene.row_progress + 1 - self.progbar.total = height - self.progbar.refresh() + self.progbar.update(self.engine.status) self.notify( QCoreApplication.translate("Scene", "Image dimensions") + f": {width} x {height}", @@ -191,8 +189,9 @@ def reverse_image(self) -> None: self.scene.reverse() def update_start_row(self, start_row: int) -> None: - self.progbar.update(start_row) self.scene.row_progress = start_row + self.engine.status.current_row = start_row + self.progbar.update(self.engine.status) def notify(self, text: str, log: bool = True) -> None: """Update the notification field.""" From a731b6691a1a6ee4429fce67640650137a2a86fe Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Mon, 8 Jul 2024 09:40:41 -0400 Subject: [PATCH 06/11] break out row header creation --- src/main/python/main/ayab/knitprogress.py | 58 +++++++++++------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index 663cb0ba..eee3a19d 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -89,39 +89,13 @@ def update_progress( if status.current_row < 0: return - # else - tr_ = QCoreApplication.translate - row, swipe = divmod(status.line_number, row_multiplier) columns: List[QTableWidgetItem] = [] - info_text = "" - info_header = QTableWidgetItem() - # row "Row [1]" - info_text= (tr_("KnitProgress", "Row") + " " + str(status.current_row)) - - # pass, see Mode object. "Pass [1,2,3]" - if row_multiplier == 1: - info_text= info_text+(" "+tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) - - # color "Color [A,B,C,D]" if status.color_symbol == "": self.color = False else: self.color = True - info_text = info_text + " " + tr_("KnitProgress", "Color") + " " + status.color_symbol - bgColor = QColor(f"#{status.color:06x}") - # Ensure text is readable - if bgColor.lightness() > 128: - bgColor.setHsl(bgColor.hslHue(),bgColor.hslSaturation(),128) - info_header.setForeground(QBrush(bgColor)) - - # Carriage & Direction "[K,L,G] [<-,->]" - carriage = status.carriage_type - direction = status.carriage_direction - info_text= info_text +(" "+carriage.symbol + " " + direction.symbol) - - print(info_text) - info_header.setText(info_text) + info_header = self.format_row_header_text(status, row_multiplier) # graph line of stitches midline = len(status.bits) - midline @@ -167,9 +141,33 @@ def update_progress( # update bar in Scene self.scene.row_progress = status.current_row - def __item(self, text: str) -> QTableWidgetItem: - item = QTableWidgetItem(text) - return item + def format_row_header_text(self, status: Status, row_multiplier: int) -> QTableWidgetItem: + tr_ = QCoreApplication.translate + info_header = QTableWidgetItem() + info_text = "" + row, swipe = divmod(status.line_number, row_multiplier) + # row "Row [1]" + info_text= (tr_("KnitProgress", "Row") + " " + str(status.current_row)) + + # pass, see Mode object. "Pass [1,2,3]" + if row_multiplier == 1: + info_text= info_text+(" "+tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) + + # color "Color [A,B,C,D]" + if self.color is True: + info_text = info_text + " " + tr_("KnitProgress", "Color") + " " + status.color_symbol + background_color = QColor(f"#{status.color:06x}") + # Ensure text is readable + if background_color.lightness() > 128: + background_color.setHsl(background_color.hslHue(),background_color.hslSaturation(),128) + info_header.setForeground(QBrush(background_color)) + + # Carriage & Direction "[K,L,G] [<-,->]" + carriage = status.carriage_type + direction = status.carriage_direction + info_text= info_text +(" "+carriage.symbol + " " + direction.symbol) + info_header.setText(info_text) + return info_header def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[int] = None) -> QTableWidgetItem: stitch = QTableWidgetItem() From 42f09c21b13d9df3906fb44bb5486f25163685ab Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Mon, 8 Jul 2024 09:40:53 -0400 Subject: [PATCH 07/11] fix variable naming --- src/main/python/main/ayab/knitprogress.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index eee3a19d..e8114039 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -172,8 +172,8 @@ def format_row_header_text(self, status: Status, row_multiplier: int) -> QTableW def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[int] = None) -> QTableWidgetItem: stitch = QTableWidgetItem() if bit: - bgColor = QColor(f"#{color:06x}") - stitch.setBackground(bgColor) + background_color = QColor(f"#{color:06x}") + stitch.setBackground(background_color) elif alt_color is not None: stitch.setBackground(QBrush(QColor(f"#{alt_color:06x}"))) else: From 3381902c11e6fad3df7b4acb46d307ae7f31bd1e Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Sun, 14 Jul 2024 22:32:13 -0400 Subject: [PATCH 08/11] make progress size adjustable, add header --- src/main/python/main/ayab/knitprogress.py | 100 +++++++++++++++------- src/main/python/main/ayab/preferences.py | 50 ++++++++--- 2 files changed, 109 insertions(+), 41 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index e8114039..05d32830 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -23,9 +23,11 @@ from PySide6.QtWidgets import QTableWidget, QTableWidgetItem, QHeaderView from PySide6.QtGui import QBrush, QColor from typing import TYPE_CHECKING, Optional, cast, List +from math import floor if TYPE_CHECKING: from .ayab import GuiMain + from .preferences import Preferences from .engine.status import Status @@ -44,10 +46,11 @@ def __init__(self, parent: GuiMain): super().__init__(parent.ui.graphics_splitter) self.clear() self.setRowCount(0) + self.__prefs: Preferences = parent.prefs self.setGeometry(QRect(0, 0, 700, 220)) self.setContentsMargins(1, 1, 1, 1) self.verticalHeader().setSectionResizeMode( - QHeaderView.ResizeMode.ResizeToContents + QHeaderView.ResizeMode.Fixed ) self.previousStatus: Optional[Status] = None self.scene = parent.scene @@ -95,81 +98,116 @@ def update_progress( self.color = False else: self.color = True - info_header = self.format_row_header_text(status, row_multiplier) - # graph line of stitches + midline = self.load_columns_from_status(status, midline, columns) + + # For the top row (row idx 0), we show the row header as "To Be Selected", + # When we show a new row, we recover the header info and recombine it with its row (now row idx 2) + self.make_row_with_spacer() + + self.instantiate_row_from_columns(midline, columns) + if self.columnCount() != len(columns): + self.setColumnCount(len(columns)) + n_cols = len(columns) + if n_cols < 4: + self.hideColumn(5) + + self.previousStatus = status + self.previous_row_mulitplier = row_multiplier + + # update bar in Scene + self.scene.row_progress = status.current_row + + def load_columns_from_status(self, status: Status, midline: int, columns: List[QTableWidgetItem]) -> int: midline = len(status.bits) - midline for c in range(0, midline): columns.append(self.__stitch( - status.color, cast(bool, status.bits[c]), status.alt_color, self.orange + QColor(f"#{status.color:06x}"), cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(midline-c, self.orange) )) # if we are only working on the right side, midline is negative. - green_start= midline - if green_start < 0: - green_start=0 + green_start = midline + if green_start < 0: + green_start = 0 for c in range(green_start, len(status.bits)): columns.append(self.__stitch( - status.color, cast(bool, status.bits[c]), status.alt_color, self.green + QColor(f"#{status.color:06x}"), cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(c-green_start, self.green) )) - self.insertRow(0) - if self.columnCount() != len(columns): - self.setColumnCount(len(columns)) - self.setVerticalHeaderItem(0,info_header) + return midline + + def instantiate_row_from_columns(self, midline: int, columns: List[QTableWidgetItem]) -> None: + self.setVerticalHeaderItem(0, QTableWidgetItem("To Be Selected")) for i, col in enumerate(columns): self.setItem(0, i, col) + self.setColumnWidth(i, cast(int, self.__prefs.settings.value("lower_display_stitch_width"))) + # when width is under 20, the column numbers are unreadable. + if self.columnWidth(i) < 20: + self.horizontalHeader().setVisible(False) + continue + self.horizontalHeader().setVisible(True) if i < midline: header = QTableWidgetItem(f"{(midline)-(i)}") header.font().setBold(True) header.setForeground(QBrush(QColor(f"#{self.orange:06x}"))) header.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.setHorizontalHeaderItem(i,header) + self.setHorizontalHeaderItem(i, header) + self.horizontalHeader().setMinimumSectionSize(0) else: header = QTableWidgetItem(f"{(i+1)-(midline)}") header.setForeground(QBrush(QColor(f"#{self.green:06x}"))) header.setTextAlignment(Qt.AlignmentFlag.AlignCenter) - self.setHorizontalHeaderItem(i,header) - n_cols = len(columns) - if n_cols < 4: - self.hideColumn(5) - self.resizeColumnsToContents() + self.setHorizontalHeaderItem(i, header) - self.previousStatus = status - - # update bar in Scene - self.scene.row_progress = status.current_row - - def format_row_header_text(self, status: Status, row_multiplier: int) -> QTableWidgetItem: + def make_row_with_spacer(self) -> None: + self.removeRow(1) + self.insertRow(0) + self.insertRow(1) + if self.rowCount() > 2: + self.setVerticalHeaderItem(2, self.format_row_header_text(self.previousStatus, self.previous_row_mulitplier)) + self.verticalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed) + self.verticalHeader().setMinimumSectionSize(0) + self.verticalHeader().resizeSection(1, 5) + + def format_row_header_text(self, status: Optional[Status], row_multiplier: int) -> QTableWidgetItem: + if status is None: + return QTableWidgetItem("") tr_ = QCoreApplication.translate info_header = QTableWidgetItem() info_text = "" row, swipe = divmod(status.line_number, row_multiplier) # row "Row [1]" - info_text= (tr_("KnitProgress", "Row") + " " + str(status.current_row)) + info_text = (tr_("KnitProgress", "Row") + " " + str(status.current_row)) # pass, see Mode object. "Pass [1,2,3]" if row_multiplier == 1: - info_text= info_text+(" "+tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) + info_text = info_text+(" "+tr_("KnitProgress", "Pass") + " " + str(swipe + 1)) - # color "Color [A,B,C,D]" + # color "Color [A,B,C,D]" if self.color is True: info_text = info_text + " " + tr_("KnitProgress", "Color") + " " + status.color_symbol background_color = QColor(f"#{status.color:06x}") # Ensure text is readable if background_color.lightness() > 128: - background_color.setHsl(background_color.hslHue(),background_color.hslSaturation(),128) + background_color.setHsl(background_color.hslHue(), background_color.hslSaturation(), 128) info_header.setForeground(QBrush(background_color)) # Carriage & Direction "[K,L,G] [<-,->]" carriage = status.carriage_type direction = status.carriage_direction - info_text= info_text +(" "+carriage.symbol + " " + direction.symbol) + info_text = info_text + (" "+carriage.symbol + " " + direction.symbol) info_header.setText(info_text) return info_header - def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[int] = None) -> QTableWidgetItem: + def __alternate_bg_colors(self, position: int, color: int, frequency: int = 10) -> QColor: + background_color = QColor(f"#{color:06x}") + bg_color_alternate = floor(position/frequency) % 2 + if bg_color_alternate > 0: + background_color.setHsl(floor(background_color.hslHue()*.85), floor(background_color.hslSaturation()*.85), background_color.lightness()) + return background_color + + def __stitch(self, color: QColor, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[QColor] = None) -> QTableWidgetItem: stitch = QTableWidgetItem() if bit: background_color = QColor(f"#{color:06x}") @@ -178,5 +216,5 @@ def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_co stitch.setBackground(QBrush(QColor(f"#{alt_color:06x}"))) else: if bg_color is not None: - stitch.setBackground(QBrush(QColor(f"#{bg_color:06x}"))) + stitch.setBackground(QBrush(bg_color)) return stitch diff --git a/src/main/python/main/ayab/preferences.py b/src/main/python/main/ayab/preferences.py index 1c6c3a12..d0e032de 100644 --- a/src/main/python/main/ayab/preferences.py +++ b/src/main/python/main/ayab/preferences.py @@ -27,7 +27,7 @@ from __future__ import annotations from PySide6.QtCore import Qt, QSettings, QCoreApplication -from PySide6.QtWidgets import QDialog, QFormLayout, QLabel, QCheckBox, QComboBox +from PySide6.QtWidgets import QDialog, QFormLayout, QLabel, QCheckBox, QComboBox, QSpinBox from .prefs_gui import Ui_Prefs from .signal_sender import SignalSender @@ -67,11 +67,12 @@ def str2bool(qvariant: str | bool) -> bool: "quiet_mode", "disable_hardware_beep", ] +PreferencesDictIntKeys: TypeAlias = Literal["lower_display_stitch_width"] PreferencesDictObjKeys: TypeAlias = Literal[ "aspect_ratio", "default_alignment", "default_knitting_mode", "machine" ] PreferencesDictKeys: TypeAlias = Literal[ - PreferencesDictBoolKeys, PreferencesDictObjKeys, "language" + PreferencesDictBoolKeys, PreferencesDictObjKeys, PreferencesDictIntKeys, "language" ] PreferencesDict = TypedDict( @@ -87,6 +88,7 @@ def str2bool(qvariant: str | bool) -> bool: "quiet_mode": type[bool], "disable_hardware_beep": type[bool], "language": type[Language], + "lower_display_stitch_width": type[int] }, ) @@ -116,13 +118,14 @@ class Preferences(SignalSender): "quiet_mode": bool, "disable_hardware_beep": bool, "language": Language, + "lower_display_stitch_width": int } def __init__(self, parent: GuiMain): super().__init__(parent.signal_receiver) self.parent = parent self.languages = Language(self.parent.app_context) - self.settings = QSettings() + self.settings: QSettings = QSettings() self.settings.setFallbacksEnabled(False) self.refresh() @@ -148,23 +151,23 @@ def value(self, var: PreferencesDictKeys) -> Any: else: return self.default_value(var) - def convert(self, var: PreferencesDictKeys) -> Callable[[T], Any]: + def convert(self, var: PreferencesDictKeys) -> Callable[[object], Any]: try: cls = self.variables[var] except KeyError: return str # else if cls == bool: - return cast(Callable[[T], Any], str2bool) + return cast(Callable[[object], Any], str2bool) # else if cls == Language: return str # else - return cast(Callable[[T], Any], int) + return cast(Callable[[object], Any], int) def default_value( self, var: PreferencesDictKeys - ) -> Optional[bool | str | Literal[0]]: + ) -> Optional[bool | str | int | Literal[0]]: try: cls = self.variables[var] except KeyError: @@ -175,6 +178,8 @@ def default_value( # else if cls == Language: return self.languages.default_language() + if cls == int: + return 20 # else return 0 @@ -226,6 +231,8 @@ def __make_widget(self, var: PreferencesDictKeys) -> PrefsWidgetTypes: cls = self.__prefs.variables[var] if cls == bool: return PrefsBoolWidget(self.__prefs, cast(PreferencesDictBoolKeys, var)) + elif cls == int: + return PrefsIntWidget(self.__prefs, cast(PreferencesDictIntKeys, var)) elif cls == Language: return PrefsLangWidget(self.__prefs) else: @@ -250,7 +257,7 @@ class PrefsBoolWidget(QCheckBox): def __init__(self, prefs: Preferences, var: PreferencesDictBoolKeys): super().__init__() - self.var = var + self.var: PreferencesDictBoolKeys = var self.prefs = prefs def connectChange(self) -> None: @@ -269,6 +276,29 @@ def refresh(self) -> None: self.setCheckState(Qt.CheckState.Unchecked) +class PrefsIntWidget(QSpinBox): + """Spinbox for Integer preferences setting. + + @author Sam Bonfante + @date July 2024 + """ + + def __init__(self, prefs: Preferences, var: PreferencesDictIntKeys): + super().__init__() + self.var: PreferencesDictIntKeys = var + self.prefs = prefs + self.setMinimum(2) + + def connectChange(self) -> None: + self.valueChanged.connect(self.update_setting) + + def update_setting(self, new_value: int) -> None: + self.prefs.settings.setValue(self.var, new_value) + + def refresh(self) -> None: + self.setValue(self.prefs.value(self.var)) + + class PrefsComboWidget(QComboBox): """ComboBox for categorical preferences setting. @@ -278,7 +308,7 @@ class PrefsComboWidget(QComboBox): def __init__(self, prefs: Preferences, var: PreferencesDictObjKeys): super().__init__() - self.var = var + self.var: PreferencesDictObjKeys = var self.prefs = prefs cls = self.prefs.variables[self.var] cls.add_items(self) @@ -315,4 +345,4 @@ def refresh(self) -> None: self.setCurrentIndex(self.findData(self.prefs.value("language"))) -PrefsWidgetTypes: TypeAlias = PrefsBoolWidget | PrefsLangWidget | PrefsComboWidget +PrefsWidgetTypes: TypeAlias = PrefsBoolWidget | PrefsLangWidget | PrefsComboWidget | PrefsIntWidget From ab49eab785dc46af53e747f5787519421928f14f Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Sun, 14 Jul 2024 23:15:26 -0400 Subject: [PATCH 09/11] fix color --- src/main/python/main/ayab/knitprogress.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/python/main/ayab/knitprogress.py b/src/main/python/main/ayab/knitprogress.py index 05d32830..5fb02fa9 100644 --- a/src/main/python/main/ayab/knitprogress.py +++ b/src/main/python/main/ayab/knitprogress.py @@ -123,7 +123,7 @@ def load_columns_from_status(self, status: Status, midline: int, columns: List[Q for c in range(0, midline): columns.append(self.__stitch( - QColor(f"#{status.color:06x}"), cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(midline-c, self.orange) + status.color, cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(midline-c, self.orange) )) # if we are only working on the right side, midline is negative. @@ -132,7 +132,7 @@ def load_columns_from_status(self, status: Status, midline: int, columns: List[Q green_start = 0 for c in range(green_start, len(status.bits)): columns.append(self.__stitch( - QColor(f"#{status.color:06x}"), cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(c-green_start, self.green) + status.color, cast(bool, status.bits[c]), status.alt_color, self.__alternate_bg_colors(c-green_start, self.green) )) return midline @@ -207,7 +207,7 @@ def __alternate_bg_colors(self, position: int, color: int, frequency: int = 10) background_color.setHsl(floor(background_color.hslHue()*.85), floor(background_color.hslSaturation()*.85), background_color.lightness()) return background_color - def __stitch(self, color: QColor, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[QColor] = None) -> QTableWidgetItem: + def __stitch(self, color: int, bit: bool, alt_color: Optional[int] = None, bg_color: Optional[QColor] = None) -> QTableWidgetItem: stitch = QTableWidgetItem() if bit: background_color = QColor(f"#{color:06x}") From 6c267e139dc4fb11a74e580c395502e132ded9ec Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Sun, 14 Jul 2024 23:16:38 -0400 Subject: [PATCH 10/11] consistent naming --- src/main/python/main/ayab/progressbar.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/python/main/ayab/progressbar.py b/src/main/python/main/ayab/progressbar.py index 3530c573..1cfdf728 100644 --- a/src/main/python/main/ayab/progressbar.py +++ b/src/main/python/main/ayab/progressbar.py @@ -56,7 +56,7 @@ def update( self.total = status.total_rows self.repeats = status.repeats self.color = status.color_symbol - self.backgroundColor = status.color + self.background_color = status.color self.refresh() return True @@ -69,11 +69,11 @@ def refresh(self) -> None: color_text = "" else: color_text = "Color " + self.color - bgColor = QColor.fromRgb(self.backgroundColor) - if bgColor.lightness() < 128: - fgColor = 0xffffff - else: fgColor = 0x000000 - self.__color_label.setStyleSheet("QLabel {background-color: "+f"#{self.backgroundColor:06x}"+f";color:#{fgColor:06x}"+";}") + bg_color = QColor.fromRgb(self.background_color) + if bg_color.lightness() < 128: + fg_color = 0xffffff + else: fg_color = 0x000000 + self.__color_label.setStyleSheet("QLabel {background-color: "+f"#{self.background_color:06x}"+f";color:#{fg_color:06x}"+";}") self.__color_label.setText(color_text) From 3bed1bc54e7cd1ef21b5291dfe58612b475b0104 Mon Sep 17 00:00:00 2001 From: Sam! Bonfante Date: Sun, 14 Jul 2024 23:17:44 -0400 Subject: [PATCH 11/11] missed a spot --- src/main/python/main/ayab/progressbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/python/main/ayab/progressbar.py b/src/main/python/main/ayab/progressbar.py index 1cfdf728..4d723bb5 100644 --- a/src/main/python/main/ayab/progressbar.py +++ b/src/main/python/main/ayab/progressbar.py @@ -41,7 +41,7 @@ def reset(self) -> None: self.total = -1 self.repeats = -1 self.color = "" - self.backgroundColor = 0xFFFFFF + self.background_color = 0xFFFFFF self.__row_label.setText("") self.__color_label.setText("") self.__status_label.setText("")