from PyQt5 import QtWidgets, QtCore from typing import Optional, Tuple, List, Any from todo.model.task import Task, ValidTaskForm from todo.model.tag import Tag from todo.model import difficulty, priority import todo.gui.icon import todo.gui.tasks.form.state import todo.gui.tasks.duration import todo.gui.tags.list 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, tags: List[int], on_validated, on_cancel): widget = QtWidgets.QWidget(parent) layout = QtWidgets.QVBoxLayout(widget) widget.setLayout(layout) init_name = task.name if task is not None else "" name_input = name_edit(widget, layout, "Name", init_name) grid = QtWidgets.QWidget(widget) layout.addWidget(grid) grid_layout = QtWidgets.QGridLayout(grid) grid.setLayout(grid_layout) init_duration = todo.gui.tasks.duration.format(task.duration) if task is not None else "" duration_input = line_edit(grid, grid_layout, 1, "Duration", init_duration) 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)) (tags_list_widget, tags_signal) = tags_selection(widget, tags) layout.addWidget(tags_list_widget) 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 = todo.gui.tasks.form.state.TaskFormEdition( init_name, name_input.textChanged, init_duration, duration_input.textChanged, init_difficulty, difficulty_input.currentIndexChanged, init_priority, priority_input.currentIndexChanged, tags, tags_signal, 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 name_edit( parent, layout: QtWidgets.QVBoxLayout, label: str, default_value: str) -> QtWidgets.QLineEdit: widget = QtWidgets.QWidget(parent) inner_layout = QtWidgets.QVBoxLayout(widget) widget.setLayout(inner_layout) label = QtWidgets.QLabel(label, parent) inner_layout.addWidget(label) edit = QtWidgets.QLineEdit(parent) if default_value != None: edit.setText(default_value) inner_layout.addWidget(edit) layout.addWidget(widget) return edit 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 tags_selection(parent, init_tags: List[int]) -> QtWidgets.QWidget: return todo.gui.tags.list.widget(parent, init_tags) 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(todo.gui.icon.dialog_ok(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(todo.gui.icon.dialog_cancel(cancel.style())) cancel.clicked.connect(on_cancel) layout.addWidget(cancel) return widget