from PyQt5 import QtWidgets, QtCore from typing import Optional, Tuple, List, Any from model.task import Task, ValidTaskForm from model import difficulty, priority import gui.icon import gui.tasks.form.state import gui.tasks.duration class TextEditSignal(QtCore.QObject): _signal = QtCore.pyqtSignal(str, name = 'textEdit') def __init__(self): QtCore.QObject.__init__(self) def emit(self, text: str): self._signal.emit(text) def connect(self, f): self._signal.connect(f) def widget( parent: QtWidgets.QWidget, action_title: str, task: Task, on_validated, on_cancel): widget = QtWidgets.QWidget(parent) layout = QtWidgets.QVBoxLayout(widget) widget.setLayout(layout) grid = QtWidgets.QWidget(widget) layout.addWidget(grid) grid_layout = QtWidgets.QGridLayout(grid) grid.setLayout(grid_layout) init_name = task.name if task is not None else '' name_input = line_edit(grid, grid_layout, 0, 'Name', init_name) init_duration = gui.tasks.duration.format(task.duration) if task is not None else '' duration_input = line_edit(grid, grid_layout, 1, 'Duration', init_duration) init_tag = task.tag if task is not None else '' tag_input = line_edit(grid, grid_layout, 2, 'Tag', init_tag) init_difficulty = task.difficulty if task is not None else difficulty.Difficulty.NORMAL difficulty_input = combo_box( grid, grid_layout, 3, 'Difficulty', [difficulty.format(d) for d in difficulty.values], int(init_difficulty)) init_priority = task.priority if task is not None else priority.Priority.MIDDLE priority_input = combo_box( grid, grid_layout, 4, 'Priority', [priority.format(d) for d in priority.values], int(init_priority)) init_description = task.description if task is not None else '' (description_input, description_signal) = text_edit(widget, 'Description', init_description) layout.addWidget(description_input) task_form_edition = gui.tasks.form.state.TaskFormEdition( init_name, name_input.textChanged, init_duration, duration_input.textChanged, init_tag, tag_input.textChanged, init_difficulty, difficulty_input.currentIndexChanged, init_priority, priority_input.currentIndexChanged, init_description, description_signal) def on_validate(): form = task_form_edition.get() if form: on_validated(form) layout.addWidget(buttons( parent = widget, action_title = action_title, task_form_signal = task_form_edition.signal(), on_validate = on_validate, on_cancel = on_cancel)) return widget def line_edit( parent, layout: QtWidgets.QGridLayout, n: int, label: str, default_value: str) -> QtWidgets.QLineEdit: label = QtWidgets.QLabel(label, parent) layout.addWidget(label, n, 0) edit = QtWidgets.QLineEdit(parent) if default_value != None: edit.setText(default_value) layout.addWidget(edit, n, 1) return edit def combo_box( parent, layout: QtWidgets.QGridLayout, n: int, label: str, values: List[str], default_value: int) -> QtWidgets.QComboBox: label = QtWidgets.QLabel(label, parent) layout.addWidget(label, n, 0) box = QtWidgets.QComboBox(parent) for value in values: box.addItem(value) if default_value != None: box.setCurrentIndex(default_value) layout.addWidget(box, n, 1) return box def text_edit( parent, label: str, default_value: str) -> Tuple[QtWidgets.QWidget, TextEditSignal]: widget = QtWidgets.QWidget(parent) layout = QtWidgets.QVBoxLayout(widget) signal = TextEditSignal() label = QtWidgets.QLabel(label, parent) layout.addWidget(label) edit = QtWidgets.QTextEdit(parent) if default_value != None: edit.insertPlainText(default_value) layout.addWidget(edit) edit.textChanged.connect(lambda: signal.emit(edit.toPlainText())) return (widget, signal) def buttons(parent, action_title, task_form_signal, on_validate, on_cancel): widget = QtWidgets.QWidget(parent) layout = QtWidgets.QHBoxLayout(widget) validate = QtWidgets.QPushButton(action_title, widget) validate.setDisabled(True) validate.setIcon(gui.icon.dialog_apply(validate.style())) validate.clicked.connect(on_validate); layout.addWidget(validate) def on_task_form_signal(form: Optional[ValidTaskForm]): if form: validate.setEnabled(True) else: validate.setDisabled(True) task_form_signal.connect(on_task_form_signal) cancel = QtWidgets.QPushButton('cancel', widget) cancel.setIcon(gui.icon.dialog_cancel(cancel.style())) cancel.clicked.connect(on_cancel) layout.addWidget(cancel) return widget