diff options
author | Joris | 2020-06-06 17:44:26 +0200 |
---|---|---|
committer | Joris | 2020-06-06 19:54:03 +0200 |
commit | 1595e0de940a86a7810df0e02e43838d97c0d846 (patch) | |
tree | 9701eeec0d98baa9f6044b1911df68e4c8539819 | |
parent | 6b9195000eb5404c247288b384d7ca2bacc1ab23 (diff) |
Provide nix build
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | README.md | 6 | ||||
-rwxr-xr-x | bin/test (renamed from scripts/test) | 2 | ||||
-rwxr-xr-x | bin/todo | 22 | ||||
-rw-r--r-- | default.nix | 34 | ||||
-rw-r--r-- | setup.py | 12 | ||||
-rw-r--r-- | shell.nix | 20 | ||||
-rw-r--r-- | src/gui/tags/panel/widget.py | 30 | ||||
-rw-r--r-- | src/gui/tasks/table/menu.py | 49 | ||||
-rw-r--r-- | src/gui/tasks/widget.py | 30 | ||||
-rw-r--r-- | src/gui/window.py | 36 | ||||
-rw-r--r-- | src/main.py | 20 | ||||
-rw-r--r-- | src/service/tasks.py | 32 | ||||
-rw-r--r-- | todo/__init__.py | 0 | ||||
-rw-r--r-- | todo/arguments.py (renamed from src/arguments.py) | 0 | ||||
-rw-r--r-- | todo/database.py (renamed from src/database.py) | 4 | ||||
-rw-r--r-- | todo/db/__init__.py | 0 | ||||
-rw-r--r-- | todo/db/init.py (renamed from src/db/init.py) | 0 | ||||
-rw-r--r-- | todo/db/tags.py (renamed from src/db/tags.py) | 2 | ||||
-rw-r--r-- | todo/db/task_tags.py (renamed from src/db/task_tags.py) | 2 | ||||
-rw-r--r-- | todo/db/tasks.py (renamed from src/db/tasks.py) | 6 | ||||
-rw-r--r-- | todo/gui/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/color.py (renamed from src/gui/color.py) | 0 | ||||
-rw-r--r-- | todo/gui/icon.py (renamed from src/gui/icon.py) | 0 | ||||
-rw-r--r-- | todo/gui/signal.py (renamed from src/gui/signal.py) | 0 | ||||
-rw-r--r-- | todo/gui/tags/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tags/list.py (renamed from src/gui/tags/list.py) | 8 | ||||
-rw-r--r-- | todo/gui/tags/panel/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tags/panel/dialog.py (renamed from src/gui/tags/panel/dialog.py) | 23 | ||||
-rw-r--r-- | todo/gui/tags/panel/form/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tags/panel/form/state.py (renamed from src/gui/tags/panel/form/state.py) | 2 | ||||
-rw-r--r-- | todo/gui/tags/panel/form/widget.py (renamed from src/gui/tags/panel/form/widget.py) | 16 | ||||
-rw-r--r-- | todo/gui/tags/panel/signal.py (renamed from src/gui/tags/panel/signal.py) | 2 | ||||
-rw-r--r-- | todo/gui/tags/panel/table/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tags/panel/table/menu.py (renamed from src/gui/tags/panel/table/menu.py) | 19 | ||||
-rw-r--r-- | todo/gui/tags/panel/table/model.py (renamed from src/gui/tags/panel/table/model.py) | 13 | ||||
-rw-r--r-- | todo/gui/tags/panel/table/widget.py (renamed from src/gui/tags/panel/table/widget.py) | 38 | ||||
-rw-r--r-- | todo/gui/tags/panel/widget.py | 30 | ||||
-rw-r--r-- | todo/gui/tasks/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tasks/dialog.py (renamed from src/gui/tasks/dialog.py) | 20 | ||||
-rw-r--r-- | todo/gui/tasks/duration.py (renamed from src/gui/tasks/duration.py) | 8 | ||||
-rw-r--r-- | todo/gui/tasks/form/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tasks/form/state.py (renamed from src/gui/tasks/form/state.py) | 14 | ||||
-rw-r--r-- | todo/gui/tasks/form/widget.py (renamed from src/gui/tasks/form/widget.py) | 24 | ||||
-rw-r--r-- | todo/gui/tasks/signal.py (renamed from src/gui/tasks/signal.py) | 2 | ||||
-rw-r--r-- | todo/gui/tasks/table/__init__.py | 0 | ||||
-rw-r--r-- | todo/gui/tasks/table/menu.py | 48 | ||||
-rw-r--r-- | todo/gui/tasks/table/widget.py (renamed from src/gui/tasks/table/widget.py) | 89 | ||||
-rw-r--r-- | todo/gui/tasks/test_duration.py (renamed from src/gui/tasks/test_duration.py) | 2 | ||||
-rw-r--r-- | todo/gui/tasks/widget.py | 30 | ||||
-rw-r--r-- | todo/gui/window.py | 36 | ||||
-rw-r--r-- | todo/model/__init__.py | 0 | ||||
-rw-r--r-- | todo/model/difficulty.py (renamed from src/model/difficulty.py) | 0 | ||||
-rw-r--r-- | todo/model/priority.py (renamed from src/model/priority.py) | 0 | ||||
-rw-r--r-- | todo/model/status.py (renamed from src/model/status.py) | 0 | ||||
-rw-r--r-- | todo/model/tag.py (renamed from src/model/tag.py) | 0 | ||||
-rw-r--r-- | todo/model/task.py (renamed from src/model/task.py) | 4 | ||||
-rw-r--r-- | todo/model/task_tag.py (renamed from src/model/task_tag.py) | 0 | ||||
-rw-r--r-- | todo/service/__init__.py | 0 | ||||
-rw-r--r-- | todo/service/tasks.py | 32 | ||||
-rw-r--r-- | todo/util/__init__.py | 0 | ||||
-rw-r--r-- | todo/util/array.py (renamed from src/util/array.py) | 0 | ||||
-rw-r--r-- | todo/util/range.py (renamed from src/util/range.py) | 0 | ||||
-rw-r--r-- | todo/util/test_array.py (renamed from src/util/test_array.py) | 2 | ||||
-rw-r--r-- | todo/util/test_range.py (renamed from src/util/test_range.py) | 2 |
65 files changed, 397 insertions, 375 deletions
@@ -1,2 +1,3 @@ __pycache__ database +result @@ -1,4 +1,4 @@ -# todo-next +# todo Manage a context-based next-action list, compatible with the [GTD](https://en.wikipedia.org/wiki/Getting_Things_Done) method. @@ -6,13 +6,13 @@ Manage a context-based next-action list, compatible with the ## Getting started ```bash -nix-shell --run "python src/main.py" +nix-shell --run bin/todo ``` ## Tests ```bash -scripts/test +nix-shell --run bin/test ``` ## Links @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -euo pipefail -cd "$(dirname $0)/../src" +cd "$(dirname $0)/.." python -m pytest diff --git a/bin/todo b/bin/todo new file mode 100755 index 0000000..c743d0d --- /dev/null +++ b/bin/todo @@ -0,0 +1,22 @@ +#!/usr/bin/env python +import sys +from PyQt5 import QtCore, QtWidgets +import sqlite3 +import os.path + +import todo.database +import todo.db.init +import todo.gui.window +import todo.arguments +import todo.database + +args = todo.arguments.parser().parse_args() +todo.database.init(args.database if args.database != None else "database") +app = QtWidgets.QApplication(sys.argv) + +window = todo.gui.window.get() +window.show() +res = app.exec_() + +todo.database.close() +sys.exit(res) diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..4430918 --- /dev/null +++ b/default.nix @@ -0,0 +1,34 @@ +with (import (builtins.fetchGit { + name = "nixpkgs-20.03"; + url = "git@github.com:nixos/nixpkgs.git"; + rev = "5272327b81ed355bbed5659b8d303cf2979b6953"; + ref = "refs/tags/20.03"; +}) {}); + +python38Packages.buildPythonApplication rec { + pname = "todo"; + version = "0.1.0"; + + src = ./.; + + buildInputs = [ + qt5.qtbase + sqlite + ]; + + propagatedBuildInputs = with python38Packages; [ + pyqt5 + pytest + ]; + + makeWrapperArgs = [ + "--set QT_QPA_PLATFORM_PLUGIN_PATH ${qt5.qtbase.bin}/lib/qt-*/plugins/platforms" + "--set QT_PLUGIN_PATH ${qt5.qtbase.bin}/lib/qt-*/plugins" + ]; + + shellHook = '' + export QT_QPA_PLATFORM_PLUGIN_PATH="$(echo ${qt5.qtbase.bin}/lib/qt-*/plugins/platforms)" + export QT_PLUGIN_PATH="$(echo ${qt5.qtbase.bin}/lib/qt-*/plugins)" + export PYTHONPATH=./:$PYTHONPATH # Give access to kiosk_browser module + ''; +} diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..31fac1e --- /dev/null +++ b/setup.py @@ -0,0 +1,12 @@ +import setuptools + +setuptools.setup( + name="todo", + version="0.1.0", + author="Joris Guyonvarch", + description="Context based next-action list manager", + long_description_content_type="text/markdown", + url="https://gitlab.com/guyonvarch/todo/", + packages=setuptools.find_packages(), + scripts=['bin/todo'] +) diff --git a/shell.nix b/shell.nix deleted file mode 100644 index bb95254..0000000 --- a/shell.nix +++ /dev/null @@ -1,20 +0,0 @@ -with (import (builtins.fetchGit { - name = "nixpkgs-20.03"; - url = "git@github.com:nixos/nixpkgs.git"; - rev = "5272327b81ed355bbed5659b8d303cf2979b6953"; - ref = "refs/tags/20.03"; -}) {}); - -mkShell { - - buildInputs = [ - qt5.full - sqlite - ]; - - propagatedBuildInputs = [ - python38Packages.pyqt5 - python38Packages.pytest - ]; - -} diff --git a/src/gui/tags/panel/widget.py b/src/gui/tags/panel/widget.py deleted file mode 100644 index faca1da..0000000 --- a/src/gui/tags/panel/widget.py +++ /dev/null @@ -1,30 +0,0 @@ -from PyQt5 import QtWidgets - -import gui.tags.panel.dialog -import gui.tags.panel.signal -import gui.tags.panel.table.widget -import gui.icon - -def widget(parent): - widget = QtWidgets.QWidget(parent) - - layout = QtWidgets.QVBoxLayout(widget) - widget.setLayout(layout) - - layout.addSpacing(15) - - add_tag_signal = gui.tags.panel.signal.AddTag() - - add_tag_button = QtWidgets.QPushButton(" Add a tag", widget) - add_tag_button.setFixedHeight(30) - add_tag_button.setIcon(gui.icon.new_folder(widget.style())) - - add_tag_button.clicked.connect(lambda: gui.tags.panel.dialog.add(widget, add_tag_signal).exec_()) - layout.addWidget(add_tag_button) - - layout.addSpacing(20) - - table = gui.tags.panel.table.widget.Widget(widget, add_tag_signal) - layout.addWidget(table) - - return widget diff --git a/src/gui/tasks/table/menu.py b/src/gui/tasks/table/menu.py deleted file mode 100644 index 5356be2..0000000 --- a/src/gui/tasks/table/menu.py +++ /dev/null @@ -1,49 +0,0 @@ -from PyQt5 import QtWidgets, QtCore -from typing import List - -import db.tasks -import gui.tasks.dialog -from model.status import Status -from model.task import Task, ValidTaskForm -from model.tag import Tag - -def open(table: QtWidgets.QTableWidget, status: Status, update_task_signal, position): - rows = set([index.row() for index in table.selectedIndexes()]) - - menu = QtWidgets.QMenu(table) - - if len(rows) == 1: - modify_action = menu.addAction(gui.icon.dialog_open(menu.style()), "modify") - else: - modify_action = QtWidgets.QAction(menu) - - delete_action = menu.addAction(gui.icon.trash(menu.style()), "delete") - - if status != Status.READY: - move_to_ready = menu.addAction(gui.icon.task_ready(menu.style()), "move to ready") - else: - move_to_ready = QtWidgets.QAction(menu) - - if status != Status.WAITING: - move_to_waiting = menu.addAction(gui.icon.task_waiting(menu.style()), "move to waiting") - else: - move_to_waiting = QtWidgets.QAction(menu) - - if status != Status.MAYBE: - move_to_maybe = menu.addAction(gui.icon.task_maybe(menu.style()), "move to maybe") - else: - move_to_maybe = QtWidgets.QAction(menu) - - action = menu.exec_(table.mapToGlobal(position + QtCore.QPoint(15, 20))) - if action == modify_action and len(rows) == 1: - row = list(rows)[0] - (task, tags) = table.get_at(row) - gui.tasks.dialog.update(table, update_task_signal, row, task, tags).exec_() - elif action == delete_action: - gui.tasks.dialog.confirm_delete(table, rows, lambda: table.delete_rows(rows)) - elif action == move_to_ready: - gui.tasks.dialog.confirm_move(table, rows, Status.READY, lambda: table.update_status(rows, Status.READY)) - elif action == move_to_waiting: - gui.tasks.dialog.confirm_move(table, rows, Status.WAITING, lambda: table.update_status(rows, Status.WAITING)) - elif action == move_to_maybe: - gui.tasks.dialog.confirm_move(table, rows, Status.MAYBE, lambda: table.update_status(rows, Status.MAYBE)) diff --git a/src/gui/tasks/widget.py b/src/gui/tasks/widget.py deleted file mode 100644 index 87b15d3..0000000 --- a/src/gui/tasks/widget.py +++ /dev/null @@ -1,30 +0,0 @@ -from PyQt5 import QtWidgets - -from model.status import Status -import gui.tasks.signal -import gui.tasks.table.widget -import gui.icon -import gui.signal - -def widget(parent, on_show: gui.signal.Reload, status: Status): - widget = QtWidgets.QWidget(parent) - - layout = QtWidgets.QVBoxLayout(widget) - widget.setLayout(layout) - - layout.addSpacing(15) - - add_task_signal = gui.tasks.signal.AddTask() - - add_task_button = QtWidgets.QPushButton(" Add a task", widget) - add_task_button.setFixedHeight(30) - add_task_button.setIcon(gui.icon.new_folder(widget.style())) - add_task_button.clicked.connect(lambda: gui.tasks.dialog.add(widget, status, add_task_signal).exec_()) - layout.addWidget(add_task_button) - - layout.addSpacing(20) - - table = gui.tasks.table.widget.Widget(widget, on_show, add_task_signal, status) - layout.addWidget(table) - - return widget diff --git a/src/gui/window.py b/src/gui/window.py deleted file mode 100644 index 584fda6..0000000 --- a/src/gui/window.py +++ /dev/null @@ -1,36 +0,0 @@ -from PyQt5 import QtCore, QtWidgets - -import gui.tasks.widget -import gui.tasks.widget -import gui.tags.panel.widget -import gui.signal -from model.status import Status - -def get(): - window = QtWidgets.QMainWindow() - window.setWindowTitle("todo-next") - window.setMinimumSize(QtCore.QSize(640, 480)) - - tabs = QtWidgets.QTabWidget(window) - window.setCentralWidget(tabs) - - show_ready = gui.signal.Reload() - show_waiting = gui.signal.Reload() - show_maybe = gui.signal.Reload() - - def on_current_tab_changed(index: int): - if index == 0: - show_ready.emit() - elif index == 1: - show_waiting.emit() - elif index == 2: - show_maybe.emit() - - tabs.currentChanged.connect(on_current_tab_changed) - - tabs.addTab(gui.tasks.widget.widget(tabs, show_ready, Status.READY), "Ready") - tabs.addTab(gui.tasks.widget.widget(tabs, show_waiting, Status.WAITING), "Waiting") - tabs.addTab(gui.tasks.widget.widget(tabs, show_maybe, Status.MAYBE), "Maybe") - tabs.addTab(gui.tags.panel.widget.widget(tabs), "Tags") - - return window diff --git a/src/main.py b/src/main.py deleted file mode 100644 index f89872a..0000000 --- a/src/main.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys -from PyQt5 import QtCore, QtWidgets -import sqlite3 -import os.path - -import db.init -import gui.window -import arguments -import database - -args = arguments.parser().parse_args() -database.init(args.database if args.database != None else "database") -app = QtWidgets.QApplication(sys.argv) - -window = gui.window.get() -window.show() -res = app.exec_() - -database.close() -sys.exit(res) diff --git a/src/service/tasks.py b/src/service/tasks.py deleted file mode 100644 index 87194c4..0000000 --- a/src/service/tasks.py +++ /dev/null @@ -1,32 +0,0 @@ -from typing import List - -from model.task import Task, ValidTaskForm -from model.status import Status -import db.tasks -import db.task_tags -import database - -def get(cursor, status: Status) -> List[Task]: - return db.tasks.get(cursor, status) - -def create(cursor, status: Status, task_form: ValidTaskForm) -> Task: - task = db.tasks.insert(cursor, status, task_form) - db.task_tags.insert_many(cursor, task.id, task_form.tags) - database.commit() - return task - -def update(cursor, task: Task, task_form: ValidTaskForm) -> Task: - db.task_tags.delete(cursor, [task.id]) - updated_task = db.tasks.update(cursor, task, task_form) - db.task_tags.insert_many(cursor, task.id, task_form.tags) - database.commit() - return updated_task - -def delete(cursor, task_ids: List[int]): - db.task_tags.delete(cursor, task_ids) - db.tasks.delete(cursor, task_ids) - database.commit() - -def update_status(cursor, task_ids: List[int], status: Status) -> List[Task]: - db.tasks.update_status(cursor, task_ids, status) - database.commit() diff --git a/todo/__init__.py b/todo/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/__init__.py diff --git a/src/arguments.py b/todo/arguments.py index bb60dce..bb60dce 100644 --- a/src/arguments.py +++ b/todo/arguments.py diff --git a/src/database.py b/todo/database.py index 478f62e..b571e88 100644 --- a/src/database.py +++ b/todo/database.py @@ -1,10 +1,10 @@ -import db.init +import todo.db.init _database = None def init(path): global _database - _database = db.init.init(path) + _database = todo.db.init.init(path) def cursor(): global _database diff --git a/todo/db/__init__.py b/todo/db/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/db/__init__.py diff --git a/src/db/init.py b/todo/db/init.py index 5d847a3..5d847a3 100644 --- a/src/db/init.py +++ b/todo/db/init.py diff --git a/src/db/tags.py b/todo/db/tags.py index 666bd1e..c5ce33c 100644 --- a/src/db/tags.py +++ b/todo/db/tags.py @@ -2,7 +2,7 @@ from sqlite3 import Cursor import time from typing import List -from model.tag import Tag, ValidTagForm +from todo.model.tag import Tag, ValidTagForm def get(cursor: Cursor) -> List[Tag]: cursor.execute( diff --git a/src/db/task_tags.py b/todo/db/task_tags.py index e8c0ee0..0fae5f9 100644 --- a/src/db/task_tags.py +++ b/todo/db/task_tags.py @@ -2,7 +2,7 @@ from sqlite3 import Cursor import time from typing import List -from model.task_tag import TaskTag +from todo.model.task_tag import TaskTag def one_is_used(cursor: Cursor, tag_ids: List[int]) -> bool: if len(tag_ids) >= 1: diff --git a/src/db/tasks.py b/todo/db/tasks.py index efb88d6..fc23bf0 100644 --- a/src/db/tasks.py +++ b/todo/db/tasks.py @@ -2,9 +2,9 @@ from sqlite3 import Cursor import time from typing import List -from model.task import Task, ValidTaskForm -from model.status import Status -from model import difficulty, priority, status +from todo.model.task import Task, ValidTaskForm +from todo.model.status import Status +from todo.model import difficulty, priority, status def get(cursor: Cursor, s: Status) -> List[Task]: cursor.execute( diff --git a/todo/gui/__init__.py b/todo/gui/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/__init__.py diff --git a/src/gui/color.py b/todo/gui/color.py index cc7e5a8..cc7e5a8 100644 --- a/src/gui/color.py +++ b/todo/gui/color.py diff --git a/src/gui/icon.py b/todo/gui/icon.py index 7e2156d..7e2156d 100644 --- a/src/gui/icon.py +++ b/todo/gui/icon.py diff --git a/src/gui/signal.py b/todo/gui/signal.py index 99100f1..99100f1 100644 --- a/src/gui/signal.py +++ b/todo/gui/signal.py diff --git a/todo/gui/tags/__init__.py b/todo/gui/tags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tags/__init__.py diff --git a/src/gui/tags/list.py b/todo/gui/tags/list.py index f7eeba3..d0374ed 100644 --- a/src/gui/tags/list.py +++ b/todo/gui/tags/list.py @@ -1,9 +1,9 @@ from PyQt5 import QtWidgets, QtCore from typing import List, Tuple -from model.tag import Tag -import db.tags -import database +from todo.model.tag import Tag +import todo.db.tags +import todo.database class SelectionSignal(QtCore.QObject): _signal = QtCore.pyqtSignal(list, name = "selection") @@ -30,7 +30,7 @@ def widget(parent, init_tags: List[int]) -> Tuple[QtWidgets.QWidget, SelectionSi list_widget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection) layout.addWidget(list_widget) - tags = db.tags.get(database.cursor()) + tags = todo.db.tags.get(todo.database.cursor()) for tag in tags: item = QtWidgets.QListWidgetItem(tag.name) diff --git a/todo/gui/tags/panel/__init__.py b/todo/gui/tags/panel/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tags/panel/__init__.py diff --git a/src/gui/tags/panel/dialog.py b/todo/gui/tags/panel/dialog.py index f0ca986..f1a669c 100644 --- a/src/gui/tags/panel/dialog.py +++ b/todo/gui/tags/panel/dialog.py @@ -1,16 +1,15 @@ from PyQt5 import QtCore, QtWidgets -from model.tag import Tag, ValidTagForm - -import db.tags -import gui.tags.panel.form.widget -import database +from todo.model.tag import Tag, ValidTagForm +import todo.db.tags +import todo.gui.tags.panel.form.widget +import todo.database def add(parent_widget, add_tag_signal): def on_add(form: ValidTagForm): - tag = db.tags.insert(database.cursor(), form) - database.commit() + tag = todo.db.tags.insert(todo.database.cursor(), form) + todo.database.commit() add_tag_signal.emit(tag) return widget(parent_widget, "Add a tag", "add", None, on_add) @@ -18,9 +17,9 @@ def add(parent_widget, add_tag_signal): def update(parent_widget, update_tag_signal, row, tag): def on_update(form: ValidTagForm): - updated_tag = db.tags.update(database.cursor(), tag, form) + updated_tag = todo.db.tags.update(todo.database.cursor(), tag, form) update_tag_signal.emit(row, updated_tag) - database.commit() + todo.database.commit() return widget(parent_widget, "Modify a tag", "modify", tag, on_update) @@ -33,8 +32,8 @@ def show_delete(table, rows): QtWidgets.QMessageBox.Yes) if confirm == QtWidgets.QMessageBox.Yes: - db.tags.delete(database.cursor(), table.model().row_ids(rows)) - database.commit() + todo.db.tags.delete(todo.database.cursor(), table.model().row_ids(rows)) + todo.database.commit() table.model().delete_tags(rows) def widget( @@ -55,7 +54,7 @@ def widget( dialog.accept() on_validated(form) - layout.addWidget(gui.tags.panel.form.widget.widget( + layout.addWidget(todo.gui.tags.panel.form.widget.widget( parent = dialog, action_title = action_title, tag = tag, diff --git a/todo/gui/tags/panel/form/__init__.py b/todo/gui/tags/panel/form/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tags/panel/form/__init__.py diff --git a/src/gui/tags/panel/form/state.py b/todo/gui/tags/panel/form/state.py index fbec956..f898ac4 100644 --- a/src/gui/tags/panel/form/state.py +++ b/todo/gui/tags/panel/form/state.py @@ -1,7 +1,7 @@ from PyQt5 import QtCore from typing import Optional -from model.tag import ValidTagForm +from todo.model.tag import ValidTagForm class TagFormEdition: def __init__( diff --git a/src/gui/tags/panel/form/widget.py b/todo/gui/tags/panel/form/widget.py index 7079e57..9ac4eb1 100644 --- a/src/gui/tags/panel/form/widget.py +++ b/todo/gui/tags/panel/form/widget.py @@ -1,11 +1,11 @@ from PyQt5 import QtWidgets, QtCore, QtGui from typing import Optional, Tuple, List, Any -from model.tag import Tag, ValidTagForm -from model import difficulty, priority -import gui.icon -import gui.tags.panel.form.state -import gui.color +from todo.model.tag import Tag, ValidTagForm +from todo.model import difficulty, priority +import todo.gui.icon +import todo.gui.tags.panel.form.state +import todo.gui.color def widget( parent: QtWidgets.QWidget, @@ -29,7 +29,7 @@ def widget( init_color = tag.color if tag is not None else "#FFFFFF" color_input = color_edit(grid, grid_layout, 1, "Color", QtGui.QColor(init_color)) - tag_form_edition = gui.tags.panel.form.state.TagFormEdition( + tag_form_edition = todo.gui.tags.panel.form.state.TagFormEdition( init_name, name_input.textChanged, init_color, @@ -117,7 +117,7 @@ def buttons(parent, action_title, tag_form_signal, on_validate, on_cancel): validate = QtWidgets.QPushButton(action_title, widget) validate.setDisabled(True) - validate.setIcon(gui.icon.dialog_ok(validate.style())) + validate.setIcon(todo.gui.icon.dialog_ok(validate.style())) validate.clicked.connect(on_validate); layout.addWidget(validate) @@ -130,7 +130,7 @@ def buttons(parent, action_title, tag_form_signal, on_validate, on_cancel): tag_form_signal.connect(on_tag_form_signal) cancel = QtWidgets.QPushButton("cancel", widget) - cancel.setIcon(gui.icon.dialog_cancel(cancel.style())) + cancel.setIcon(todo.gui.icon.dialog_cancel(cancel.style())) cancel.clicked.connect(on_cancel) layout.addWidget(cancel) diff --git a/src/gui/tags/panel/signal.py b/todo/gui/tags/panel/signal.py index 022abde..97065cd 100644 --- a/src/gui/tags/panel/signal.py +++ b/todo/gui/tags/panel/signal.py @@ -1,6 +1,6 @@ from PyQt5 import QtCore -from model.tag import Tag +from todo.model.tag import Tag class AddTag(QtCore.QObject): _signal = QtCore.pyqtSignal(Tag, name = "addTag") diff --git a/todo/gui/tags/panel/table/__init__.py b/todo/gui/tags/panel/table/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tags/panel/table/__init__.py diff --git a/src/gui/tags/panel/table/menu.py b/todo/gui/tags/panel/table/menu.py index f9ee148..e286051 100644 --- a/src/gui/tags/panel/table/menu.py +++ b/todo/gui/tags/panel/table/menu.py @@ -1,10 +1,9 @@ from PyQt5 import QtWidgets, QtCore -from model.tag import Tag, ValidTagForm -import database -import db.tags -import db.task_tags -import gui.tags.panel.dialog +from todo.model.tag import Tag, ValidTagForm +import todo.database +import todo.db.task_tags +import todo.gui.tags.panel.dialog def open(table, update_tag_signal, position): rows = set([index.row() for index in table.selectedIndexes()]) @@ -14,14 +13,14 @@ def open(table, update_tag_signal, position): actions = 0 if len(rows) == 1: - modify_action = menu.addAction(gui.icon.dialog_open(menu.style()), "modify") + modify_action = menu.addAction(todo.gui.icon.dialog_open(menu.style()), "modify") actions += 1 else: modify_action = QtWidgets.QAction(menu) tags = table.model().row_ids(rows) - if not db.task_tags.one_is_used(database.cursor(), tags): - delete_action = menu.addAction(gui.icon.trash(menu.style()), "delete") + if not todo.db.task_tags.one_is_used(todo.database.cursor(), tags): + delete_action = menu.addAction(todo.gui.icon.trash(menu.style()), "delete") actions += 1 else: delete_action = QtWidgets.QAction(menu) @@ -31,6 +30,6 @@ def open(table, update_tag_signal, position): if action == modify_action and len(rows) == 1: row = list(rows)[0] tag = table.model().get_at(row) - gui.tags.panel.dialog.update(table, update_tag_signal, row, tag).exec_() + todo.gui.tags.panel.dialog.update(table, update_tag_signal, row, tag).exec_() elif action == delete_action: - gui.tags.panel.dialog.show_delete(table, rows) + todo.gui.tags.panel.dialog.show_delete(table, rows) diff --git a/src/gui/tags/panel/table/model.py b/todo/gui/tags/panel/table/model.py index 00ca785..6f9d71a 100644 --- a/src/gui/tags/panel/table/model.py +++ b/todo/gui/tags/panel/table/model.py @@ -1,13 +1,12 @@ from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5.QtCore import Qt from typing import List - -from model.tag import Tag import time import math -import util.array -import util.range -import gui.color + +from todo.model.tag import Tag +import todo.util.array +import todo.util.range columns = 1 @@ -62,7 +61,7 @@ class TableModel(QtCore.QAbstractTableModel): row = header.sortIndicatorSection() order = header.sortIndicatorOrder() is_rev = is_reversed(row, order) - return util.array.insert_position( + return todo.util.array.insert_position( sort_key(tag, row, is_rev), [sort_key(t, row, is_rev) for t in self._tags], is_rev) @@ -72,7 +71,7 @@ class TableModel(QtCore.QAbstractTableModel): return self.insert_tag(header, tag) def delete_tags(self, indexes): - for range in reversed(util.range.from_indexes(indexes)): + for range in reversed(todo.util.range.from_indexes(indexes)): self.delete_tag_range(range.start, range.length) return True diff --git a/src/gui/tags/panel/table/widget.py b/todo/gui/tags/panel/table/widget.py index 0ef67c2..b36759d 100644 --- a/src/gui/tags/panel/table/widget.py +++ b/todo/gui/tags/panel/table/widget.py @@ -1,29 +1,29 @@ from PyQt5 import QtWidgets from PyQt5.QtCore import Qt -from model.tag import Tag, ValidTagForm -import database -import db.tags -import db.task_tags -import gui.tags.panel.dialog -import gui.tags.panel.signal -import gui.tags.panel.table.menu -import gui.tags.panel.table.model +from todo.model.tag import Tag, ValidTagForm +import todo.database +import todo.db.tags +import todo.db.task_tags +import todo.gui.tags.panel.dialog +import todo.gui.tags.panel.signal +import todo.gui.tags.panel.table.menu +import todo.gui.tags.panel.table.model class Widget(QtWidgets.QTableView): def __init__(self, parent, add_tag_signal): super().__init__(parent) - self._update_tag_signal = gui.tags.panel.signal.UpdateTag() + self._update_tag_signal = todo.gui.tags.panel.signal.UpdateTag() - tags = db.tags.get(database.cursor()) - table_model = gui.tags.panel.table.model.TableModel(tags) + tags = todo.db.tags.get(todo.database.cursor()) + table_model = todo.gui.tags.panel.table.model.TableModel(tags) self.setModel(table_model) self.sortByColumn( - gui.tags.panel.table.model.default_sort[0], - gui.tags.panel.table.model.default_sort[1]) + todo.gui.tags.panel.table.model.default_sort[0], + todo.gui.tags.panel.table.model.default_sort[1]) self.setSortingEnabled(True) self.setSelectionBehavior(QtWidgets.QTableView.SelectRows) self.horizontalHeader().setStretchLastSection(True) @@ -33,7 +33,7 @@ class Widget(QtWidgets.QTableView): # # Menu self.setContextMenuPolicy(Qt.CustomContextMenu) - self.customContextMenuRequested.connect(lambda position: gui.tags.panel.table.menu.open(self, self._update_tag_signal, position)) + self.customContextMenuRequested.connect(lambda position: todo.gui.tags.panel.table.menu.open(self, self._update_tag_signal, position)) add_tag_signal.connect(lambda tag: self.insert(tag)) self._update_tag_signal.connect(lambda row, tag: self.update(row, tag)) @@ -48,7 +48,7 @@ class Widget(QtWidgets.QTableView): self.resizeColumns() def resizeColumns(self): - for column in range(gui.tags.panel.table.model.columns): + for column in range(todo.gui.tags.panel.table.model.columns): self.resizeColumnToContents(column) def keyPressEvent(self, event): @@ -58,16 +58,16 @@ class Widget(QtWidgets.QTableView): if len(rows) == 1: row = rows[0] tag = self.model().get_at(row) - gui.tags.panel.dialog.update(self, self._update_tag_signal, row, tag).exec_() + todo.gui.tags.panel.dialog.update(self, self._update_tag_signal, row, tag).exec_() elif event.key() == Qt.Key_Delete: rows = self.get_selected_rows() tags = self.model().row_ids(rows) - if not db.task_tags.one_is_used(database.cursor(), tags): - gui.tags.panel.dialog.show_delete(self, rows) + if not db.task_tags.one_is_used(todo.database.cursor(), tags): + todo.gui.tags.panel.dialog.show_delete(self, rows) def get_selected_rows(self): return list(set([index.row() for index in self.selectedIndexes()])) def on_double_click(self, row: int): tag = self.model().get_at(row) - gui.tags.panel.dialog.update(self, self._update_tag_signal, row, tag).exec_() + todo.gui.tags.panel.dialog.update(self, self._update_tag_signal, row, tag).exec_() diff --git a/todo/gui/tags/panel/widget.py b/todo/gui/tags/panel/widget.py new file mode 100644 index 0000000..071442e --- /dev/null +++ b/todo/gui/tags/panel/widget.py @@ -0,0 +1,30 @@ +from PyQt5 import QtWidgets + +import todo.gui.tags.panel.dialog +import todo.gui.tags.panel.signal +import todo.gui.tags.panel.table.widget +import todo.gui.icon + +def widget(parent): + widget = QtWidgets.QWidget(parent) + + layout = QtWidgets.QVBoxLayout(widget) + widget.setLayout(layout) + + layout.addSpacing(15) + + add_tag_signal = todo.gui.tags.panel.signal.AddTag() + + add_tag_button = QtWidgets.QPushButton(" Add a tag", widget) + add_tag_button.setFixedHeight(30) + add_tag_button.setIcon(todo.gui.icon.new_folder(widget.style())) + + add_tag_button.clicked.connect(lambda: todo.gui.tags.panel.dialog.add(widget, add_tag_signal).exec_()) + layout.addWidget(add_tag_button) + + layout.addSpacing(20) + + table = todo.gui.tags.panel.table.widget.Widget(widget, add_tag_signal) + layout.addWidget(table) + + return widget diff --git a/todo/gui/tasks/__init__.py b/todo/gui/tasks/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tasks/__init__.py diff --git a/src/gui/tasks/dialog.py b/todo/gui/tasks/dialog.py index 2bf3b6b..c2bd164 100644 --- a/src/gui/tasks/dialog.py +++ b/todo/gui/tasks/dialog.py @@ -1,19 +1,17 @@ from PyQt5 import QtCore, QtWidgets from typing import List -from model.tag import Tag -from model.task import Task, ValidTaskForm -from model.status import Status -import database -import db.task_tags -import db.tasks -import gui.tasks.form.widget -import service.tasks +from todo.model.tag import Tag +from todo.model.task import Task, ValidTaskForm +from todo.model.status import Status +import todo.database +import todo.gui.tasks.form.widget +import todo.service.tasks def add(parent_widget, status: Status, add_task_signal): def on_add(task_form: ValidTaskForm): - task = service.tasks.create(database.cursor(), status, task_form) + task = todo.service.tasks.create(todo.database.cursor(), status, task_form) add_task_signal.emit(task, task_form.tags) return widget(parent_widget, "Add a task", "add", None, [], on_add) @@ -21,7 +19,7 @@ def add(parent_widget, status: Status, add_task_signal): def update(parent_widget, update_task_signal, row: int, task: Task, tags: List[int]): def on_update(task_form: ValidTaskForm): - updated_task = service.tasks.update(database.cursor(), task, task_form) + updated_task = todo.service.tasks.update(todo.database.cursor(), task, task_form) update_task_signal.emit(row, updated_task, task_form.tags) return widget(parent_widget, "Modify a task", "modify", task, tags, on_update) @@ -67,7 +65,7 @@ def widget( dialog.accept() on_validated(form) - layout.addWidget(gui.tasks.form.widget.widget( + layout.addWidget(todo.gui.tasks.form.widget.widget( parent = dialog, action_title = action_title, task = task, diff --git a/src/gui/tasks/duration.py b/todo/gui/tasks/duration.py index dc948e6..81db661 100644 --- a/src/gui/tasks/duration.py +++ b/todo/gui/tasks/duration.py @@ -3,7 +3,7 @@ from typing import Optional import math import re -import gui.color +import todo.gui.color def format(minutes: int): if minutes >= 60 * 24: @@ -43,8 +43,8 @@ def parse(duration: str) -> Optional[int]: def color(minutes: int): if minutes <= 15: - return gui.color.short_duration + return todo.gui.color.short_duration elif minutes < 60: - return gui.color.medium_duration + return todo.gui.color.medium_duration else: - return gui.color.long_duration + return todo.gui.color.long_duration diff --git a/todo/gui/tasks/form/__init__.py b/todo/gui/tasks/form/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tasks/form/__init__.py diff --git a/src/gui/tasks/form/state.py b/todo/gui/tasks/form/state.py index 09e658e..33b0873 100644 --- a/src/gui/tasks/form/state.py +++ b/todo/gui/tasks/form/state.py @@ -1,11 +1,11 @@ from PyQt5 import QtCore from typing import Optional -from model.task import ValidTaskForm -from model.difficulty import Difficulty -from model.priority import Priority -import gui.tasks.duration -import gui.tags.list +from todo.model.task import ValidTaskForm +from todo.model.difficulty import Difficulty +from todo.model.priority import Priority +import todo.gui.tasks.duration +import todo.gui.tags.list class TaskFormEdition: def __init__( @@ -18,7 +18,7 @@ class TaskFormEdition: difficulty_signal, priority, priority_signal, - tags_signal: gui.tags.list.SelectionSignal, + tags_signal: todo.gui.tags.list.SelectionSignal, description, description_signal): @@ -39,7 +39,7 @@ class TaskFormEdition: def get(self) -> Optional[ValidTaskForm]: name = self._name.strip() - duration = gui.tasks.duration.parse(self._duration) + duration = todo.gui.tasks.duration.parse(self._duration) difficulty = self._difficulty priority = self._priority description = self._description.strip() diff --git a/src/gui/tasks/form/widget.py b/todo/gui/tasks/form/widget.py index 70d506d..15be21b 100644 --- a/src/gui/tasks/form/widget.py +++ b/todo/gui/tasks/form/widget.py @@ -1,13 +1,13 @@ from PyQt5 import QtWidgets, QtCore from typing import Optional, Tuple, List, Any -from model.task import Task, ValidTaskForm -from model.tag import Tag -from model import difficulty, priority -import gui.icon -import gui.tasks.form.state -import gui.tasks.duration -import gui.tags.list +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") @@ -41,7 +41,7 @@ def widget( 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 "" + 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 @@ -69,7 +69,7 @@ def widget( (description_input, description_signal) = text_edit(widget, "Description", init_description) layout.addWidget(description_input) - task_form_edition = gui.tasks.form.state.TaskFormEdition( + task_form_edition = todo.gui.tasks.form.state.TaskFormEdition( init_name, name_input.textChanged, init_duration, @@ -134,7 +134,7 @@ def combo_box( return box def tags_selection(parent, init_tags: List[int]) -> QtWidgets.QWidget: - return gui.tags.list.widget(parent, init_tags) + return todo.gui.tags.list.widget(parent, init_tags) def text_edit( parent, @@ -164,7 +164,7 @@ def buttons(parent, action_title, task_form_signal, on_validate, on_cancel): validate = QtWidgets.QPushButton(action_title, widget) validate.setDisabled(True) - validate.setIcon(gui.icon.dialog_ok(validate.style())) + validate.setIcon(todo.gui.icon.dialog_ok(validate.style())) validate.clicked.connect(on_validate); layout.addWidget(validate) @@ -177,7 +177,7 @@ def buttons(parent, action_title, task_form_signal, on_validate, on_cancel): task_form_signal.connect(on_task_form_signal) cancel = QtWidgets.QPushButton("cancel", widget) - cancel.setIcon(gui.icon.dialog_cancel(cancel.style())) + cancel.setIcon(todo.gui.icon.dialog_cancel(cancel.style())) cancel.clicked.connect(on_cancel) layout.addWidget(cancel) diff --git a/src/gui/tasks/signal.py b/todo/gui/tasks/signal.py index 074e8ec..52f65d1 100644 --- a/src/gui/tasks/signal.py +++ b/todo/gui/tasks/signal.py @@ -1,7 +1,7 @@ from PyQt5 import QtCore from typing import List -from model.task import Task +from todo.model.task import Task class AddTask(QtCore.QObject): _signal = QtCore.pyqtSignal(Task, list, name = "addTask") diff --git a/todo/gui/tasks/table/__init__.py b/todo/gui/tasks/table/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/gui/tasks/table/__init__.py diff --git a/todo/gui/tasks/table/menu.py b/todo/gui/tasks/table/menu.py new file mode 100644 index 0000000..bc039b2 --- /dev/null +++ b/todo/gui/tasks/table/menu.py @@ -0,0 +1,48 @@ +from PyQt5 import QtWidgets, QtCore +from typing import List + +import todo.gui.tasks.dialog +from todo.model.status import Status +from todo.model.task import Task, ValidTaskForm +from todo.model.tag import Tag + +def open(table: QtWidgets.QTableWidget, status: Status, update_task_signal, position): + rows = set([index.row() for index in table.selectedIndexes()]) + + menu = QtWidgets.QMenu(table) + + if len(rows) == 1: + modify_action = menu.addAction(todo.gui.icon.dialog_open(menu.style()), "modify") + else: + modify_action = QtWidgets.QAction(menu) + + delete_action = menu.addAction(todo.gui.icon.trash(menu.style()), "delete") + + if status != Status.READY: + move_to_ready = menu.addAction(todo.gui.icon.task_ready(menu.style()), "move to ready") + else: + move_to_ready = QtWidgets.QAction(menu) + + if status != Status.WAITING: + move_to_waiting = menu.addAction(todo.gui.icon.task_waiting(menu.style()), "move to waiting") + else: + move_to_waiting = QtWidgets.QAction(menu) + + if status != Status.MAYBE: + move_to_maybe = menu.addAction(todo.gui.icon.task_maybe(menu.style()), "move to maybe") + else: + move_to_maybe = QtWidgets.QAction(menu) + + action = menu.exec_(table.mapToGlobal(position + QtCore.QPoint(15, 20))) + if action == modify_action and len(rows) == 1: + row = list(rows)[0] + (task, tags) = table.get_at(row) + todo.gui.tasks.dialog.update(table, update_task_signal, row, task, tags).exec_() + elif action == delete_action: + todo.gui.tasks.dialog.confirm_delete(table, rows, lambda: table.delete_rows(rows)) + elif action == move_to_ready: + todo.gui.tasks.dialog.confirm_move(table, rows, Status.READY, lambda: table.update_status(rows, Status.READY)) + elif action == move_to_waiting: + todo.gui.tasks.dialog.confirm_move(table, rows, Status.WAITING, lambda: table.update_status(rows, Status.WAITING)) + elif action == move_to_maybe: + todo.gui.tasks.dialog.confirm_move(table, rows, Status.MAYBE, lambda: table.update_status(rows, Status.MAYBE)) diff --git a/src/gui/tasks/table/widget.py b/todo/gui/tasks/table/widget.py index aacae2f..e06c921 100644 --- a/src/gui/tasks/table/widget.py +++ b/todo/gui/tasks/table/widget.py @@ -4,33 +4,32 @@ from typing import List, Tuple import time import math -from model import difficulty, priority -from model.difficulty import Difficulty -from model.priority import Priority -from model.tag import Tag -from model.task import Task -from model.task_tag import TaskTag -from model.status import Status -import database -import db.tags -import db.task_tags -import gui.color -import gui.signal -import gui.tasks.dialog -import gui.tasks.duration -import gui.tasks.signal -import gui.tasks.signal -import gui.tasks.table.menu -import service.tasks -import util.array -import util.range +from todo.model import difficulty, priority +from todo.model.difficulty import Difficulty +from todo.model.priority import Priority +from todo.model.tag import Tag +from todo.model.task import Task +from todo.model.task_tag import TaskTag +from todo.model.status import Status +import todo.database +import todo.db.tags +import todo.db.task_tags +import todo.gui.color +import todo.gui.signal +import todo.gui.tasks.dialog +import todo.gui.tasks.duration +import todo.gui.tasks.signal +import todo.gui.tasks.signal +import todo.gui.tasks.table.menu +import todo.service.tasks +import todo.util.array class Widget(QtWidgets.QTableWidget): def __init__( self, parent, - on_show: gui.signal.Reload, - add_task_signal: gui.tasks.signal.AddTask, + on_show: todo.gui.signal.Reload, + add_task_signal: todo.gui.tasks.signal.AddTask, status: Status): super().__init__(parent) @@ -48,7 +47,7 @@ class Widget(QtWidgets.QTableWidget): # Menu self.setContextMenuPolicy(Qt.CustomContextMenu) - self.customContextMenuRequested.connect(lambda position: gui.tasks.table.menu.open(self, status, self._update_task_signal, position)) + self.customContextMenuRequested.connect(lambda position: todo.gui.tasks.table.menu.open(self, status, self._update_task_signal, position)) self.doubleClicked.connect(lambda index: self.on_double_click(index.row())) add_task_signal.connect(lambda task, tags: self.insert(task, tags)) @@ -56,12 +55,12 @@ class Widget(QtWidgets.QTableWidget): on_show.connect(lambda: self.on_show()) def init_state(self, status: Status): - self._update_task_signal = gui.tasks.signal.UpdateTask() - cursor = database.cursor() + self._update_task_signal = todo.gui.tasks.signal.UpdateTask() + cursor = todo.database.cursor() self._status = status - self._tasks = service.tasks.get(cursor, self._status) - self._task_tags = db.task_tags.get(cursor) - self._tags = db.tags.get(cursor) + self._tasks = todo.service.tasks.get(cursor, self._status) + self._task_tags = todo.db.task_tags.get(cursor) + self._tags = todo.db.tags.get(cursor) self._sort_column = 0 self._sort_is_ascending = True @@ -75,10 +74,10 @@ class Widget(QtWidgets.QTableWidget): self.setHorizontalHeader(self._header_view) def on_show(self): - cursor = database.cursor() - self._tasks = service.tasks.get(cursor, self._status) - self._task_tags = db.task_tags.get(cursor) - self._tags = db.tags.get(cursor) + cursor = todo.database.cursor() + self._tasks = todo.service.tasks.get(cursor, self._status) + self._task_tags = todo.db.task_tags.get(cursor) + self._tags = todo.db.tags.get(cursor) self.setRowCount(len(self._tasks)) self.sort() self.update_view() @@ -125,7 +124,7 @@ class Widget(QtWidgets.QTableWidget): task = self._tasks[row] self.setItem(row, 0, item(age_since(task.created_at))) self.setItem(row, 1, item(task.name)) - self.setCellWidget(row, 2, colored_label(self, gui.tasks.duration.format(task.duration), gui.tasks.duration.color(task.duration))) + self.setCellWidget(row, 2, colored_label(self, todo.gui.tasks.duration.format(task.duration), todo.gui.tasks.duration.color(task.duration))) self.setCellWidget(row, 3, colored_label(self, difficulty.format(task.difficulty), difficulty_color(task.difficulty))) self.setCellWidget(row, 4, colored_label(self, priority.format(task.priority), priority_color(task.priority))) tag_ids = [tt.tag_id for tt in self._task_tags if tt.task_id == task.id] @@ -135,7 +134,7 @@ class Widget(QtWidgets.QTableWidget): def insert(self, task: Task, tags: List[int]) -> int: is_rev = self.is_reversed() - row = util.array.insert_position( + row = todo.util.array.insert_position( self.sort_key(task, is_rev), [self.sort_key(t, is_rev) for t in self._tasks], is_rev) @@ -184,19 +183,19 @@ class Widget(QtWidgets.QTableWidget): if len(rows) == 1: row = rows[0] (task, tags) = self.get_at(row) - gui.tasks.dialog.update(self, self._update_task_signal, row, task, tags).exec_() + todo.gui.tasks.dialog.update(self, self._update_task_signal, row, task, tags).exec_() elif event.key() == Qt.Key_Delete: rows = self.get_selected_rows() - gui.tasks.dialog.show_delete(self, rows, lambda: self.delete_rows(rows)) + todo.gui.tasks.dialog.show_delete(self, rows, lambda: self.delete_rows(rows)) def delete_rows(self, rows: List[int]): task_ids = [task.id for i, task in enumerate(self._tasks) if i in rows] - service.tasks.delete(database.cursor(), task_ids) + todo.service.tasks.delete(todo.database.cursor(), task_ids) self.remove_rows_from_table(rows, task_ids) def update_status(self, rows: List[int], status: Status): task_ids = [task.id for i, task in enumerate(self._tasks) if i in rows] - service.tasks.update_status(database.cursor(), task_ids, status) + todo.service.tasks.update_status(todo.database.cursor(), task_ids, status) self.remove_rows_from_table(rows, task_ids) def remove_rows_from_table(self, rows: List[int], task_ids: List[int]): @@ -211,7 +210,7 @@ class Widget(QtWidgets.QTableWidget): def on_double_click(self, row: int): (task, tags) = self.get_at(row) - gui.tasks.dialog.update(self, self._update_task_signal, row, task, tags).exec_() + todo.gui.tasks.dialog.update(self, self._update_task_signal, row, task, tags).exec_() def get_at(self, row: int) -> Tuple[Task, List[int]]: task = self._tasks[row] @@ -269,16 +268,16 @@ def render_tags(parent, tags: List[Tag]): def difficulty_color(d: Difficulty) -> QtGui.QColor: if d == Difficulty.EASY: - return gui.color.easy_difficulty + return todo.gui.color.easy_difficulty elif d == Difficulty.NORMAL: - return gui.color.normal_difficulty + return todo.gui.color.normal_difficulty elif d == Difficulty.HARD: - return gui.color.hard_difficulty + return todo.gui.color.hard_difficulty def priority_color(p: Priority) -> QtGui.QColor: if p == Priority.LOW: - return gui.color.low_priority + return todo.gui.color.low_priority elif p == Priority.MIDDLE: - return gui.color.middle_priority + return todo.gui.color.middle_priority elif p == Priority.HIGH: - return gui.color.high_priority + return todo.gui.color.high_priority diff --git a/src/gui/tasks/test_duration.py b/todo/gui/tasks/test_duration.py index 9d5d9b8..1435e2d 100644 --- a/src/gui/tasks/test_duration.py +++ b/todo/gui/tasks/test_duration.py @@ -1,4 +1,4 @@ -from gui.tasks.duration import format, parse +from todo.gui.tasks.duration import format, parse def test_format(): assert format(0) == "" diff --git a/todo/gui/tasks/widget.py b/todo/gui/tasks/widget.py new file mode 100644 index 0000000..cc7fe96 --- /dev/null +++ b/todo/gui/tasks/widget.py @@ -0,0 +1,30 @@ +from PyQt5 import QtWidgets + +from todo.model.status import Status +import todo.gui.tasks.signal +import todo.gui.tasks.table.widget +import todo.gui.icon +import todo.gui.signal + +def widget(parent, on_show: todo.gui.signal.Reload, status: Status): + widget = QtWidgets.QWidget(parent) + + layout = QtWidgets.QVBoxLayout(widget) + widget.setLayout(layout) + + layout.addSpacing(15) + + add_task_signal = todo.gui.tasks.signal.AddTask() + + add_task_button = QtWidgets.QPushButton(" Add a task", widget) + add_task_button.setFixedHeight(30) + add_task_button.setIcon(todo.gui.icon.new_folder(widget.style())) + add_task_button.clicked.connect(lambda: todo.gui.tasks.dialog.add(widget, status, add_task_signal).exec_()) + layout.addWidget(add_task_button) + + layout.addSpacing(20) + + table = todo.gui.tasks.table.widget.Widget(widget, on_show, add_task_signal, status) + layout.addWidget(table) + + return widget diff --git a/todo/gui/window.py b/todo/gui/window.py new file mode 100644 index 0000000..0391ee9 --- /dev/null +++ b/todo/gui/window.py @@ -0,0 +1,36 @@ +from PyQt5 import QtCore, QtWidgets + +import todo.gui.tasks.widget +import todo.gui.tasks.widget +import todo.gui.tags.panel.widget +import todo.gui.signal +from todo.model.status import Status + +def get(): + window = QtWidgets.QMainWindow() + window.setWindowTitle("todo") + window.setMinimumSize(QtCore.QSize(640, 480)) + + tabs = QtWidgets.QTabWidget(window) + window.setCentralWidget(tabs) + + show_ready = todo.gui.signal.Reload() + show_waiting = todo.gui.signal.Reload() + show_maybe = todo.gui.signal.Reload() + + def on_current_tab_changed(index: int): + if index == 0: + show_ready.emit() + elif index == 1: + show_waiting.emit() + elif index == 2: + show_maybe.emit() + + tabs.currentChanged.connect(on_current_tab_changed) + + tabs.addTab(todo.gui.tasks.widget.widget(tabs, show_ready, Status.READY), "Ready") + tabs.addTab(todo.gui.tasks.widget.widget(tabs, show_waiting, Status.WAITING), "Waiting") + tabs.addTab(todo.gui.tasks.widget.widget(tabs, show_maybe, Status.MAYBE), "Maybe") + tabs.addTab(todo.gui.tags.panel.widget.widget(tabs), "Tags") + + return window diff --git a/todo/model/__init__.py b/todo/model/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/model/__init__.py diff --git a/src/model/difficulty.py b/todo/model/difficulty.py index 526cdb9..526cdb9 100644 --- a/src/model/difficulty.py +++ b/todo/model/difficulty.py diff --git a/src/model/priority.py b/todo/model/priority.py index 5948104..5948104 100644 --- a/src/model/priority.py +++ b/todo/model/priority.py diff --git a/src/model/status.py b/todo/model/status.py index 6881e0a..6881e0a 100644 --- a/src/model/status.py +++ b/todo/model/status.py diff --git a/src/model/tag.py b/todo/model/tag.py index 030b223..030b223 100644 --- a/src/model/tag.py +++ b/todo/model/tag.py diff --git a/src/model/task.py b/todo/model/task.py index 69f9807..f20cbc9 100644 --- a/src/model/task.py +++ b/todo/model/task.py @@ -1,7 +1,7 @@ from typing import NamedTuple, List -from model.difficulty import Difficulty -from model.priority import Priority +from todo.model.difficulty import Difficulty +from todo.model.priority import Priority class Task(NamedTuple): id: int diff --git a/src/model/task_tag.py b/todo/model/task_tag.py index 0a33c66..0a33c66 100644 --- a/src/model/task_tag.py +++ b/todo/model/task_tag.py diff --git a/todo/service/__init__.py b/todo/service/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/service/__init__.py diff --git a/todo/service/tasks.py b/todo/service/tasks.py new file mode 100644 index 0000000..2cebf00 --- /dev/null +++ b/todo/service/tasks.py @@ -0,0 +1,32 @@ +from typing import List + +from todo.model.task import Task, ValidTaskForm +from todo.model.status import Status +import todo.db.tasks +import todo.db.task_tags +import todo.database + +def get(cursor, status: Status) -> List[Task]: + return todo.db.tasks.get(cursor, status) + +def create(cursor, status: Status, task_form: ValidTaskForm) -> Task: + task = todo.db.tasks.insert(cursor, status, task_form) + todo.db.task_tags.insert_many(cursor, task.id, task_form.tags) + todo.database.commit() + return task + +def update(cursor, task: Task, task_form: ValidTaskForm) -> Task: + todo.db.task_tags.delete(cursor, [task.id]) + updated_task = todo.db.tasks.update(cursor, task, task_form) + todo.db.task_tags.insert_many(cursor, task.id, task_form.tags) + todo.database.commit() + return updated_task + +def delete(cursor, task_ids: List[int]): + todo.db.task_tags.delete(cursor, task_ids) + todo.db.tasks.delete(cursor, task_ids) + todo.database.commit() + +def update_status(cursor, task_ids: List[int], status: Status) -> List[Task]: + todo.db.tasks.update_status(cursor, task_ids, status) + todo.database.commit() diff --git a/todo/util/__init__.py b/todo/util/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/todo/util/__init__.py diff --git a/src/util/array.py b/todo/util/array.py index bb4eee3..bb4eee3 100644 --- a/src/util/array.py +++ b/todo/util/array.py diff --git a/src/util/range.py b/todo/util/range.py index bd4b27e..bd4b27e 100644 --- a/src/util/range.py +++ b/todo/util/range.py diff --git a/src/util/test_array.py b/todo/util/test_array.py index 38759b9..0186403 100644 --- a/src/util/test_array.py +++ b/todo/util/test_array.py @@ -1,4 +1,4 @@ -from array import insert_position +from todo.util.array import insert_position def test_insert_position(): assert insert_position(0, [], False) == 0 diff --git a/src/util/test_range.py b/todo/util/test_range.py index 0bd909b..8a96636 100644 --- a/src/util/test_range.py +++ b/todo/util/test_range.py @@ -1,4 +1,4 @@ -from range import from_indexes, Range +from todo.util.range import from_indexes, Range def test_from_indexes(): assert from_indexes([]) == [] |