aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2020-06-06 17:44:26 +0200
committerJoris2020-06-06 19:54:03 +0200
commit1595e0de940a86a7810df0e02e43838d97c0d846 (patch)
tree9701eeec0d98baa9f6044b1911df68e4c8539819
parent6b9195000eb5404c247288b384d7ca2bacc1ab23 (diff)
downloadtodo-1595e0de940a86a7810df0e02e43838d97c0d846.tar.gz
todo-1595e0de940a86a7810df0e02e43838d97c0d846.tar.bz2
todo-1595e0de940a86a7810df0e02e43838d97c0d846.zip
Provide nix build
-rw-r--r--.gitignore1
-rw-r--r--README.md6
-rwxr-xr-xbin/test (renamed from scripts/test)2
-rwxr-xr-xbin/todo22
-rw-r--r--default.nix34
-rw-r--r--setup.py12
-rw-r--r--shell.nix20
-rw-r--r--src/gui/tags/panel/widget.py30
-rw-r--r--src/gui/tasks/table/menu.py49
-rw-r--r--src/gui/tasks/widget.py30
-rw-r--r--src/gui/window.py36
-rw-r--r--src/main.py20
-rw-r--r--src/service/tasks.py32
-rw-r--r--todo/__init__.py0
-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__.py0
-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__.py0
-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__.py0
-rw-r--r--todo/gui/tags/list.py (renamed from src/gui/tags/list.py)8
-rw-r--r--todo/gui/tags/panel/__init__.py0
-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__.py0
-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__.py0
-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.py30
-rw-r--r--todo/gui/tasks/__init__.py0
-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__.py0
-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__.py0
-rw-r--r--todo/gui/tasks/table/menu.py48
-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.py30
-rw-r--r--todo/gui/window.py36
-rw-r--r--todo/model/__init__.py0
-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__.py0
-rw-r--r--todo/service/tasks.py32
-rw-r--r--todo/util/__init__.py0
-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
diff --git a/.gitignore b/.gitignore
index 42b5d44..8c33891 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
__pycache__
database
+result
diff --git a/README.md b/README.md
index e323a4d..b2f47b8 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/scripts/test b/bin/test
index 9b3fae7..cd6c0de 100755
--- a/scripts/test
+++ b/bin/test
@@ -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([]) == []