aboutsummaryrefslogtreecommitdiff
path: root/src/gui/tasks/table/model.py
blob: cb25b2295559d5590bd97b5b20c44b4dfb2fb91f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt

from model.task import Task
import time
import math
import util.array
import util.range
import gui.tasks.duration

columns = 4

headers = ['Age', 'Name', 'Duration', 'Tag']

default_sort = (0, Qt.AscendingOrder)

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, tasks):
        super(TableModel, self).__init__()
        self._tasks = tasks

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            return headers[section]
        elif role == Qt.DisplayRole and orientation == Qt.Vertical:
            return section + 1
        else:
            return QtCore.QVariant()

    def data(self, index, role):
        if role == Qt.DisplayRole:
            task = self._tasks[index.row()]
            if index.column() == 0:
                return age_since(task.created_at)
            elif index.column() == 1:
                return task.name
            elif index.column() == 2:
                return gui.tasks.duration.format(task.duration)
            elif index.column() == 3:
                return task.tag
        else:
            return QtCore.QVariant()

    def rowCount(self, index):
        return len(self._tasks)

    def columnCount(self, index):
        return columns

    def get_at(self, row):
        if row >= 0 and row < len(self._tasks):
            return self._tasks[row]


    def insert_task(self, header: QtWidgets.QHeaderView, task: Task) -> int:
        at = self.insert_position(header, task)
        self.beginInsertRows(QtCore.QModelIndex(), at, at)
        self._tasks.insert(at, task)
        self.endInsertRows()
        return at

    def insert_position(self, header: QtWidgets.QHeaderView, task: Task) -> int:
        row = header.sortIndicatorSection()
        order = header.sortIndicatorOrder()
        return util.array.insert_position(
                sort_key(task, row),
                [sort_key(t, row) for t in self._tasks],
                is_reversed(row, order))

    def update_task(self, header: QtWidgets.QHeaderView, row, task: Task) -> int:
        self.delete_task_range(row, 1)
        return self.insert_task(header, task)

    def delete_tasks(self, indexes):
        for range in reversed(util.range.from_indexes(indexes)):
            self.delete_task_range(range.start, range.length)
        return True

    def delete_task_range(self, row, rows):
        self.beginRemoveRows(QtCore.QModelIndex(), row, row + rows - 1)
        self._tasks = self._tasks[:row] + self._tasks[row + rows:]
        self.endRemoveRows()
        return True

    def row_ids(self, rows):
        return [task.id for i, task in enumerate(self._tasks) if i in rows]

    def sort(self, row: int, order: Qt.SortOrder):
        self.layoutAboutToBeChanged.emit()
        self._tasks = sorted(
                self._tasks,
                key = lambda task: sort_key(task, row),
                reverse = is_reversed(row, order))
        self.layoutChanged.emit()

def age_since(timestamp):
    diff = int(time.time()) - timestamp
    if diff >= 60 * 60 * 24:
        return '' + str(math.floor(diff / 60 / 60 / 24)) + 'd'
    elif diff >= 60 * 60:
        return '' + str(math.floor(diff / 60 / 60)) + 'h'
    elif diff >= 60:
        return '' + str(math.floor(diff / 60)) + 'm'
    else:
        return '1m'

def sort_key(task: Task, row: int):
    if row == 0:
        return task.created_at
    elif row == 1:
        return task.name.lower()
    elif row == 2:
        return task.duration
    elif row == 3:
        return task.tag.lower()

def is_reversed(row: int, order: Qt.SortOrder) -> bool:
    if row == 0:
        return order == Qt.AscendingOrder
    else:
        return order == Qt.DescendingOrder