Skip to content

Commit

Permalink
- fixes the 30 ways to leave an Artisan dialog
Browse files Browse the repository at this point in the history
- lib updates
  • Loading branch information
MAKOMO committed Oct 30, 2024
1 parent abb3982 commit 9df1931
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 79 deletions.
2 changes: 1 addition & 1 deletion src/artisanlib/ble_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ def stop(self) -> None:
if self._ble_client is None:
ble.terminate_scan() # we stop ongoing scanning
self._disconnect()
del self._async_loop_thread # on this level the released object should be automatically collected by the GC
#del self._async_loop_thread # on this level the released object should be automatically collected by the GC
self._async_loop_thread = None
self._ble_client = None
self._connected_service_uuid = None
Expand Down
10 changes: 5 additions & 5 deletions src/artisanlib/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ def __init__(self, parent:Optional[QWidget], aw:'ApplicationWindow') -> None:
(cancelButton,'Cancel',QApplication.translate('Button','Cancel'))]:
self.setButtonTranslations(btn,txt,trans)

@pyqtSlot()
def cancelDialog(self) -> None:
# self.dialogbuttons.rejected.emit()
self.reject()

@staticmethod
def setButtonTranslations(btn: Optional['QPushButton'], txt:str, trans:str) -> None:
if btn is not None:
Expand All @@ -108,6 +103,11 @@ def setButtonTranslations(btn: Optional['QPushButton'], txt:str, trans:str) -> N
if txt != current_trans:
btn.setText(current_trans)

@pyqtSlot()
def cancelDialog(self) -> None: # ESC key
# self.reject() # this does not call any closeEvent in subclasses!
self.dialogbuttons.rejected.emit()

@pyqtSlot('QCloseEvent')
def closeEvent(self,_:Optional['QCloseEvent'] = None) -> None:
self.dialogbuttons.rejected.emit()
Expand Down
2 changes: 1 addition & 1 deletion src/artisanlib/modbusport.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def disconnect(self) -> None:
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
self._client = None
del self._asyncLoopThread
#del self._asyncLoopThread
self._asyncLoopThread = None

def clearCommError(self) -> None:
Expand Down
102 changes: 46 additions & 56 deletions src/artisanlib/roast_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ def keyPressEvent(self, event: Optional['QKeyEvent']) -> None:
self.coffeeinweightEdit.setText(f'{float2float(v):g}')
elif self.coffeeoutweightEdit.hasFocus():
self.coffeeoutweightEdit.setText(f'{float2float(v):g}')
else:
super().keyPressEvent(event)

def widgetWeight(self, widget:QLineEdit) -> None:
w = self.retrieveWeight()
Expand Down Expand Up @@ -1146,7 +1148,7 @@ def __init__(self, parent:QWidget, aw:'ApplicationWindow', activeTab:int = 0) ->

# connect the ArtisanDialog standard OK/Cancel buttons
self.dialogbuttons.accepted.connect(self.accept)
self.dialogbuttons.rejected.connect(self.cancel_dialog)
self.dialogbuttons.rejected.connect(self.closeEvent)

# container tare
self.tareComboBox = QComboBox()
Expand Down Expand Up @@ -2525,57 +2527,14 @@ def addRecentRoast(self, __:bool = False) -> None:
_, _, exc_tb = sys.exc_info()
self.aw.qmc.adderror((QApplication.translate('Error Message', 'Exception:') + ' addRecentRoast(): {0}').format(str(e)),getattr(exc_tb, 'tb_lineno', '?'))

# triggered if dialog is closed via its windows close box
# and called from accept if dialog is closed via OK
@pyqtSlot('QCloseEvent')
def closeEvent(self, _:Optional['QCloseEvent'] = None) -> None:
self.disconnecting = True
if self.acaia is not None:
try:
self.acaia.battery_changed_signal.disconnect()
self.acaia.weight_changed_signal.disconnect()
self.acaia.disconnected_signal.disconnect()
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
try:
#self.acaia.stop()
QTimer.singleShot(2,self.acaia.stop) # no delay on RoastProperties window close on Windows
self.updateWeightLCD('')
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
self.acaia = None
settings = QSettings()
#save window geometry
settings.setValue('RoastGeometry',self.saveGeometry())
self.aw.editGraphDlg_activeTab = self.TabWidget.currentIndex()
# self.aw.closeEventSettings() # save all app settings
self.aw.editgraphdialog = None
if self.stockWorker is not None and self.updateStockSignalConnection is not None:
self.stockWorker.updatedSignal.disconnect(self.updateStockSignalConnection)


# triggered via the cancel button
# called on CANCEL or WINDOW_CLOSE; reverts state and calls clean_up_and_close()
@pyqtSlot()
def cancel_dialog(self) -> None:
self.disconnecting = True
if self.acaia is not None:
try:
self.acaia.battery_changed_signal.disconnect()
self.acaia.weight_changed_signal.disconnect()
self.acaia.disconnected_signal.disconnect()
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
try:
self.acaia.stop()
self.updateWeightLCD('')
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
self.acaia = None
settings = QSettings()
#save window geometry
settings.setValue('RoastGeometry',self.saveGeometry())
self.aw.editGraphDlg_activeTab = self.TabWidget.currentIndex()
@pyqtSlot('QCloseEvent')
def closeEvent(self, _:Optional['QCloseEvent'] = None) -> None:

# restore
self.restoreAllEnergySettings()

self.aw.qmc.beans = self.org_beans
Expand All @@ -2601,9 +2560,34 @@ def cancel_dialog(self) -> None:

self.aw.qmc.roastpropertiesAutoOpenFlag = self.org_roastpropertiesAutoOpenFlag
self.aw.qmc.roastpropertiesAutoOpenDropFlag = self.org_roastpropertiesAutoOpenDropFlag
self.aw.editgraphdialog = None

self.reject()
self.clean_up()
super().reject()


# called on CANCEL and WindowClose from closeEvent(), and on OK from accept()
def clean_up(self) -> None:
self.disconnecting = True
if self.acaia is not None:
try:
self.acaia.battery_changed_signal.disconnect()
self.acaia.weight_changed_signal.disconnect()
self.acaia.disconnected_signal.disconnect()
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
try:
self.acaia.stop()
self.updateWeightLCD('')
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
self.acaia = None
settings = QSettings()
#save window geometry
settings.setValue('RoastGeometry',self.saveGeometry())
self.aw.editGraphDlg_activeTab = self.TabWidget.currentIndex()
self.aw.editgraphdialog = None
if self.stockWorker is not None and self.updateStockSignalConnection is not None:
self.stockWorker.updatedSignal.disconnect(self.updateStockSignalConnection)

# calcs volume (in ml) from density (in g/l) and weight (in g)
@staticmethod
Expand All @@ -2625,14 +2609,16 @@ def keyPressEvent(self, event: Optional['QKeyEvent']) -> None:
self.inWeight(True,overwrite=True) # we don't add to current reading but overwrite
elif self.weightoutedit.hasFocus():
self.outWeight(True,overwrite=True) # we don't add to current reading but overwrite
if key == 76 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl L on Roast tab => open volume calculator
elif key == 76 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl L on Roast tab => open volume calculator
self.volumeCalculatorTimer(True)
if key == 73 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl I on Roast tab => send scale weight to in-weight field
elif key == 73 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl I on Roast tab => send scale weight to in-weight field
self.inWeight(True)
if key == 79 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl O on Roast tab => send scale weight to out-weight field
elif key == 79 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl O on Roast tab => send scale weight to out-weight field
self.outWeight(True)
if key == 80 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl P on Roast tab => send scale weight to in-weight field
elif key == 80 and control_modifier and self.TabWidget.currentIndex() == 0: #ctrl P on Roast tab => send scale weight to in-weight field
self.resetScaleSet()
else:
super().keyPressEvent(event)

@pyqtSlot(int)
def tareChanged(self, i:int) -> None:
Expand Down Expand Up @@ -3643,7 +3629,10 @@ def energyTabSwitched(self, i:int) -> None:

@staticmethod
def validateText2Seconds(s:str) -> int:
return stringtoseconds(s) if len(s) > 0 else 0
try:
return stringtoseconds(s) if len(s) > 0 else 0
except Exception: # pylint: disable=broad-except
return 0

@staticmethod
def validateSeconds2Text(seconds:float) -> str:
Expand Down Expand Up @@ -5120,7 +5109,8 @@ def accept(self) -> None:
plus.queue.addRoast()
except Exception as e: # pylint: disable=broad-except
_log.exception(e)
self.close()
self.clean_up()
super().accept()

def getMeasuredvalues(self, title:str, func_updatefields:Callable[[],None],
fields:List[QLineEdit], loadEnergy:List[float], func_updateduration:Callable[[],None],
Expand Down
41 changes: 37 additions & 4 deletions src/plus/blend.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
QHeaderView, # @UnusedImport @Reimport @UnresolvedImport
)
from PyQt6.QtCore import Qt, pyqtSlot, QSize, QSettings # @UnusedImport @Reimport @UnresolvedImport
from PyQt6.QtGui import QIcon, QStandardItemModel # @UnusedImport @Reimport @UnresolvedImport
from PyQt6.QtGui import QKeySequence, QAction, QIcon, QStandardItemModel # @UnusedImport @Reimport @UnresolvedImport
# from PyQt6 import sip # @UnusedImport @Reimport @UnresolvedImport
except Exception: # pylint: disable=broad-except
#pylint: disable = E, W, R, C
Expand All @@ -49,7 +49,7 @@
QHeaderView, # @UnusedImport @Reimport @UnresolvedImport
)
from PyQt5.QtCore import Qt, pyqtSlot, QSize, QSettings # type: ignore # @UnusedImport @Reimport @UnresolvedImport
from PyQt5.QtGui import QIcon, QStandardItemModel # type: ignore # @UnusedImport @Reimport @UnresolvedImport
from PyQt5.QtGui import QKeySequence, QAction, QIcon, QStandardItemModel # type: ignore # @UnusedImport @Reimport @UnresolvedImport
# try:
# from PyQt5 import sip # type: ignore # @Reimport @UnresolvedImport @UnusedImport
# except Exception: # pylint: disable=broad-except
Expand All @@ -65,7 +65,7 @@
if TYPE_CHECKING:
from artisanlib.main import ApplicationWindow # noqa: F401 # pylint: disable=unused-import
from PyQt6.QtWidgets import QWidget # noqa: F401 # pylint: disable=unused-import
from PyQt6.QtGui import QCloseEvent # pylint: disable=unused-import
from PyQt6.QtGui import QCloseEvent, QKeyEvent # pylint: disable=unused-import

_log: Final[logging.Logger] = logging.getLogger(__name__)

Expand Down Expand Up @@ -163,6 +163,23 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow', inWeight:float, wei
self.ui.buttonBox.removeButton(applyButton)
self.applyButton = self.ui.buttonBox.addButton(applyButton.text(), QDialogButtonBox.ButtonRole.AcceptRole)

cancelButton = self.ui.buttonBox.button(QDialogButtonBox.StandardButton.Cancel)
if cancelButton is not None:
cancelButton.setDefault(False)
cancelButton.setAutoDefault(False)
# add additional CMD-. shortcut to close the dialog
cancelButton.setShortcut(QKeySequence('Ctrl+.'))
# add additional CMD-W shortcut to close this dialog (ESC on Mac OS X)
# cancelAction = QAction(self, triggered=lambda _:self.dialogbuttons.rejected.emit())
cancelAction = QAction(self)
cancelAction.triggered.connect(self.cancelDialog)
try:
cancelAction.setShortcut(QKeySequence.StandardKey.Cancel)
except Exception: # pylint: disable=broad-except
pass
cancelButton.addActions([cancelAction])


# populate widgets
self.ui.lineEdit_name.setText(self.blend.name)
self.ui.label_weight.setText(QApplication.translate('Label','Weight'))
Expand All @@ -183,6 +200,22 @@ def __init__(self, parent:'QWidget', aw:'ApplicationWindow', inWeight:float, wei
if settings.contains('BlendGeometry'):
self.restoreGeometry(settings.value('BlendGeometry'))

@pyqtSlot()
def cancelDialog(self) -> None: # ESC key
self.reject()

def keyPressEvent(self, event: Optional['QKeyEvent']) -> None:
if event is not None:
key = int(event.key())
#uncomment next line to find the integer value of a key
#print(key)
#modifiers = QApplication.keyboardModifiers()
modifiers = event.modifiers()
if key == 16777216 or (key == 87 and modifiers == Qt.KeyboardModifier.ControlModifier): #ESCAPE or CMD-W
self.reject()
else:
super().keyPressEvent(event)

@pyqtSlot(str)
def textChanged(self,s:str) -> None:
if s == '': # content got cleared
Expand Down Expand Up @@ -291,7 +324,7 @@ def saveSettings(self) -> None:

@pyqtSlot('QCloseEvent')
def closeEvent(self, _:Optional['QCloseEvent'] = None) -> None:
self.saveSettings()
self.reject()

@pyqtSlot()
def accept(self) -> None:
Expand Down
9 changes: 8 additions & 1 deletion src/plus/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -2086,11 +2086,12 @@ def keyPressEvent(self, event: Optional['QKeyEvent']) -> None:
self.selected_completed_item.clicked.emit()
else:
self.selected_completed_item.selected.emit()
elif k == 46 and QApplication.keyboardModifiers() == Qt.KeyboardModifier.ControlModifier: # CMD-.
self.closeEvent()
else:
super().keyPressEvent(event)



@pyqtSlot('QCloseEvent')
def closeEvent(self, evnt:Optional['QCloseEvent'] = None) -> None: # type:ignore[reportIncompatibleMethodOverride, unused-ignore]
if self.aw.scheduler_auto_open and len(self.scheduled_items) > 0 and self.aw.plus_account is not None:
Expand Down Expand Up @@ -2119,6 +2120,11 @@ def closeEvent(self, evnt:Optional['QCloseEvent'] = None) -> None: # type:ignore
else:
self.closeScheduler()

@pyqtSlot()
def close(self) -> bool:
self.closeEvent(None)
return True

def closeScheduler(self) -> None:
self.aw.scheduled_items_uuids = self.get_scheduled_items_ids()
# remember Dialog geometry
Expand Down Expand Up @@ -2146,6 +2152,7 @@ def closeScheduler(self) -> None:
self.aw.qmc.scheduleID = None
self.aw.qmc.scheduleDate = None
self.aw.sendmessage(QApplication.translate('Message','Scheduler stopped'))
self.accept()

# updates the current schedule items by joining its roast with those received as part of a stock update from the server
# adding new items at the end
Expand Down
14 changes: 7 additions & 7 deletions src/requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
types-openpyxl>=3.1.5.20240918
types-openpyxl>=3.1.5.20241025
types-Pillow>=10.2.0.20240822
types-protobuf>=5.28.0.20240924
types-psutil>=6.0.0.20241011
types-protobuf>=5.28.3.20241030
types-psutil>=6.1.0.20241022
types-pyserial>=3.5.0.20240826
types-python-dateutil==2.9.0.20241003
types-pytz>=2024.2.0.20241003
types-pyyaml>=6.0.12.20240917
types-requests>=2.32.0.20241016
types-setuptools>=75.1.0.20241014
types-setuptools>=75.2.0.20241025
types-urllib3>=1.26.25.14
types-docutils>=0.21.0.20241005
lxml-stubs>=0.5.1
mypy==1.13.0
pyright==1.1.386
pyright==1.1.387
ruff>=0.7.1
pylint==3.3.1
pre-commit>=4.0.1
Expand All @@ -25,8 +25,8 @@ pytest-cov==5.0.0
#pytest-bdd==6.1.1
#pytest-benchmark==4.0.0
#pytest-mock==3.11.1
hypothesis>=6.115.3
coverage>=7.6.3
hypothesis>=6.115.6
coverage>=7.6.4
coverage-badge==1.1.2
codespell==2.3.0
# the following 2 packages are not installed along aiohttp on Python3.12 and make mypy complain
Expand Down
9 changes: 5 additions & 4 deletions src/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,19 @@ portalocker==2.10.1
xlrd==2.0.1
websockets==13.1
PyYAML==6.0.2
psutil==6.0.0
psutil==6.1.0
typing-extensions==4.10.0; python_version < '3.8' # required for supporting Final and TypeDict on Python <3.8
protobuf==5.28.2
protobuf==5.28.3
numpy==1.24.3; python_version < '3.9' # last Python 3.8 release
numpy==2.1.2; python_version >= '3.9'
scipy==1.10.1; python_version < '3.9' # last Python 3.8 release
scipy==1.14.1; python_version >= '3.9'
wquantiles==0.6
colorspacious==1.1.2
openpyxl==3.1.5
keyring==25.4.1
prettytable==3.11.0
keyring==25.5.0
prettytable==3.11.0; python_version < '3.9' # last Python 3.8 release
prettytable==3.12.0; python_version >= '3.9'
lxml==5.3.0
matplotlib==3.7.3; python_version < '3.9' # last Python 3.8 release
matplotlib==3.9.2; python_version >= '3.9'
Expand Down

0 comments on commit 9df1931

Please sign in to comment.