From b5658771fd9b1a50e10a0004dd1934c746505446 Mon Sep 17 00:00:00 2001 From: Joris Date: Sat, 9 May 2020 15:04:24 +0200 Subject: Enable task modification and deletion with keyboard and mouse --- src/gui/tasks/dialog.py | 64 +++++++++++++++++++++++++++++++++++ src/gui/tasks/modal.py | 32 ------------------ src/gui/tasks/table/menu.py | 24 ++----------- src/gui/tasks/table/widget.py | 79 ++++++++++++++++++++++++++++--------------- src/gui/tasks/widget.py | 20 ++--------- 5 files changed, 122 insertions(+), 97 deletions(-) create mode 100644 src/gui/tasks/dialog.py delete mode 100644 src/gui/tasks/modal.py diff --git a/src/gui/tasks/dialog.py b/src/gui/tasks/dialog.py new file mode 100644 index 0000000..2e0d8d4 --- /dev/null +++ b/src/gui/tasks/dialog.py @@ -0,0 +1,64 @@ +from PyQt5 import QtCore, QtWidgets + +from model.task import Task, ValidTaskForm + +import db.tasks +import gui.tasks.form.widget + +def add(database, parent_widget, add_task_signal): + + def on_add(form: ValidTaskForm): + task = db.tasks.insert(database.cursor(), form) + database.commit() + add_task_signal.emit(task) + + return widget(parent_widget, 'Add a task', 'add', None, on_add) + +def update(database, parent_widget, update_task_signal, row, task): + + def on_update(form: ValidTaskForm): + updated_task = db.tasks.update(database.cursor(), task, form) + update_task_signal.emit(row, updated_task) + database.commit() + + return widget(parent_widget, 'Modify a task', 'modify', task, on_update) + +def show_delete(database, table, rows): + confirm = QtWidgets.QMessageBox.question( + table, + 'Task deletion', + 'Do you really want to delete the selected tasks ?', + QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes, + QtWidgets.QMessageBox.Yes) + + if confirm == QtWidgets.QMessageBox.Yes: + db.tasks.delete(database.cursor(), table.model().row_ids(rows)) + database.commit() + table.model().delete_tasks(rows) + +def widget( + parent: QtWidgets.QWidget, + title: str, + action_title: str, + task: Task, + on_validated): + + dialog = QtWidgets.QDialog(parent) + dialog.setWindowTitle(title) + dialog.setMinimumSize(QtCore.QSize(320, 240)) + + layout = QtWidgets.QVBoxLayout(dialog) + dialog.setLayout(layout) + + def on_dialog_validated(form): + dialog.accept() + on_validated(form) + + layout.addWidget(gui.tasks.form.widget.widget( + parent = dialog, + action_title = action_title, + task = task, + on_validated = on_dialog_validated, + on_cancel = lambda: dialog.reject())) + + return dialog diff --git a/src/gui/tasks/modal.py b/src/gui/tasks/modal.py deleted file mode 100644 index 3662947..0000000 --- a/src/gui/tasks/modal.py +++ /dev/null @@ -1,32 +0,0 @@ -from PyQt5 import QtCore, QtWidgets - -from model.task import Task - -import gui.tasks.form.widget - -def dialog( - parent: QtWidgets.QWidget, - title: str, - action_title: str, - task: Task, - on_validated): - - dialog = QtWidgets.QDialog(parent) - dialog.setWindowTitle(title) - dialog.setMinimumSize(QtCore.QSize(320, 240)) - - layout = QtWidgets.QVBoxLayout(dialog) - dialog.setLayout(layout) - - layout.addWidget(gui.tasks.form.widget.widget( - parent = dialog, - action_title = action_title, - task = task, - on_validated = lambda form: on_dialog_validated(dialog, on_validated, form), - on_cancel = lambda: dialog.reject())) - - return dialog - -def on_dialog_validated(dialog, on_validated, f): - dialog.accept() - on_validated(f) diff --git a/src/gui/tasks/table/menu.py b/src/gui/tasks/table/menu.py index f89ec92..51f7330 100644 --- a/src/gui/tasks/table/menu.py +++ b/src/gui/tasks/table/menu.py @@ -1,7 +1,7 @@ from PyQt5 import QtWidgets import db.tasks -import gui.tasks.modal +import gui.tasks.dialog from model.task import Task, ValidTaskForm def open(database, table, update_task_signal, position): @@ -20,24 +20,6 @@ def open(database, table, update_task_signal, position): if action == modify_action and len(rows) == 1: row = list(rows)[0] task = table.model().get_at(row) - show_update_dialog(database, table, update_task_signal, row, task) + gui.tasks.dialog.update(database, table, update_task_signal, row, task).exec_() elif action == delete_action: - confirm = QtWidgets.QMessageBox.question(table, 'Task deletion', 'Do you really want to delete the selected tasks ?', QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.Yes) - if confirm == QtWidgets.QMessageBox.Yes: - db.tasks.delete(database.cursor(), table.model().row_ids(rows)) - database.commit() - table.model().delete_tasks(rows) - -def show_update_dialog(database, parent_widget, update_task_signal, row, task): - dialog = gui.tasks.modal.dialog( - parent_widget, - 'Modify a task', - 'modify', - task, - lambda form: on_update(database, update_task_signal, row, task, form)) - dialog.exec_() - -def on_update(database, update_task_signal, row, task: Task, form: ValidTaskForm): - task = db.tasks.update(database.cursor(), task, form) - update_task_signal.emit(row, task) - database.commit() + gui.tasks.dialog.show_delete(database, table, rows) diff --git a/src/gui/tasks/table/widget.py b/src/gui/tasks/table/widget.py index a990c0e..95ebe44 100644 --- a/src/gui/tasks/table/widget.py +++ b/src/gui/tasks/table/widget.py @@ -5,42 +5,67 @@ import db.tasks import gui.tasks.signal import gui.tasks.table.menu import gui.tasks.table.model +import gui.tasks.dialog +from model.task import Task, ValidTaskForm -def widget(database, parent, add_task_signal): - table = QtWidgets.QTableView(parent) +class Widget(QtWidgets.QTableView): - tasks = db.tasks.get(database.cursor()) - table_model = gui.tasks.table.model.TableModel(tasks) + def __init__(self, database, parent, add_task_signal): + super().__init__(parent) - table.setModel(table_model) - table.sortByColumn( + self._database = database + self._update_task_signal = gui.tasks.signal.UpdateTask() + + tasks = db.tasks.get(self._database.cursor()) + table_model = gui.tasks.table.model.TableModel(tasks) + + self.setModel(table_model) + self.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) + self.setSortingEnabled(True) + self.setSelectionBehavior(QtWidgets.QTableView.SelectRows) + self.horizontalHeader().setStretchLastSection(True) + self.resizeColumns() + + self.doubleClicked.connect(lambda index: self.on_double_click(index.row())) + + # Menu + self.setContextMenuPolicy(Qt.CustomContextMenu) + self.customContextMenuRequested.connect(lambda position: gui.tasks.table.menu.open(self._database, self, self._update_task_signal, position)) - update_task_signal = gui.tasks.signal.UpdateTask() + add_task_signal.get().connect(lambda task: self.insert(task)) + self._update_task_signal.get().connect(lambda row, task: self.update(row, task)) - # Menu - table.setContextMenuPolicy(Qt.CustomContextMenu) - table.customContextMenuRequested.connect(lambda position: gui.tasks.table.menu.open(database, table, update_task_signal, position)) + def insert(self, task): + self.model().insert_task(self.horizontalHeader(), task) + self.resizeColumns() - add_task_signal.get().connect(lambda task: insert(table, task)) - update_task_signal.get().connect(lambda row, task: update(table, row, task)) + def update(self, row, task): + row = self.model().update_task(self.horizontalHeader(), row, task) + self.selectRow(row) + self.resizeColumns() - return table + def resizeColumns(self): + for column in range(gui.tasks.table.model.columns): + self.resizeColumnToContents(column) -def insert(table, task): - table.model().insert_task(table.horizontalHeader(), task) - resizeColumns(table) + def keyPressEvent(self, event): + super().keyPressEvent(event) + if event.key() in (Qt.Key_Return, Qt.Key_Enter): + rows = self.get_selected_rows() + if len(rows) == 1: + row = rows[0] + task = self.model().get_at(row) + gui.tasks.dialog.update( + self._database, self, self._update_task_signal, row, task).exec_() + elif event.key() == Qt.Key_Delete: + rows = self.get_selected_rows() + gui.tasks.dialog.show_delete(self._database, self, rows) -def update(table, row, task): - row = table.model().update_task(table.horizontalHeader(), row, task) - table.selectRow(row) - resizeColumns(table) + def get_selected_rows(self): + return list(set([index.row() for index in self.selectedIndexes()])) -def resizeColumns(table): - for column in range(gui.tasks.table.model.columns): - table.resizeColumnToContents(column) + def on_double_click(self, row: int): + task = self.model().get_at(row) + gui.tasks.dialog.update(self._database, self, self._update_task_signal, row, task).exec_() diff --git a/src/gui/tasks/widget.py b/src/gui/tasks/widget.py index 6fa8bf0..0462f54 100644 --- a/src/gui/tasks/widget.py +++ b/src/gui/tasks/widget.py @@ -1,6 +1,5 @@ from PyQt5 import QtWidgets, QtCore -import db.tasks import gui.tasks.signal import gui.tasks.table.widget import gui.icons @@ -16,24 +15,11 @@ def widget(database, parent): 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)) + add_task_button.clicked.connect(lambda: gui.tasks.dialog.add( + database, widget, add_task_signal).exec_()) layout.addWidget(add_task_button) - table = gui.tasks.table.widget.widget(database, widget, add_task_signal) + 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 form: on_add(database, form, add_task_signal)) - dialog.exec_() - -def on_add(database, form: ValidTaskForm, add_task_signal): - task = db.tasks.insert(database.cursor(), form) - database.commit() - add_task_signal.emit(task) -- cgit v1.2.3