aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoris2020-05-10 12:50:46 +0200
committerJoris2020-05-10 12:50:46 +0200
commit7372ab407535ade48ce0b642ae051990e3bef7ed (patch)
tree65ae22d72cf10e40e777c4fa1919539d8e065e46
parenta134f20eb62e6d174e7da81fd4adb7ff9e8b3b71 (diff)
downloadtodo-7372ab407535ade48ce0b642ae051990e3bef7ed.tar.gz
todo-7372ab407535ade48ce0b642ae051990e3bef7ed.tar.bz2
todo-7372ab407535ade48ce0b642ae051990e3bef7ed.zip
Add task difficulty and priority fields
-rw-r--r--src/db/init.py6
-rw-r--r--src/db/tasks.py44
-rw-r--r--src/gui/color.py13
-rw-r--r--src/gui/tasks/form/state.py52
-rw-r--r--src/gui/tasks/form/widget.py52
-rw-r--r--src/gui/tasks/table/model.py40
-rw-r--r--src/model/difficulty.py30
-rw-r--r--src/model/priority.py30
-rw-r--r--src/model/task.py12
9 files changed, 235 insertions, 44 deletions
diff --git a/src/db/init.py b/src/db/init.py
index cb8a4a8..83e73f2 100644
--- a/src/db/init.py
+++ b/src/db/init.py
@@ -12,9 +12,11 @@ def init(path):
" created_at INTEGER NOT NULL,"
" modified_at INTEGER NOT NULL,"
" name TEXT NOT NULL,"
- " description TEXT,"
" duration INTEGER,"
- " tag TEXT"
+ " tag TEXT,"
+ " difficulty INT,"
+ " priority INT,"
+ " description TEXT"
" )")
database.commit()
return database
diff --git a/src/db/tasks.py b/src/db/tasks.py
index e22a315..5fdd25e 100644
--- a/src/db/tasks.py
+++ b/src/db/tasks.py
@@ -10,9 +10,11 @@ def get(cursor: Cursor) -> Task:
" created_at,"
" modified_at,"
" name,"
- " description,"
" duration,"
- " tag"
+ " tag,"
+ " difficulty,"
+ " priority,"
+ " description"
" FROM tasks")
res = []
@@ -23,9 +25,11 @@ def get(cursor: Cursor) -> Task:
created_at = task[1],
modified_at = task[2],
name = task[3],
- description = task[4],
- duration = task[5],
- tag = task[6]
+ duration = task[4],
+ tag = task[5],
+ difficulty = task[6],
+ priority = task[7],
+ description = task[8]
))
return res
@@ -37,20 +41,24 @@ def insert(cursor: Cursor, form: ValidTaskForm):
" created_at,"
" modified_at,"
" name,"
- " description,"
" duration,"
- " tag"
- " ) VALUES (?, ?, ?, ?, ?, ?)",
- (now, now, form.name, form.description, form.duration, form.tag))
+ " tag,"
+ " difficulty,"
+ " priority,"
+ " description"
+ " ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
+ (now, now, form.name, form.duration, form.tag, int(form.difficulty), int(form.priority), form.description))
return Task(
id = cursor.lastrowid,
created_at = now,
modified_at = now,
name = form.name,
- description = form.description,
duration = form.duration,
- tag = form.tag
+ tag = form.tag,
+ difficulty = form.difficulty,
+ priority = form.priority,
+ description = form.description
)
def update(cursor: Cursor, task: Task, form: ValidTaskForm):
@@ -61,20 +69,24 @@ def update(cursor: Cursor, task: Task, form: ValidTaskForm):
" SET"
" modified_at = ?,"
" name = ?,"
- " description = ?,"
" duration = ?,"
- " tag = ?"
+ " tag = ?,"
+ " difficulty = ?,"
+ " priority = ?,"
+ " description = ?"
" WHERE id = ?",
- (now, form.name, form.description, form.duration, form.tag, task.id))
+ (now, form.name, form.duration, form.tag, int(form.difficulty), int(form.priority), form.description, task.id))
return Task(
id = task.id,
created_at = task.created_at,
modified_at = now,
name = form.name,
- description = form.description,
duration = form.duration,
- tag = form.tag
+ tag = form.tag,
+ difficulty = form.difficulty,
+ priority = form.priority,
+ description = form.description
)
def delete(cursor: Cursor, ids):
diff --git a/src/gui/color.py b/src/gui/color.py
new file mode 100644
index 0000000..dcb21ea
--- /dev/null
+++ b/src/gui/color.py
@@ -0,0 +1,13 @@
+from PyQt5 import QtGui
+
+red: QtGui.QColor = QtGui.QColor(200, 30, 30)
+green: QtGui.QColor = QtGui.QColor(30, 180, 30)
+blue: QtGui.QColor = QtGui.QColor(30, 30, 200)
+
+low_difficulty = green
+medium_difficulty = blue
+high_difficulty = red
+
+low_priority = green
+medium_priority = blue
+high_priority = red
diff --git a/src/gui/tasks/form/state.py b/src/gui/tasks/form/state.py
index 46e2909..727bedd 100644
--- a/src/gui/tasks/form/state.py
+++ b/src/gui/tasks/form/state.py
@@ -3,6 +3,8 @@ from PyQt5 import QtCore
from typing import NamedTuple, Optional
from model.task import ValidTaskForm
+from model.difficulty import Difficulty
+from model.priority import Priority
import gui.tasks.duration
class TaskFormEdition:
@@ -10,36 +12,48 @@ class TaskFormEdition:
self,
name,
name_signal,
- description,
- description_signal,
duration,
duration_signal,
tag,
- tag_signal):
+ tag_signal,
+ difficulty,
+ difficulty_signal,
+ priority,
+ priority_signal,
+ description,
+ description_signal):
self._name = name
- self._description = description
self._duration = duration
self._tag = tag
+ self._difficulty = difficulty
+ self._priority = priority
+ self._description = description
self._signal = ValidTaskFormSignal()
- name_signal.connect(lambda name: self.on_name_signal(name))
- description_signal.connect(lambda description: self.on_description_signal(description))
- duration_signal.connect(lambda duration: self.on_duration_signal(duration))
- tag_signal.connect(lambda tag: self.on_tag_signal(tag))
+ name_signal.connect(lambda n: self.on_name_signal(n))
+ duration_signal.connect(lambda d: self.on_duration_signal(d))
+ tag_signal.connect(lambda t: self.on_tag_signal(t))
+ difficulty_signal.connect(lambda d: self.on_difficulty_signal(d))
+ priority_signal.connect(lambda p: self.on_priority_signal(p))
+ description_signal.connect(lambda d: self.on_description_signal(d))
def get(self) -> Optional[ValidTaskForm]:
name = self._name.strip()
- description = self._description.strip()
duration = gui.tasks.duration.parse(self._duration)
tag = self._tag.strip()
+ difficulty = self._difficulty
+ priority = self._priority
+ description = self._description.strip()
if name and duration != None:
return ValidTaskForm(
name = name,
- description = description,
duration = duration,
- tag = tag)
+ tag = tag,
+ difficulty = difficulty,
+ priority = priority,
+ description = description)
else:
return None
@@ -47,10 +61,6 @@ class TaskFormEdition:
self._name = name
self.emit()
- def on_description_signal(self, description: str):
- self._description = description
- self.emit()
-
def on_duration_signal(self, duration: str):
self._duration = duration
self.emit()
@@ -59,6 +69,18 @@ class TaskFormEdition:
self._tag = tag
self.emit()
+ def on_difficulty_signal(self, index: int):
+ self._difficulty = Difficulty(index)
+ self.emit()
+
+ def on_priority_signal(self, index: int):
+ self._priority = Priority(index)
+ self.emit()
+
+ def on_description_signal(self, description: str):
+ self._description = description
+ self.emit()
+
def emit(self):
validForm = self.get()
if validForm:
diff --git a/src/gui/tasks/form/widget.py b/src/gui/tasks/form/widget.py
index 49bf5f7..846ce90 100644
--- a/src/gui/tasks/form/widget.py
+++ b/src/gui/tasks/form/widget.py
@@ -1,9 +1,9 @@
from PyQt5 import QtWidgets, QtCore
-from typing import Optional, Tuple
+from typing import Optional, Tuple, List, Any
import db.tasks
from model.task import Task, ValidTaskForm
-
+from model import difficulty, priority
import gui.icons
import gui.tasks.form.state
import gui.tasks.duration
@@ -45,6 +45,24 @@ def widget(
init_tag = task.tag if task is not None else ''
tag_input = line_edit(grid, grid_layout, 2, 'Tag', init_tag)
+ init_difficulty = task.difficulty if task is not None else difficulty.Difficulty.MEDIUM
+ difficulty_input = combo_box(
+ grid,
+ grid_layout,
+ 3,
+ 'Difficulty',
+ [difficulty.format(d) for d in difficulty.values],
+ int(init_difficulty))
+
+ init_priority = task.priority if task is not None else priority.Priority.MEDIUM
+ priority_input = combo_box(
+ grid,
+ grid_layout,
+ 4,
+ 'Priority',
+ [priority.format(d) for d in priority.values],
+ int(init_priority))
+
init_description = task.description if task is not None else ''
(description_input, description_signal) = text_edit(widget, 'Description', init_description)
layout.addWidget(description_input)
@@ -52,12 +70,16 @@ def widget(
task_form_edition = gui.tasks.form.state.TaskFormEdition(
init_name,
name_input.textChanged,
- init_description,
- description_signal,
init_duration,
duration_input.textChanged,
init_tag,
- tag_input.textChanged)
+ tag_input.textChanged,
+ init_difficulty,
+ difficulty_input.currentIndexChanged,
+ init_priority,
+ priority_input.currentIndexChanged,
+ init_description,
+ description_signal)
def on_validate():
form = task_form_edition.get()
@@ -90,6 +112,26 @@ def line_edit(
return edit
+def combo_box(
+ parent,
+ layout: QtWidgets.QGridLayout,
+ n: int,
+ label: str,
+ values: List[str],
+ default_value: int) -> QtWidgets.QComboBox:
+
+ label = QtWidgets.QLabel(label, parent)
+ layout.addWidget(label, n, 0)
+
+ box = QtWidgets.QComboBox(parent)
+ for value in values:
+ box.addItem(value)
+ if default_value != None:
+ box.setCurrentIndex(default_value)
+ layout.addWidget(box, n, 1)
+
+ return box
+
def text_edit(
parent,
label: str,
diff --git a/src/gui/tasks/table/model.py b/src/gui/tasks/table/model.py
index cb25b22..5013569 100644
--- a/src/gui/tasks/table/model.py
+++ b/src/gui/tasks/table/model.py
@@ -1,16 +1,20 @@
-from PyQt5 import QtCore, QtWidgets
+from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import Qt
from model.task import Task
+from model.difficulty import Difficulty
+from model.priority import Priority
+from model import difficulty, priority
import time
import math
import util.array
import util.range
import gui.tasks.duration
+import gui.color
-columns = 4
+columns = 6
-headers = ['Age', 'Name', 'Duration', 'Tag']
+headers = ['Age', 'Name', 'Duration', 'Difficulty', 'Priority', 'Tag']
default_sort = (0, Qt.AscendingOrder)
@@ -28,6 +32,8 @@ class TableModel(QtCore.QAbstractTableModel):
return QtCore.QVariant()
def data(self, index, role):
+ task = self._tasks[index.row()]
+
if role == Qt.DisplayRole:
task = self._tasks[index.row()]
if index.column() == 0:
@@ -37,7 +43,15 @@ class TableModel(QtCore.QAbstractTableModel):
elif index.column() == 2:
return gui.tasks.duration.format(task.duration)
elif index.column() == 3:
+ return difficulty.format(task.difficulty)
+ elif index.column() == 4:
+ return priority.format(task.priority)
+ elif index.column() == 5:
return task.tag
+ elif role == Qt.ForegroundRole and index.column() == 3:
+ return QtGui.QBrush(difficulty_color(task.difficulty))
+ elif role == Qt.ForegroundRole and index.column() == 4:
+ return QtGui.QBrush(priority_color(task.priority))
else:
return QtCore.QVariant()
@@ -112,6 +126,10 @@ def sort_key(task: Task, row: int):
elif row == 2:
return task.duration
elif row == 3:
+ return task.difficulty
+ elif row == 4:
+ return task.priority
+ elif row == 5:
return task.tag.lower()
def is_reversed(row: int, order: Qt.SortOrder) -> bool:
@@ -119,3 +137,19 @@ def is_reversed(row: int, order: Qt.SortOrder) -> bool:
return order == Qt.AscendingOrder
else:
return order == Qt.DescendingOrder
+
+def difficulty_color(d: Difficulty) -> QtGui.QColor:
+ if d == Difficulty.LOW:
+ return gui.color.low_difficulty
+ elif d == Difficulty.MEDIUM:
+ return gui.color.medium_difficulty
+ elif d == Difficulty.HIGH:
+ return gui.color.high_difficulty
+
+def priority_color(p: Priority) -> QtGui.QColor:
+ if p == Priority.LOW:
+ return gui.color.low_priority
+ elif p == Priority.MEDIUM:
+ return gui.color.medium_priority
+ elif p == Priority.HIGH:
+ return gui.color.high_priority
diff --git a/src/model/difficulty.py b/src/model/difficulty.py
new file mode 100644
index 0000000..595f844
--- /dev/null
+++ b/src/model/difficulty.py
@@ -0,0 +1,30 @@
+from enum import IntEnum
+from typing import Optional
+
+class Difficulty(IntEnum):
+ LOW = 0
+ MEDIUM = 1
+ HIGH = 2
+
+values = [
+ Difficulty.LOW,
+ Difficulty.MEDIUM,
+ Difficulty.HIGH]
+
+def format(difficulty: Difficulty) -> str:
+ if difficulty == Difficulty.LOW:
+ return 'Low'
+ elif difficulty == Difficulty.MEDIUM:
+ return 'Medium'
+ elif difficulty == Difficulty.HIGH:
+ return 'High'
+
+def parse(string: str) -> Optional[Difficulty]:
+ if string == 'Low':
+ return Difficulty.LOW
+ elif string == 'Medium':
+ return Difficulty.MEDIUM
+ elif string == 'High':
+ return Difficulty.HIGH
+ else:
+ return None
diff --git a/src/model/priority.py b/src/model/priority.py
new file mode 100644
index 0000000..873369d
--- /dev/null
+++ b/src/model/priority.py
@@ -0,0 +1,30 @@
+from enum import IntEnum
+from typing import Optional
+
+class Priority(IntEnum):
+ LOW = 0
+ MEDIUM = 1
+ HIGH = 2
+
+values = [
+ Priority.LOW,
+ Priority.MEDIUM,
+ Priority.HIGH]
+
+def format(priority: Priority) -> str:
+ if priority == Priority.LOW:
+ return 'Low'
+ elif priority == Priority.MEDIUM:
+ return 'Medium'
+ elif priority == Priority.HIGH:
+ return 'High'
+
+def parse(string: str) -> Optional[Priority]:
+ if string == 'Low':
+ return Priority.LOW
+ elif string == 'Medium':
+ return Priority.MEDIUM
+ elif string == 'High':
+ return Priority.HIGH
+ else:
+ return None
diff --git a/src/model/task.py b/src/model/task.py
index cc7758d..f5e0ae5 100644
--- a/src/model/task.py
+++ b/src/model/task.py
@@ -1,17 +1,23 @@
from typing import NamedTuple
-from datetime import datetime
+
+from model.difficulty import Difficulty
+from model.priority import Priority
class Task(NamedTuple):
id: int
created_at: int
modified_at: int
name: str
- description: str
duration: int
tag: str
+ difficulty: Difficulty
+ priority: Priority
+ description: str
class ValidTaskForm(NamedTuple):
name: str
- description: str
duration: int
tag: str
+ difficulty: Difficulty
+ priority: Priority
+ description: str