From 8435065b1de17b9101bbf1a43f643d5ad53c94df Mon Sep 17 00:00:00 2001 From: Constantine Date: Thu, 9 Jan 2025 22:46:51 +0100 Subject: [PATCH] [Bugfix] Error when trying to start another pomodoro while the timer is running (#72, #74) --- res/CHANGELOG.txt | 1 + src/fk/desktop/desktop.py | 8 ++++++-- src/fk/e2e/backlog_e2e.py | 24 ++++++++++++++++++++++++ src/fk/qt/workitem_tableview.py | 13 ++++++++++--- src/fk/qt/workitem_widget.py | 8 +++++++- src/fk/tools/minimal_workitems.py | 9 ++++++++- 6 files changed, 56 insertions(+), 7 deletions(-) diff --git a/res/CHANGELOG.txt b/res/CHANGELOG.txt index 984f1907..5b9743c6 100644 --- a/res/CHANGELOG.txt +++ b/res/CHANGELOG.txt @@ -3,6 +3,7 @@ - [Technical] System proxy settings are applied automatically. - [Bugfix] Defaulting to embedded Noto Sans (#68). - [Bugfix] "Unhandled JSONDecodeError" behind the proxy (#69, #73). +- [Bugfix] Error when trying to start another pomodoro while the timer is running (#72, #74). ### v0.9.0 (30 December 2024) - You can now drag backlogs and work items to reorder them. Backlogs are not reordered automatically anymore. diff --git a/src/fk/desktop/desktop.py b/src/fk/desktop/desktop.py index 3c233c99..4c8c8d39 100644 --- a/src/fk/desktop/desktop.py +++ b/src/fk/desktop/desktop.py @@ -20,7 +20,7 @@ from PySide6 import QtCore, QtWidgets, QtUiTools, QtAsyncio from PySide6.QtCore import Qt from PySide6.QtGui import QIcon -from PySide6.QtWidgets import QMessageBox, QMainWindow, QMenu, QWizard +from PySide6.QtWidgets import QMessageBox, QMainWindow, QMenu from fk.core import events from fk.core.abstract_event_source import AbstractEventSource @@ -347,7 +347,11 @@ def _on_source_changed(event: str, source: AbstractEventSource): right_layout: QtWidgets.QVBoxLayout = window.findChild(QtWidgets.QVBoxLayout, "rightTableLayoutInternal") # Workitems table - workitems_widget: WorkitemWidget = WorkitemWidget(window, app, app.get_source_holder(), actions) + workitems_widget: WorkitemWidget = WorkitemWidget(window, + app, + app.get_source_holder(), + pomodoro_timer, + actions) right_layout.addWidget(workitems_widget) progress_widget = ProgressWidget(window, app.get_source_holder()) diff --git a/src/fk/e2e/backlog_e2e.py b/src/fk/e2e/backlog_e2e.py index c0f14676..66f861a6 100644 --- a/src/fk/e2e/backlog_e2e.py +++ b/src/fk/e2e/backlog_e2e.py @@ -369,6 +369,30 @@ def assert_backlog_actions_enabled(new_from_incomplete: bool): 'focus.voidPomodoro', ]) + ####################################### + # Check actions on a started workitem # + ####################################### + self.info('Start a workitem to check actions visibility') + await self._find_workitem('Workitem 13') + await self._start_pomodoro() + await self._wait_mid_pomodoro() + + assert_backlog_actions_enabled(True) + self.assert_actions_enabled([ + 'workitems_table.deleteItem', + 'workitems_table.addPomodoro', + 'workitems_table.completeItem', + 'workitems_table.renameItem', + 'workitems_table.removePomodoro', + 'focus.voidPomodoro', + ]) + self.assert_actions_disabled([ + 'workitems_table.startItem', + ]) + + self.info('Void pomodoro to reset the state') + await self._void_pomodoro() + async def test_03_renames(self): # noinspection PyTypeChecker backlogs_table: BacklogTableView = self.window().findChild(BacklogTableView, "backlogs_table") diff --git a/src/fk/qt/workitem_tableview.py b/src/fk/qt/workitem_tableview.py index c4d7310d..6405ae77 100644 --- a/src/fk/qt/workitem_tableview.py +++ b/src/fk/qt/workitem_tableview.py @@ -23,6 +23,7 @@ from fk.core.events import AfterWorkitemCreate, AfterSettingsChanged from fk.core.pomodoro_strategies import StartWorkStrategy, AddPomodoroStrategy, RemovePomodoroStrategy from fk.core.tag import Tag +from fk.core.timer import PomodoroTimer from fk.core.workitem import Workitem from fk.core.workitem_strategies import DeleteWorkitemStrategy, CreateWorkitemStrategy, CompleteWorkitemStrategy from fk.desktop.application import Application @@ -36,11 +37,13 @@ class WorkitemTableView(AbstractTableView[Backlog | Tag, Workitem]): _application: Application _menu: QMenu + _pomodoro_timer: PomodoroTimer def __init__(self, parent: QWidget, application: Application, source_holder: EventSourceHolder, + pomodoro_timer: PomodoroTimer, actions: Actions): super().__init__(parent, source_holder, @@ -52,9 +55,11 @@ def __init__(self, 'The selected backlog is empty.\nCreate the first workitem by pressing Ins key.', 1) self._application = application + self._pomodoro_timer = pomodoro_timer self._configure_delegate() self._menu = self._init_menu(actions) source_holder.on(AfterSourceChanged, self._on_source_changed) + pomodoro_timer.on('Timer(Work|Rest)(Start|Complete)', lambda **_: self.update_actions(self.get_current())) self.update_actions(None) application.get_settings().on(AfterSettingsChanged, self._on_setting_changed) @@ -138,15 +143,17 @@ def upstream_selected(self, backlog_or_tag: Backlog | Tag) -> None: def update_actions(self, selected: Workitem) -> None: # It can be None for example if we don't have any backlogs left, or if we haven't loaded any yet. - # TODO: Call this on any workitem and timer event is_workitem_selected = selected is not None is_workitem_editable = is_workitem_selected and not selected.is_sealed() self._actions['workitems_table.deleteItem'].setEnabled(is_workitem_selected) self._actions['workitems_table.renameItem'].setEnabled(is_workitem_editable) - self._actions['workitems_table.startItem'].setEnabled(is_workitem_editable and selected.is_startable()) + self._actions['workitems_table.startItem'].setEnabled(is_workitem_editable + and selected.is_startable() + and self._pomodoro_timer.is_idling()) self._actions['workitems_table.completeItem'].setEnabled(is_workitem_editable) self._actions['workitems_table.addPomodoro'].setEnabled(is_workitem_editable) - self._actions['workitems_table.removePomodoro'].setEnabled(is_workitem_editable and selected.is_startable()) + self._actions['workitems_table.removePomodoro'].setEnabled(is_workitem_editable + and selected.is_startable()) # Actions diff --git a/src/fk/qt/workitem_widget.py b/src/fk/qt/workitem_widget.py index 24e0cc02..c106f07c 100644 --- a/src/fk/qt/workitem_widget.py +++ b/src/fk/qt/workitem_widget.py @@ -22,6 +22,7 @@ from fk.core.event_source_holder import EventSourceHolder from fk.core.events import AfterSettingsChanged from fk.core.tag import Tag +from fk.core.timer import PomodoroTimer from fk.desktop.application import Application from fk.qt.actions import Actions from fk.qt.configurable_toolbar import ConfigurableToolBar @@ -38,6 +39,7 @@ def __init__(self, parent: QWidget, application: Application, source_holder: EventSourceHolder, + pomodoro_timer: PomodoroTimer, actions: Actions): super().__init__(parent) self.setObjectName('workitems_widget') @@ -60,7 +62,11 @@ def __init__(self, tb.addAction(actions['workitems_table.completeItem']) layout.addWidget(tb) - self._workitems_table = WorkitemTableView(self, application, source_holder, actions) + self._workitems_table = WorkitemTableView(self, + application, + source_holder, + pomodoro_timer, + actions) layout.addWidget(self._workitems_table) application.get_settings().on(AfterSettingsChanged, self.on_setting_changed) diff --git a/src/fk/tools/minimal_workitems.py b/src/fk/tools/minimal_workitems.py index 6bd7a990..11410635 100644 --- a/src/fk/tools/minimal_workitems.py +++ b/src/fk/tools/minimal_workitems.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from fk.core.tenant import Tenant +from fk.core.timer import PomodoroTimer +from fk.qt.qt_timer import QtTimer from fk.qt.workitem_tableview import WorkitemTableView from fk.tools.minimal_common import MinimalCommon @@ -24,10 +26,15 @@ def select_first_backlog(data: Tenant): mc = MinimalCommon(select_first_backlog) +pomodoro_timer = PomodoroTimer(QtTimer("Pomodoro Tick"), QtTimer("Pomodoro Transition"), mc.get_settings(), mc.get_app().get_source_holder()) mc.get_window().resize(600, 400) WorkitemTableView.define_actions(mc.get_actions()) -workitems_table: WorkitemTableView = WorkitemTableView(mc.get_window(), mc.get_app(), mc.get_app().get_source_holder(), mc.get_actions()) +workitems_table: WorkitemTableView = WorkitemTableView(mc.get_window(), + mc.get_app(), + mc.get_app().get_source_holder(), + pomodoro_timer, + mc.get_actions()) mc.get_actions().bind('workitems_table', workitems_table) mc.get_window().setCentralWidget(workitems_table)