Implemented report stuff: editing and switching days.
This commit is contained in:
parent
828d797a86
commit
19a7dbf6db
52
data.py
52
data.py
@ -2,7 +2,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import base64
|
import base64
|
||||||
import atexit
|
import atexit
|
||||||
from datetime import datetime, date, timedelta
|
from datetime import datetime, date, time, timedelta
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from collections.abc import MutableMapping
|
from collections.abc import MutableMapping
|
||||||
|
|
||||||
@ -117,10 +117,14 @@ class Log:
|
|||||||
def log(self, task, ptime=None):
|
def log(self, task, ptime=None):
|
||||||
if ptime is None:
|
if ptime is None:
|
||||||
ptime = datetime.now()
|
ptime = datetime.now()
|
||||||
|
# round to nearest minute
|
||||||
|
round_min = timedelta(minutes=round(ptime.second/60))
|
||||||
|
ptime = ptime - timedelta(seconds=ptime.second) + round_min
|
||||||
|
# month dance necessary to trigger Data.__setitem__
|
||||||
month = self._data.setdefault(ptime.strftime("%Y-%m"), {})
|
month = self._data.setdefault(ptime.strftime("%Y-%m"), {})
|
||||||
month.setdefault(ptime.strftime("%d"), [])\
|
month.setdefault(ptime.strftime("%d"), [])\
|
||||||
.append(f"{ptime.strftime('%H:%M:%S')} {base64.b64encode(task.encode('utf-8')).decode('utf-8')}")
|
.append(f"{ptime.strftime('%H:%M')} {base64.b64encode(task.encode('utf-8')).decode('utf-8')}")
|
||||||
self._data[ptime.strftime("%Y-%m")] = month # necessary to trigger Data.__setitem__
|
self._data[ptime.strftime("%Y-%m")] = month
|
||||||
|
|
||||||
def last_log(self, pdate=date.today()):
|
def last_log(self, pdate=date.today()):
|
||||||
if pdate.strftime("%Y-%m") not in self._data or pdate.strftime("%d") not in self._data[pdate.strftime("%Y-%m")]:
|
if pdate.strftime("%Y-%m") not in self._data or pdate.strftime("%d") not in self._data[pdate.strftime("%Y-%m")]:
|
||||||
@ -128,12 +132,23 @@ class Log:
|
|||||||
return base64.b64decode(
|
return base64.b64decode(
|
||||||
self._data[pdate.strftime("%Y-%m")][pdate.strftime("%d")][-1].split()[1].encode("utf-8")).decode("utf-8")
|
self._data[pdate.strftime("%Y-%m")][pdate.strftime("%d")][-1].split()[1].encode("utf-8")).decode("utf-8")
|
||||||
|
|
||||||
def report(self, pdate=date.today()):
|
def report(self, pdate=None):
|
||||||
|
if pdate is None:
|
||||||
|
pdate = date.today()
|
||||||
|
return Report(self._data, pdate)
|
||||||
|
|
||||||
|
|
||||||
|
class Report:
|
||||||
|
def __init__(self, data, pdate):
|
||||||
|
self._data = data
|
||||||
|
self._date = pdate
|
||||||
|
|
||||||
|
def report(self):
|
||||||
tmp = []
|
tmp = []
|
||||||
for e in self._data[pdate.strftime("%Y-%m")][pdate.strftime("%d")]:
|
for e in self._data[self._date.strftime("%Y-%m")][self._date.strftime("%d")]:
|
||||||
tstr, b64str = e.split()
|
tstr, b64str = e.split()
|
||||||
task = base64.b64decode(b64str.encode("utf-8")).decode("utf-8")
|
task = base64.b64decode(b64str.encode("utf-8")).decode("utf-8")
|
||||||
start_time = datetime.combine(pdate, datetime.strptime(tstr, "%H:%M:%S").time())
|
start_time = datetime.combine(self._date, datetime.strptime(tstr, "%H:%M").time())
|
||||||
tmp.append((task, start_time))
|
tmp.append((task, start_time))
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
@ -155,3 +170,28 @@ class Log:
|
|||||||
dmins, _ = divmod(rem, 60)
|
dmins, _ = divmod(rem, 60)
|
||||||
ret.append(("Sum", "", f"{dhours:02d}:{dmins:02d}"))
|
ret.append(("Sum", "", f"{dhours:02d}:{dmins:02d}"))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def save(self, report):
|
||||||
|
report = report[:-2] # cut of sum display
|
||||||
|
save_list = []
|
||||||
|
for tstr, ttime, _ in report:
|
||||||
|
b64str = base64.b64encode(tstr.encode("utf-8")).decode("utf-8")
|
||||||
|
save_string = f"{ttime} {b64str}"
|
||||||
|
save_list.append(save_string)
|
||||||
|
# month dance necessary to trigger Data.__setitem__
|
||||||
|
month = self._data[self._date.strftime("%Y-%m")]
|
||||||
|
if month[self._date.strftime("%d")] == save_list: # no changes
|
||||||
|
return
|
||||||
|
month[self._date.strftime("%d")] = save_list
|
||||||
|
self._data[self._date.strftime("%Y-%m")] = month
|
||||||
|
|
||||||
|
def prev_next_avail(self):
|
||||||
|
prev = (self._date - timedelta(days=1)).strftime("%d") in self._data[self._date.strftime("%Y-%m")]
|
||||||
|
_next = (self._date + timedelta(days=1)).strftime("%d") in self._data[self._date.strftime("%Y-%m")]
|
||||||
|
return prev, _next
|
||||||
|
|
||||||
|
def previous(self):
|
||||||
|
self._date = self._date - timedelta(days=1)
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
self._date = self._date + timedelta(days=1)
|
||||||
|
6
main.py
6
main.py
@ -34,12 +34,18 @@ class App:
|
|||||||
self.taskEdit.accepted.connect(self.tasks_edited)
|
self.taskEdit.accepted.connect(self.tasks_edited)
|
||||||
|
|
||||||
self.reportDialog = Report(None)
|
self.reportDialog = Report(None)
|
||||||
|
self.taskEdit.accepted.connect(self.tasks_edited)
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def tasks_edited(self):
|
def tasks_edited(self):
|
||||||
self.tasks.tasks = self.taskEdit.tasks
|
self.tasks.tasks = self.taskEdit.tasks
|
||||||
self.update_tray_menu()
|
self.update_tray_menu()
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def report_done(self):
|
||||||
|
self.active_task = self.log.last_log() or "Nothing"
|
||||||
|
self.update_tray_menu()
|
||||||
|
|
||||||
def change_task(self, task):
|
def change_task(self, task):
|
||||||
self.active_task = task
|
self.active_task = task
|
||||||
self.log.log(task)
|
self.log.log(task)
|
||||||
|
92
report.py
92
report.py
@ -4,6 +4,9 @@ from PySide2 import QtCore, QtGui, QtWidgets
|
|||||||
class Report(QtWidgets.QDialog):
|
class Report(QtWidgets.QDialog):
|
||||||
def __init__(self, parent, *args, **kwargs):
|
def __init__(self, parent, *args, **kwargs):
|
||||||
super().__init__(parent, *args, **kwargs)
|
super().__init__(parent, *args, **kwargs)
|
||||||
|
self._report = None
|
||||||
|
self._report_data = None
|
||||||
|
|
||||||
self.setWindowTitle("Report")
|
self.setWindowTitle("Report")
|
||||||
|
|
||||||
self.tableWidget = QtWidgets.QTableWidget()
|
self.tableWidget = QtWidgets.QTableWidget()
|
||||||
@ -13,23 +16,29 @@ class Report(QtWidgets.QDialog):
|
|||||||
self.header = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal)
|
self.header = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal)
|
||||||
self.tableWidget.setHorizontalHeader(self.header)
|
self.tableWidget.setHorizontalHeader(self.header)
|
||||||
|
|
||||||
new_button = QtWidgets.QPushButton()
|
self.previous_button = QtWidgets.QPushButton()
|
||||||
new_button.setText("New item")
|
self.previous_button.setText("Previous")
|
||||||
new_button.setIcon(QtGui.QIcon.fromTheme("list-add"))
|
self.previous_button.setIcon(QtGui.QIcon.fromTheme("arrow-left"))
|
||||||
new_button.pressed.connect(self.new_task)
|
self.previous_button.pressed.connect(self.previous)
|
||||||
|
|
||||||
|
self.next_button = QtWidgets.QPushButton()
|
||||||
|
self.next_button.setText("Next")
|
||||||
|
self.next_button.setIcon(QtGui.QIcon.fromTheme("arrow-right"))
|
||||||
|
self.next_button.pressed.connect(self.next)
|
||||||
|
|
||||||
del_button = QtWidgets.QPushButton()
|
del_button = QtWidgets.QPushButton()
|
||||||
del_button.setText("Delete item")
|
del_button.setText("Delete item")
|
||||||
del_button.setIcon(QtGui.QIcon.fromTheme("list-remove"))
|
del_button.setIcon(QtGui.QIcon.fromTheme("list-remove"))
|
||||||
del_button.pressed.connect(self.del_task)
|
del_button.pressed.connect(self.del_log)
|
||||||
|
|
||||||
ok_button = QtWidgets.QPushButton()
|
ok_button = QtWidgets.QPushButton()
|
||||||
ok_button.setText("OK")
|
ok_button.setText("OK")
|
||||||
ok_button.setIcon(QtGui.QIcon.fromTheme("dialog-ok-apply"))
|
ok_button.setIcon(QtGui.QIcon.fromTheme("dialog-ok-apply"))
|
||||||
ok_button.pressed.connect(self.accept)
|
ok_button.pressed.connect(self._accept)
|
||||||
|
|
||||||
blayout = QtWidgets.QHBoxLayout()
|
blayout = QtWidgets.QHBoxLayout()
|
||||||
blayout.addWidget(new_button)
|
blayout.addWidget(self.previous_button)
|
||||||
|
blayout.addWidget(self.next_button)
|
||||||
blayout.addWidget(del_button)
|
blayout.addWidget(del_button)
|
||||||
blayout.addWidget(ok_button)
|
blayout.addWidget(ok_button)
|
||||||
|
|
||||||
@ -39,12 +48,25 @@ class Report(QtWidgets.QDialog):
|
|||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def set_data(self, data):
|
def set_data(self, data):
|
||||||
self.tableWidget.setRowCount(len(data))
|
self._report = data
|
||||||
|
self._report_data = self._report.report()
|
||||||
|
self.refresh_table()
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
for row, _ in enumerate(data):
|
def refresh_table(self):
|
||||||
self.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(data[row][0]))
|
self.tableWidget.setRowCount(len(self._report_data))
|
||||||
self.tableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem(data[row][1]))
|
|
||||||
self.tableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem(data[row][2]))
|
for row, _ in enumerate(self._report_data):
|
||||||
|
item0 = QtWidgets.QTableWidgetItem(self._report_data[row][0])
|
||||||
|
self.tableWidget.setItem(row, 0, item0)
|
||||||
|
item1 = QtWidgets.QTableWidgetItem(self._report_data[row][1])
|
||||||
|
self.tableWidget.setItem(row, 1, item1)
|
||||||
|
item2 = QtWidgets.QTableWidgetItem(self._report_data[row][2])
|
||||||
|
self.tableWidget.setItem(row, 2, item2)
|
||||||
|
item0.setFlags(item0.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
|
item2.setFlags(item2.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
|
if row > len(self._report_data) - 3:
|
||||||
|
item1.setFlags(item1.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
|
|
||||||
self.tableWidget.resizeColumnsToContents()
|
self.tableWidget.resizeColumnsToContents()
|
||||||
|
|
||||||
@ -57,26 +79,34 @@ class Report(QtWidgets.QDialog):
|
|||||||
self.tableWidget.setMinimumHeight(min((self.tableWidget.rowCount() + 2) * self.tableWidget.rowHeight(0),
|
self.tableWidget.setMinimumHeight(min((self.tableWidget.rowCount() + 2) * self.tableWidget.rowHeight(0),
|
||||||
self.tableWidget.screen().size().height() * 0.8))
|
self.tableWidget.screen().size().height() * 0.8))
|
||||||
|
|
||||||
@QtCore.Slot()
|
def update_prev_next(self):
|
||||||
def new_task(self):
|
prev, _next = self._report.prev_next_avail()
|
||||||
l = self.list.stringList()
|
self.previous_button.setEnabled(prev)
|
||||||
l.append("")
|
self.next_button.setEnabled(_next)
|
||||||
self.list.setStringList(l)
|
|
||||||
i = self.list.index(len(l) - 1)
|
|
||||||
self.tableView.setCurrentIndex(i)
|
|
||||||
self.tableView.edit(i)
|
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def del_task(self):
|
def del_log(self):
|
||||||
l = self.list.stringList()
|
row = self.tableWidget.currentRow()
|
||||||
del l[self.tableView.currentIndex().row()]
|
if row > len(self._report_data) - 3:
|
||||||
self.list.setStringList(l)
|
return
|
||||||
|
del self._report_data[row]
|
||||||
|
self.refresh_table()
|
||||||
|
|
||||||
@property
|
@QtCore.Slot()
|
||||||
def tasks(self):
|
def _accept(self):
|
||||||
ret = self.list.stringList()
|
self._report.save(self._report_data)
|
||||||
return list(filter(None, ret)) # filter empty strings
|
self.accept()
|
||||||
|
|
||||||
@tasks.setter
|
@QtCore.Slot()
|
||||||
def tasks(self, tasks):
|
def previous(self):
|
||||||
self.list.setStringList(tasks)
|
self._report.save(self._report_data)
|
||||||
|
self._report.previous()
|
||||||
|
self.refresh_table()
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def next(self):
|
||||||
|
self._report.save(self._report_data)
|
||||||
|
self._report.next()
|
||||||
|
self.refresh_table()
|
||||||
|
self.update_prev_next()
|
||||||
|
Loading…
Reference in New Issue
Block a user