From bff2dfd96169f595510b16980a4cb2f3d4548029 Mon Sep 17 00:00:00 2001 From: Joris Date: Fri, 8 May 2020 14:33:15 +0200 Subject: Extract task form code from the dialog file --- src/gui/tasks/form/state.py | 39 +++++++++++++ src/gui/tasks/form/widget.py | 100 +++++++++++++++++++++++++++++++++ src/gui/tasks/main.py | 39 ------------- src/gui/tasks/modal.py | 127 +++--------------------------------------- src/gui/tasks/table/main.py | 46 --------------- src/gui/tasks/table/widget.py | 46 +++++++++++++++ src/gui/tasks/widget.py | 39 +++++++++++++ src/gui/window.py | 4 +- 8 files changed, 234 insertions(+), 206 deletions(-) create mode 100644 src/gui/tasks/form/state.py create mode 100644 src/gui/tasks/form/widget.py delete mode 100644 src/gui/tasks/main.py delete mode 100644 src/gui/tasks/table/main.py create mode 100644 src/gui/tasks/table/widget.py create mode 100644 src/gui/tasks/widget.py diff --git a/src/gui/tasks/form/state.py b/src/gui/tasks/form/state.py new file mode 100644 index 0000000..6aedb95 --- /dev/null +++ b/src/gui/tasks/form/state.py @@ -0,0 +1,39 @@ +from PyQt5 import QtCore + +from model.task import TaskForm + +class TaskFormEdition: + def __init__(self, name, name_signal, tag, tag_signal): + self._name = name + self._tag = tag + self._signal = TaskFormSignal() + name_signal.connect(lambda name: self.on_name_signal(name)) + tag_signal.connect(lambda tag: self.on_tag_signal(tag)) + + def get(self): + return TaskForm( + name = self._name, + tag = self._tag) + + def on_name_signal(self, name: str): + self._name = name + self._signal.emit(self.get()) + + def on_tag_signal(self, tag: str): + self._tag = tag + self._signal.emit(self.get()) + + def signal(self): + return self._signal + +class TaskFormSignal(QtCore.QObject): + _signal = QtCore.pyqtSignal(TaskForm, name = 'taskForm') + + def __init__(self): + QtCore.QObject.__init__(self) + + def emit(self, taskForm): + self._signal.emit(taskForm) + + def connect(self, f): + self._signal.connect(f) diff --git a/src/gui/tasks/form/widget.py b/src/gui/tasks/form/widget.py new file mode 100644 index 0000000..61fa24d --- /dev/null +++ b/src/gui/tasks/form/widget.py @@ -0,0 +1,100 @@ +from PyQt5 import QtWidgets + +import db.tasks +from model.task import Task, TaskForm + +import gui.icons +import gui.tasks.form.state + +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) + + init_name = task.name if task is not None else '' + (name_labelled_input, name_input) = labelled_input(widget, 'Name', init_name) + layout.addWidget(name_labelled_input) + + init_tag = task.tag if task is not None else '' + (tag_labelled_input, tag_input) = labelled_input(widget, 'Tag', init_tag) + layout.addWidget(tag_labelled_input) + + task_form_edition = gui.tasks.form.state.TaskFormEdition( + init_name, + name_input.textChanged, + init_tag, + tag_input.textChanged) + + layout.addWidget(buttons( + parent = widget, + action_title = action_title, + task_form_signal = task_form_edition.signal(), + on_validate = lambda: validate(task_form_edition.get(), on_validated), + on_cancel = on_cancel)) + + return widget + +# Use grid ? +def labelled_input(parent, label: str, default_value: str): + widget = QtWidgets.QWidget(parent) + + layout = QtWidgets.QHBoxLayout(widget) + widget.setLayout(layout) + + label = QtWidgets.QLabel(label, widget) + layout.addWidget(label) + + line_edit = QtWidgets.QLineEdit(widget) + if default_value != None: + line_edit.setText(default_value) + layout.addWidget(line_edit) + + return (widget, line_edit) + +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.icons.dialog_apply(validate.style())) + validate.clicked.connect(on_validate); + layout.addWidget(validate) + + def on_task_form_signal(task_form): + if validate_form(task_form): + validate.setEnabled(True) + else: + validate.setDisabled(True) + + task_form_signal.connect(on_task_form_signal) + + cancel = QtWidgets.QPushButton('cancel', widget) + cancel.setIcon(gui.icons.dialog_cancel(cancel.style())) + cancel.clicked.connect(on_cancel) + layout.addWidget(cancel) + + return widget + +def validate(task_form: TaskForm, on_validated): + valid_form = validate_form(task_form) + if valid_form: + on_validated(valid_form) + +def clean_form(task_form: TaskForm): + return TaskForm( + name = task_form.name.strip(), + tag = task_form.tag.strip()) + +def validate_form(task_form: TaskForm): + task_form = clean_form(task_form) + if task_form.name: + return task_form + else: + return None diff --git a/src/gui/tasks/main.py b/src/gui/tasks/main.py deleted file mode 100644 index 3c7d3db..0000000 --- a/src/gui/tasks/main.py +++ /dev/null @@ -1,39 +0,0 @@ -from PyQt5 import QtWidgets, QtCore - -import db.tasks -import gui.tasks.signal -import gui.tasks.table.main -import gui.icons -from model.task import TaskForm - -def widget(database, parent): - widget = QtWidgets.QWidget(parent) - - layout = QtWidgets.QVBoxLayout(widget) - widget.setLayout(layout) - - add_task_signal = gui.tasks.signal.AddTask() - - add_task_button = QtWidgets.QPushButton('Add a task', widget) - add_task_button.setIcon(gui.icons.new_folder(widget.style())) - add_task_button.clicked.connect(lambda: show_add_dialog(database, widget, add_task_signal)) - layout.addWidget(add_task_button) - - table = gui.tasks.table.main.widget(database, widget, add_task_signal) - layout.addWidget(table) - - return widget - -def show_add_dialog(database, parent_widget, add_task_signal): - dialog = gui.tasks.modal.dialog( - parent_widget, - 'Add a task', - 'add', - None, - lambda taskForm: on_add(database, taskForm, add_task_signal)) - dialog.exec_() - -def on_add(database, taskForm: TaskForm, add_task_signal): - task = db.tasks.insert(database.cursor(), taskForm) - database.commit() - add_task_signal.emit(task) diff --git a/src/gui/tasks/modal.py b/src/gui/tasks/modal.py index 3ccf56e..3662947 100644 --- a/src/gui/tasks/modal.py +++ b/src/gui/tasks/modal.py @@ -1,9 +1,8 @@ from PyQt5 import QtCore, QtWidgets -import db.tasks -from model.task import Task, TaskForm +from model.task import Task -import gui.icons +import gui.tasks.form.widget def dialog( parent: QtWidgets.QWidget, @@ -19,125 +18,15 @@ def dialog( layout = QtWidgets.QVBoxLayout(dialog) dialog.setLayout(layout) - init_name = task.name if task is not None else '' - (name_labelled_input, name_input) = labelled_input(dialog, 'Name', init_name) - layout.addWidget(name_labelled_input) - - init_tag = task.tag if task is not None else '' - (tag_labelled_input, tag_input) = labelled_input(dialog, 'Tag', init_tag) - layout.addWidget(tag_labelled_input) - - task_form_edition = TaskFormEdition( - init_name, - name_input.textChanged, - init_tag, - tag_input.textChanged) - - layout.addWidget(buttons( + layout.addWidget(gui.tasks.form.widget.widget( parent = dialog, action_title = action_title, - task_form_signal = task_form_edition.signal(), - on_validate = lambda: validate(dialog, task_form_edition.get(), on_validated), + task = task, + on_validated = lambda form: on_dialog_validated(dialog, on_validated, form), on_cancel = lambda: dialog.reject())) return dialog -# Use grid ? -def labelled_input(parent, label: str, default_value: str): - widget = QtWidgets.QWidget(parent) - - layout = QtWidgets.QHBoxLayout(widget) - widget.setLayout(layout) - - label = QtWidgets.QLabel(label, widget) - layout.addWidget(label) - - line_edit = QtWidgets.QLineEdit(widget) - if default_value != None: - line_edit.setText(default_value) - layout.addWidget(line_edit) - - return (widget, line_edit) - -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.icons.dialog_apply(validate.style())) - validate.clicked.connect(on_validate); - layout.addWidget(validate) - - def on_task_form_signal(task_form): - if validate_form(task_form): - validate.setEnabled(True) - else: - validate.setDisabled(True) - - task_form_signal.connect(on_task_form_signal) - - cancel = QtWidgets.QPushButton('cancel', widget) - cancel.setIcon(gui.icons.dialog_cancel(cancel.style())) - cancel.clicked.connect(on_cancel) - layout.addWidget(cancel) - - return widget - -def validate(dialog, task_form: TaskForm, on_validated): - valid_form = validate_form(task_form) - if valid_form: - on_validated(valid_form) - dialog.accept() - -def clean_form(task_form: TaskForm): - return TaskForm( - name = task_form.name.strip(), - tag = task_form.tag.strip()) - -def validate_form(task_form: TaskForm): - task_form = clean_form(task_form) - if task_form.name: - return task_form - else: - return None - -##################### -# Task form edition # -##################### - -class TaskFormEdition: - def __init__(self, name, name_signal, tag, tag_signal): - self._name = name - self._tag = tag - self._signal = TaskFormSignal() - name_signal.connect(lambda name: self.on_name_signal(name)) - tag_signal.connect(lambda tag: self.on_tag_signal(tag)) - - def get(self): - return TaskForm( - name = self._name, - tag = self._tag) - - def on_name_signal(self, name: str): - self._name = name - self._signal.emit(self.get()) - - def on_tag_signal(self, tag: str): - self._tag = tag - self._signal.emit(self.get()) - - def signal(self): - return self._signal - -class TaskFormSignal(QtCore.QObject): - _signal = QtCore.pyqtSignal(TaskForm, name = 'taskForm') - - def __init__(self): - QtCore.QObject.__init__(self) - - def emit(self, taskForm): - self._signal.emit(taskForm) - - def connect(self, f): - self._signal.connect(f) +def on_dialog_validated(dialog, on_validated, f): + dialog.accept() + on_validated(f) diff --git a/src/gui/tasks/table/main.py b/src/gui/tasks/table/main.py deleted file mode 100644 index a990c0e..0000000 --- a/src/gui/tasks/table/main.py +++ /dev/null @@ -1,46 +0,0 @@ -from PyQt5 import QtWidgets -from PyQt5.QtCore import Qt - -import db.tasks -import gui.tasks.signal -import gui.tasks.table.menu -import gui.tasks.table.model - -def widget(database, parent, add_task_signal): - table = QtWidgets.QTableView(parent) - - tasks = db.tasks.get(database.cursor()) - table_model = gui.tasks.table.model.TableModel(tasks) - - table.setModel(table_model) - table.sortByColumn( - gui.tasks.table.model.default_sort[0], - gui.tasks.table.model.default_sort[1]) - table.setSortingEnabled(True) - table.setSelectionBehavior(QtWidgets.QTableView.SelectRows) - table.horizontalHeader().setStretchLastSection(True) - resizeColumns(table) - - update_task_signal = gui.tasks.signal.UpdateTask() - - # Menu - table.setContextMenuPolicy(Qt.CustomContextMenu) - table.customContextMenuRequested.connect(lambda position: gui.tasks.table.menu.open(database, table, update_task_signal, position)) - - add_task_signal.get().connect(lambda task: insert(table, task)) - update_task_signal.get().connect(lambda row, task: update(table, row, task)) - - return table - -def insert(table, task): - table.model().insert_task(table.horizontalHeader(), task) - resizeColumns(table) - -def update(table, row, task): - row = table.model().update_task(table.horizontalHeader(), row, task) - table.selectRow(row) - resizeColumns(table) - -def resizeColumns(table): - for column in range(gui.tasks.table.model.columns): - table.resizeColumnToContents(column) diff --git a/src/gui/tasks/table/widget.py b/src/gui/tasks/table/widget.py new file mode 100644 index 0000000..a990c0e --- /dev/null +++ b/src/gui/tasks/table/widget.py @@ -0,0 +1,46 @@ +from PyQt5 import QtWidgets +from PyQt5.QtCore import Qt + +import db.tasks +import gui.tasks.signal +import gui.tasks.table.menu +import gui.tasks.table.model + +def widget(database, parent, add_task_signal): + table = QtWidgets.QTableView(parent) + + tasks = db.tasks.get(database.cursor()) + table_model = gui.tasks.table.model.TableModel(tasks) + + table.setModel(table_model) + table.sortByColumn( + gui.tasks.table.model.default_sort[0], + gui.tasks.table.model.default_sort[1]) + table.setSortingEnabled(True) + table.setSelectionBehavior(QtWidgets.QTableView.SelectRows) + table.horizontalHeader().setStretchLastSection(True) + resizeColumns(table) + + update_task_signal = gui.tasks.signal.UpdateTask() + + # Menu + table.setContextMenuPolicy(Qt.CustomContextMenu) + table.customContextMenuRequested.connect(lambda position: gui.tasks.table.menu.open(database, table, update_task_signal, position)) + + add_task_signal.get().connect(lambda task: insert(table, task)) + update_task_signal.get().connect(lambda row, task: update(table, row, task)) + + return table + +def insert(table, task): + table.model().insert_task(table.horizontalHeader(), task) + resizeColumns(table) + +def update(table, row, task): + row = table.model().update_task(table.horizontalHeader(), row, task) + table.selectRow(row) + resizeColumns(table) + +def resizeColumns(table): + for column in range(gui.tasks.table.model.columns): + table.resizeColumnToContents(column) diff --git a/src/gui/tasks/widget.py b/src/gui/tasks/widget.py new file mode 100644 index 0000000..bca6585 --- /dev/null +++ b/src/gui/tasks/widget.py @@ -0,0 +1,39 @@ +from PyQt5 import QtWidgets, QtCore + +import db.tasks +import gui.tasks.signal +import gui.tasks.table.widget +import gui.icons +from model.task import TaskForm + +def widget(database, parent): + widget = QtWidgets.QWidget(parent) + + layout = QtWidgets.QVBoxLayout(widget) + widget.setLayout(layout) + + add_task_signal = gui.tasks.signal.AddTask() + + add_task_button = QtWidgets.QPushButton('Add a task', widget) + add_task_button.setIcon(gui.icons.new_folder(widget.style())) + add_task_button.clicked.connect(lambda: show_add_dialog(database, widget, add_task_signal)) + layout.addWidget(add_task_button) + + table = gui.tasks.table.widget.widget(database, widget, add_task_signal) + layout.addWidget(table) + + return widget + +def show_add_dialog(database, parent_widget, add_task_signal): + dialog = gui.tasks.modal.dialog( + parent_widget, + 'Add a task', + 'add', + None, + lambda taskForm: on_add(database, taskForm, add_task_signal)) + dialog.exec_() + +def on_add(database, taskForm: TaskForm, add_task_signal): + task = db.tasks.insert(database.cursor(), taskForm) + database.commit() + add_task_signal.emit(task) diff --git a/src/gui/window.py b/src/gui/window.py index 67d1dea..aa22f7e 100644 --- a/src/gui/window.py +++ b/src/gui/window.py @@ -1,6 +1,6 @@ from PyQt5 import QtCore, QtWidgets -import gui.tasks.main +import gui.tasks.widget def get(database): window = QtWidgets.QMainWindow() @@ -8,6 +8,6 @@ def get(database): window.setMinimumSize(QtCore.QSize(640, 480)) centralWidget = QtWidgets.QWidget(window) - window.setCentralWidget(gui.tasks.main.widget(database, centralWidget)) + window.setCentralWidget(gui.tasks.widget.widget(database, centralWidget)) return window -- cgit v1.2.3