stuff
This commit is contained in:
parent
e9fb29aa1b
commit
210aaba92b
@ -2,7 +2,9 @@ import atexit
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
from collections.abc import MutableMapping
|
from collections.abc import MutableMapping
|
||||||
|
from copy import deepcopy
|
||||||
from datetime import datetime, date, timedelta
|
from datetime import datetime, date, timedelta
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from typing import List, Tuple, Dict
|
from typing import List, Tuple, Dict
|
||||||
@ -193,10 +195,11 @@ class LogCommentsData:
|
|||||||
month_str = pdate.strftime("%Y-%m")
|
month_str = pdate.strftime("%Y-%m")
|
||||||
day_str = pdate.strftime("%d")
|
day_str = pdate.strftime("%d")
|
||||||
month = self._data.setdefault(month_str, {})
|
month = self._data.setdefault(month_str, {})
|
||||||
|
if month.setdefault(day_str, self._init_day)["log"] == encoded:
|
||||||
|
return # no changes
|
||||||
month.setdefault(day_str, self._init_day)["log"] = encoded
|
month.setdefault(day_str, self._init_day)["log"] = encoded
|
||||||
# trigger save if necessary
|
# trigger save
|
||||||
if self._data[month_str] != month:
|
self._data[month_str] = month
|
||||||
self._data[month_str] = month
|
|
||||||
|
|
||||||
def add_log_entry(self, task: str):
|
def add_log_entry(self, task: str):
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
@ -241,7 +244,7 @@ class LogCommentsData:
|
|||||||
return dict()
|
return dict()
|
||||||
comment_data = self._data[month_str][day_str]["comments"]
|
comment_data = self._data[month_str][day_str]["comments"]
|
||||||
ret = dict()
|
ret = dict()
|
||||||
for k, v in comment_data:
|
for k, v in comment_data.items():
|
||||||
k_dec = base64.b64decode(k.encode("utf-8")).decode("utf-8")
|
k_dec = base64.b64decode(k.encode("utf-8")).decode("utf-8")
|
||||||
v_dec = base64.b64decode(v.encode("utf-8")).decode("utf-8")
|
v_dec = base64.b64decode(v.encode("utf-8")).decode("utf-8")
|
||||||
ret[k_dec] = v_dec
|
ret[k_dec] = v_dec
|
||||||
@ -250,17 +253,18 @@ class LogCommentsData:
|
|||||||
def set_comments(self, pdate: date, comments: Dict[str, str]):
|
def set_comments(self, pdate: date, comments: Dict[str, str]):
|
||||||
self._ensure_format(pdate)
|
self._ensure_format(pdate)
|
||||||
encoded = dict()
|
encoded = dict()
|
||||||
for k, v in comments:
|
for k, v in comments.items():
|
||||||
k_enc = base64.b64encode(k.encode("utf-8")).decode("utf-8")
|
k_enc = base64.b64encode(k.encode("utf-8")).decode("utf-8")
|
||||||
v_enc = base64.b64encode(v.encode("utf-8")).decode("utf-8")
|
v_enc = base64.b64encode(v.encode("utf-8")).decode("utf-8")
|
||||||
encoded[k_enc] = v_enc
|
encoded[k_enc] = v_enc
|
||||||
month_str = pdate.strftime("%Y-%m")
|
month_str = pdate.strftime("%Y-%m")
|
||||||
day_str = pdate.strftime("%d")
|
day_str = pdate.strftime("%d")
|
||||||
month = self._data.setdefault(month_str, {})
|
month = self._data.setdefault(month_str, {})
|
||||||
|
if month.setdefault(day_str, self._init_day)["comments"] == encoded:
|
||||||
|
return # no changes
|
||||||
month.setdefault(day_str, self._init_day)["comments"] = encoded
|
month.setdefault(day_str, self._init_day)["comments"] = encoded
|
||||||
# trigger save if necessary
|
# trigger save
|
||||||
if self._data[month_str] != month:
|
self._data[month_str] = month
|
||||||
self._data[month_str] = month
|
|
||||||
|
|
||||||
|
|
||||||
class Log:
|
class Log:
|
||||||
@ -293,10 +297,15 @@ class Log:
|
|||||||
return Worklog(self._data)
|
return Worklog(self._data)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO remove
|
||||||
|
dEV = False
|
||||||
|
|
||||||
|
|
||||||
def summary(lcd: LogCommentsData, pdate: date) -> Tuple[Dict[str, timedelta], timedelta]:
|
def summary(lcd: LogCommentsData, pdate: date) -> Tuple[Dict[str, timedelta], timedelta]:
|
||||||
log = lcd.get_log(pdate)
|
log = lcd.get_log(pdate)
|
||||||
if pdate == date.today():
|
if dEV:
|
||||||
log.append((datetime.now(), "End"))
|
if pdate == date.today():
|
||||||
|
log.append((datetime.now(), "End"))
|
||||||
tasks_sums = {}
|
tasks_sums = {}
|
||||||
total_sum = timedelta()
|
total_sum = timedelta()
|
||||||
for i, le in enumerate(log):
|
for i, le in enumerate(log):
|
||||||
@ -318,15 +327,37 @@ def duration_to_str(duration: timedelta) -> str:
|
|||||||
return f"{dhours:02d}:{dmins:02d}"
|
return f"{dhours:02d}:{dmins:02d}"
|
||||||
|
|
||||||
|
|
||||||
class Report:
|
class PrevNextable:
|
||||||
def __init__(self, data: LogCommentsData):
|
def __init__(self, data: LogCommentsData):
|
||||||
self._data = data
|
self._data = data
|
||||||
self._date = date.today()
|
self._date = date.today()
|
||||||
self._not_log_len = 0
|
|
||||||
self._prev = None
|
self._prev = None
|
||||||
self._next = None
|
self._next = None
|
||||||
self._update_prev_next()
|
self._update_prev_next()
|
||||||
|
|
||||||
|
def _update_prev_next(self):
|
||||||
|
self._prev, self._next = self._data.get_prev_next_avail(self._date)
|
||||||
|
|
||||||
|
def prev_next_avail(self) -> Tuple[bool, bool]:
|
||||||
|
return self._prev is not None, self._next is not None
|
||||||
|
|
||||||
|
def previous(self):
|
||||||
|
self._date = self._prev
|
||||||
|
self._update_prev_next()
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
self._date = self._next
|
||||||
|
self._update_prev_next()
|
||||||
|
|
||||||
|
def date(self) -> str:
|
||||||
|
return self._date.strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
|
||||||
|
class Report(PrevNextable):
|
||||||
|
def __init__(self, data: LogCommentsData):
|
||||||
|
super().__init__(data)
|
||||||
|
self._not_log_len = 0
|
||||||
|
|
||||||
def report(self) -> Tuple[List[List[str]], int]:
|
def report(self) -> Tuple[List[List[str]], int]:
|
||||||
log = self._data.get_log(self._date)
|
log = self._data.get_log(self._date)
|
||||||
if self._date == date.today():
|
if self._date == date.today():
|
||||||
@ -365,24 +396,29 @@ class Report:
|
|||||||
))
|
))
|
||||||
self._data.set_log(self._date, report)
|
self._data.set_log(self._date, report)
|
||||||
|
|
||||||
def _update_prev_next(self):
|
|
||||||
self._prev, self._next = self._data.get_prev_next_avail(self._date)
|
|
||||||
|
|
||||||
def prev_next_avail(self):
|
class Worklog(PrevNextable):
|
||||||
return self._prev is not None, self._next is not None
|
|
||||||
|
|
||||||
def previous(self):
|
|
||||||
self._date = self._prev
|
|
||||||
self._update_prev_next()
|
|
||||||
|
|
||||||
def next(self):
|
|
||||||
self._date = self._next
|
|
||||||
self._update_prev_next()
|
|
||||||
|
|
||||||
def date(self):
|
|
||||||
return self._date.strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
|
|
||||||
class Worklog:
|
|
||||||
def __init__(self, data: LogCommentsData):
|
def __init__(self, data: LogCommentsData):
|
||||||
self._data = data
|
super().__init__(data)
|
||||||
|
self._worklog = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def worklog(self) -> List[List[str]]:
|
||||||
|
tasks_summary, total_sum = summary(self._data, self._date)
|
||||||
|
comments = self._data.get_comments(self._date)
|
||||||
|
self._worklog = []
|
||||||
|
for task, duration in tasks_summary.items():
|
||||||
|
self._worklog.append([task, comments.setdefault(task, ""), duration_to_str(duration)])
|
||||||
|
self._worklog.append(["Total sum", "", duration_to_str(total_sum)])
|
||||||
|
return deepcopy(self._worklog)
|
||||||
|
|
||||||
|
@worklog.setter
|
||||||
|
def worklog(self, worklog: List[List[str]]):
|
||||||
|
log = self._data.get_log(self._date)
|
||||||
|
set_comments = dict()
|
||||||
|
for i, (task, comment, duration) in enumerate(worklog[:-1]):
|
||||||
|
set_comments[task] = comment
|
||||||
|
if self._worklog[i][0] != task:
|
||||||
|
log = list(map(lambda x: (x[0], x[1].replace(self._worklog[i][0], task)), log))
|
||||||
|
self._data.set_comments(self._date, set_comments)
|
||||||
|
self._data.set_log(self._date, log)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from PySide6 import QtCore, QtGui, QtWidgets
|
from PySide6 import QtCore, QtGui, QtWidgets
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -5,7 +7,7 @@ except ImportError:
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from fime.data import Tasks
|
from fime.data import Tasks, Report
|
||||||
from fime.util import get_screen_height, get_icon, EditStartedDetector
|
from fime.util import get_screen_height, get_icon, EditStartedDetector
|
||||||
|
|
||||||
|
|
||||||
@ -25,8 +27,8 @@ class Report(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def __init__(self, tasks: Tasks, parent, *args, **kwargs):
|
def __init__(self, tasks: Tasks, parent, *args, **kwargs):
|
||||||
super().__init__(parent, *args, **kwargs)
|
super().__init__(parent, *args, **kwargs)
|
||||||
self._report = None
|
self._report: Optional[Report] = None
|
||||||
self._report_data = None
|
self._report_data: Optional[List[List[str]]] = None
|
||||||
self._changing_items = False
|
self._changing_items = False
|
||||||
self._new_log_task = ""
|
self._new_log_task = ""
|
||||||
self._new_log_pos = -1
|
self._new_log_pos = -1
|
||||||
@ -81,7 +83,7 @@ class Report(QtWidgets.QDialog):
|
|||||||
self.ok_button.setText("OK")
|
self.ok_button.setText("OK")
|
||||||
self.ok_button.setIcon(get_icon("dialog-ok"))
|
self.ok_button.setIcon(get_icon("dialog-ok"))
|
||||||
self.ok_button.pressed.connect(self._accept)
|
self.ok_button.pressed.connect(self._accept)
|
||||||
self.ok_button.setAutoDefault(True)
|
self.ok_button.setAutoDefault(False)
|
||||||
|
|
||||||
blayout = QtWidgets.QHBoxLayout()
|
blayout = QtWidgets.QHBoxLayout()
|
||||||
blayout.addWidget(self.previous_button)
|
blayout.addWidget(self.previous_button)
|
||||||
@ -95,7 +97,7 @@ class Report(QtWidgets.QDialog):
|
|||||||
layout.addLayout(blayout)
|
layout.addLayout(blayout)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def set_data(self, data):
|
def set_data(self, data: Report):
|
||||||
self._report = data
|
self._report = data
|
||||||
self.update_title()
|
self.update_title()
|
||||||
self.refresh_table()
|
self.refresh_table()
|
||||||
@ -137,9 +139,9 @@ class Report(QtWidgets.QDialog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def update_prev_next(self):
|
def update_prev_next(self):
|
||||||
prev, _next = self._report.prev_next_avail()
|
prev, next_ = self._report.prev_next_avail()
|
||||||
self.previous_button.setEnabled(prev)
|
self.previous_button.setEnabled(prev)
|
||||||
self.next_button.setEnabled(_next)
|
self.next_button.setEnabled(next_)
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def del_log(self):
|
def del_log(self):
|
||||||
|
@ -35,6 +35,5 @@ class EditStartedDetector(QtWidgets.QStyledItemDelegate):
|
|||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
editor = super().createEditor(parent, option, index)
|
editor = super().createEditor(parent, option, index)
|
||||||
editor.editingFinished.connect(self.editFinished)
|
editor.editingFinished.connect(self.editFinished)
|
||||||
editor.selectionChanged.connect(self.editFinished)
|
|
||||||
self.editStarted.emit()
|
self.editStarted.emit()
|
||||||
return editor
|
return editor
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import enum
|
import enum
|
||||||
from functools import reduce
|
from datetime import datetime
|
||||||
|
from functools import reduce, partial
|
||||||
|
from typing import Optional, List, Tuple
|
||||||
|
|
||||||
|
from fime.data import Worklog
|
||||||
from fime.progressindicator import ProgressIndicator
|
from fime.progressindicator import ProgressIndicator
|
||||||
from fime.task_completer import TaskCompleter
|
from fime.task_completer import TaskCompleter
|
||||||
from fime.util import get_icon, get_screen_height, EditStartedDetector
|
from fime.util import get_icon, get_screen_height, EditStartedDetector
|
||||||
@ -15,20 +18,20 @@ from fime.util import get_screen_width
|
|||||||
import fime.icons
|
import fime.icons
|
||||||
|
|
||||||
|
|
||||||
class Worklog(QtWidgets.QDialog):
|
class WorklogDialog(QtWidgets.QDialog):
|
||||||
class TabTable(QtWidgets.QTableWidget):
|
class TabTable(QtWidgets.QTableWidget):
|
||||||
def __init__(self, parent, *args, **kwargs):
|
def __init__(self, parent, *args, **kwargs):
|
||||||
super().__init__(parent, *args, **kwargs)
|
super().__init__(parent, *args, **kwargs)
|
||||||
|
|
||||||
def focusNextPrevChild(self, next):
|
def focusNextPrevChild(self, next_):
|
||||||
if self.currentColumn() == 1:
|
if self.currentColumn() == 1:
|
||||||
event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,
|
event = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,
|
||||||
QtCore.Qt.Key_Down if next else QtCore.Qt.Key_Up,
|
QtCore.Qt.Key_Down if next_ else QtCore.Qt.Key_Up,
|
||||||
QtCore.Qt.NoModifier)
|
QtCore.Qt.NoModifier)
|
||||||
self.keyPressEvent(event)
|
self.keyPressEvent(event)
|
||||||
if event.isAccepted():
|
if event.isAccepted():
|
||||||
return True
|
return True
|
||||||
return super().focusNextPrevChild(next)
|
return super().focusNextPrevChild(next_)
|
||||||
|
|
||||||
class ClickWidget(QtWidgets.QWidget):
|
class ClickWidget(QtWidgets.QWidget):
|
||||||
def __init__(self, item, table, parent, *args, **kwargs):
|
def __init__(self, item, table, parent, *args, **kwargs):
|
||||||
@ -64,18 +67,32 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
self.text_changed.emit(self.document().toPlainText(), self.row)
|
self.text_changed.emit(self.document().toPlainText(), self.row)
|
||||||
|
|
||||||
class TaskItemCompleter(EditStartedDetector):
|
class TaskItemCompleter(EditStartedDetector):
|
||||||
|
edit_finished_row = QtCore.Signal(int)
|
||||||
|
|
||||||
def __init__(self, config, parent=None):
|
def __init__(self, config, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.config = config
|
self.config = config
|
||||||
|
#self.row = -1
|
||||||
|
|
||||||
def createEditor(self, parent, option, index):
|
def createEditor(self, parent, option, index):
|
||||||
editor = super().createEditor(parent, option, index)
|
editor = super().createEditor(parent, option, index)
|
||||||
|
#self.row = index.row()
|
||||||
|
#editor.editingFinished.connect(partial(self.edit_finished_row_target, index.row()))
|
||||||
|
#editor.editingFinished.connect(self.edit_finished_row_target)
|
||||||
|
#self.editFinished.connect(self.edit_finished_row_target)
|
||||||
|
#self.editFinished.connect(partial(self.edit_finished_row_target, index.row()))
|
||||||
completer = TaskCompleter(self.config)
|
completer = TaskCompleter(self.config)
|
||||||
completer.setFilterMode(QtCore.Qt.MatchFlag.MatchContains)
|
completer.setFilterMode(QtCore.Qt.MatchFlag.MatchContains)
|
||||||
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||||
editor.setCompleter(completer)
|
editor.setCompleter(completer)
|
||||||
return editor
|
return editor
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def edit_finished_row_target(self, row):
|
||||||
|
#def edit_finished_row_target(self):
|
||||||
|
self.edit_finished_row.emit(row)
|
||||||
|
#self.edit_finished_row.emit(self.row)
|
||||||
|
|
||||||
class Status(enum.Enum):
|
class Status(enum.Enum):
|
||||||
PROGRESS = enum.auto()
|
PROGRESS = enum.auto()
|
||||||
OK = enum.auto()
|
OK = enum.auto()
|
||||||
@ -87,23 +104,27 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
self.setWindowTitle("Worklog")
|
self.setWindowTitle("Worklog")
|
||||||
|
|
||||||
self._changing_items = False
|
self._changing_items = False
|
||||||
self._report_data = []
|
self._worklog: Optional[Worklog] = None
|
||||||
self._status = []
|
self._worklog_data: List[List[str]] = []
|
||||||
|
self._status: List[Tuple[WorklogDialog.Status, str]] = []
|
||||||
self.row_height = None
|
self.row_height = None
|
||||||
self.focussed = False
|
self._focussed = False
|
||||||
|
|
||||||
self.tableWidget = Worklog.TabTable(self)
|
#self.tableWidget = WorklogDialog.TabTable(self)
|
||||||
|
self.tableWidget = QtWidgets.QTableWidget(self)
|
||||||
self.tableWidget.setColumnCount(3)
|
self.tableWidget.setColumnCount(3)
|
||||||
self.tableWidget.setHorizontalHeaderLabels(["Task", "Comment", "Duration"])
|
self.tableWidget.setHorizontalHeaderLabels(["Task", "Comment", "Duration"])
|
||||||
self.tableWidget.cellChanged.connect(self.cell_changed)
|
self.tableWidget.cellChanged.connect(self.cell_changed)
|
||||||
taskItemCompleter = Worklog.TaskItemCompleter(config, self)
|
taskItemCompleter = WorklogDialog.TaskItemCompleter(config, self)
|
||||||
taskItemCompleter.editStarted.connect(self.disable_buttons)
|
taskItemCompleter.editStarted.connect(self.disable_buttons)
|
||||||
taskItemCompleter.editFinished.connect(self.enable_ok)
|
taskItemCompleter.editFinished.connect(self.enable_buttons)
|
||||||
|
#taskItemCompleter.editFinished.connect(self.ensure_stati)
|
||||||
|
#taskItemCompleter.edit_finished_row.connect(self.update_status_view)
|
||||||
self.tableWidget.setItemDelegateForColumn(0, taskItemCompleter)
|
self.tableWidget.setItemDelegateForColumn(0, taskItemCompleter)
|
||||||
self.hheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal)
|
self.hheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal)
|
||||||
self.hheader.setMinimumSectionSize(10)
|
self.hheader.setMinimumSectionSize(10)
|
||||||
self.tableWidget.setHorizontalHeader(self.hheader)
|
self.tableWidget.setHorizontalHeader(self.hheader)
|
||||||
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(0), QtWidgets.QHeaderView.Stretch)
|
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(0), QtWidgets.QHeaderView.Fixed)
|
||||||
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(1), QtWidgets.QHeaderView.Fixed)
|
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(1), QtWidgets.QHeaderView.Fixed)
|
||||||
self.hheader.resizeSection(self.hheader.logicalIndex(1), get_screen_width(self) * 0.2)
|
self.hheader.resizeSection(self.hheader.logicalIndex(1), get_screen_width(self) * 0.2)
|
||||||
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(2), QtWidgets.QHeaderView.ResizeToContents)
|
self.hheader.setSectionResizeMode(self.hheader.logicalIndex(2), QtWidgets.QHeaderView.ResizeToContents)
|
||||||
@ -113,6 +134,18 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
self.tableWidget.setVerticalHeader(self.vheader)
|
self.tableWidget.setVerticalHeader(self.vheader)
|
||||||
self.tableWidget.setMaximumWidth(get_screen_width(self) * 0.8)
|
self.tableWidget.setMaximumWidth(get_screen_width(self) * 0.8)
|
||||||
|
|
||||||
|
self.previous_button = QtWidgets.QPushButton()
|
||||||
|
self.previous_button.setText("Previous")
|
||||||
|
self.previous_button.setIcon(get_icon("arrow-left"))
|
||||||
|
self.previous_button.pressed.connect(self.previous)
|
||||||
|
self.previous_button.setAutoDefault(False)
|
||||||
|
|
||||||
|
self.next_button = QtWidgets.QPushButton()
|
||||||
|
self.next_button.setText("Next")
|
||||||
|
self.next_button.setIcon(get_icon("arrow-right"))
|
||||||
|
self.next_button.pressed.connect(self.next)
|
||||||
|
self.next_button.setAutoDefault(False)
|
||||||
|
|
||||||
self.upload_button = QtWidgets.QPushButton()
|
self.upload_button = QtWidgets.QPushButton()
|
||||||
self.upload_button.setText("Upload")
|
self.upload_button.setText("Upload")
|
||||||
self.upload_button.setIcon(get_icon("cloud-upload"))
|
self.upload_button.setIcon(get_icon("cloud-upload"))
|
||||||
@ -124,10 +157,12 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
self.ok_button = QtWidgets.QPushButton()
|
self.ok_button = QtWidgets.QPushButton()
|
||||||
self.ok_button.setText("OK")
|
self.ok_button.setText("OK")
|
||||||
self.ok_button.setIcon(get_icon("dialog-ok"))
|
self.ok_button.setIcon(get_icon("dialog-ok"))
|
||||||
#self.ok_button.pressed.connect(self._accept)
|
self.ok_button.pressed.connect(self._accept)
|
||||||
self.ok_button.setAutoDefault(True)
|
self.ok_button.setAutoDefault(False)
|
||||||
|
|
||||||
alayout = QtWidgets.QHBoxLayout()
|
alayout = QtWidgets.QHBoxLayout()
|
||||||
|
alayout.addWidget(self.previous_button)
|
||||||
|
alayout.addWidget(self.next_button)
|
||||||
alayout.addSpacerItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Expanding))
|
alayout.addSpacerItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Expanding))
|
||||||
alayout.addWidget(self.upload_button)
|
alayout.addWidget(self.upload_button)
|
||||||
alayout.addWidget(self.ok_button)
|
alayout.addWidget(self.ok_button)
|
||||||
@ -137,64 +172,93 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
layout.addLayout(alayout)
|
layout.addLayout(alayout)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
|
|
||||||
def set_data(self, data):
|
def set_data(self, worklog: Worklog):
|
||||||
self._report_data = data
|
self._worklog = worklog
|
||||||
for i, _ in enumerate(self._report_data):
|
|
||||||
self._status.append((Worklog.Status.PROGRESS, "Fetching"))
|
|
||||||
self.refresh_table()
|
self.refresh_table()
|
||||||
|
self.update_title()
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
def update_status(self, row, new_status, status_text="Could not find specified issue"):
|
def update_status(self, row, new_status, status_text="Could not find specified issue"):
|
||||||
self._status[row] = (new_status, status_text)
|
self._status[row] = (new_status, status_text)
|
||||||
self.update_status_view(row)
|
self.update_status_view(row)
|
||||||
all_ok = reduce(lambda acc, it: acc and it[0] is Worklog.Status.OK, self._status, True)
|
all_ok = reduce(lambda acc, it: acc and it[0] is WorklogDialog.Status.OK, self._status, True)
|
||||||
if all_ok:
|
if all_ok:
|
||||||
self.upload_button.setEnabled(True)
|
self.upload_button.setEnabled(True)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self._worklog.worklog = self._worklog_data
|
||||||
|
|
||||||
|
def update_title(self):
|
||||||
|
self.setWindowTitle(f"Worklog {self._worklog.date()}")
|
||||||
|
|
||||||
def refresh_table(self):
|
def refresh_table(self):
|
||||||
|
self._worklog_data = self._worklog.worklog
|
||||||
|
for i, _ in enumerate(self._worklog_data[:-1]):
|
||||||
|
self._status.append((WorklogDialog.Status.PROGRESS, "Fetching"))
|
||||||
self._changing_items = True
|
self._changing_items = True
|
||||||
if not self.row_height:
|
if not self.row_height:
|
||||||
self.tableWidget.setRowCount(1)
|
self.tableWidget.setRowCount(1)
|
||||||
item = QtWidgets.QTableWidgetItem("test")
|
item = QtWidgets.QTableWidgetItem("test")
|
||||||
self.tableWidget.setItem(0, 0, item)
|
self.tableWidget.setItem(0, 0, item)
|
||||||
self.row_height = self.tableWidget.rowHeight(0)
|
self.row_height = self.tableWidget.rowHeight(0)
|
||||||
self.tableWidget.setRowCount(len(self._report_data))
|
self.tableWidget.setRowCount(len(self._worklog_data))
|
||||||
|
|
||||||
for row, _ in enumerate(self._report_data):
|
for row, _ in enumerate(self._worklog_data):
|
||||||
item0 = QtWidgets.QTableWidgetItem(self._report_data[row][0])
|
item0 = QtWidgets.QTableWidgetItem(self._worklog_data[row][0])
|
||||||
self.tableWidget.setItem(row, 0, item0)
|
self.tableWidget.setItem(row, 0, item0)
|
||||||
self.update_status_view(row)
|
if row == len(self._worklog_data) - 1:
|
||||||
text_edit = Worklog.TableTextEdit(self._report_data[row][1], row, self)
|
self.tableWidget.removeCellWidget(row, 0)
|
||||||
text_edit.textChanged.connect(self.on_resize)
|
item0.setFlags(item0.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
text_edit.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
item1 = QtWidgets.QTableWidgetItem("")
|
||||||
text_edit.text_changed.connect(self.text_edit_changed)
|
self.tableWidget.setItem(row, 1, item1)
|
||||||
self.tableWidget.setCellWidget(row, 1, text_edit)
|
item1.setFlags(item1.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
if row == 0 and not self.focussed:
|
else:
|
||||||
text_edit.setFocus()
|
self.update_status_view(row)
|
||||||
self.focussed = True
|
text_edit = WorklogDialog.TableTextEdit(self._worklog_data[row][1], row, self)
|
||||||
item2 = QtWidgets.QTableWidgetItem(self._report_data[row][2])
|
text_edit.textChanged.connect(self.on_resize)
|
||||||
|
text_edit.setFrameStyle(QtWidgets.QFrame.NoFrame)
|
||||||
|
text_edit.text_changed.connect(self.text_edit_changed)
|
||||||
|
self.tableWidget.setCellWidget(row, 1, text_edit)
|
||||||
|
if row == 0 and not self._focussed:
|
||||||
|
text_edit.setFocus()
|
||||||
|
self._focussed = True
|
||||||
|
item2 = QtWidgets.QTableWidgetItem(self._worklog_data[row][2])
|
||||||
self.tableWidget.setItem(row, 2, item2)
|
self.tableWidget.setItem(row, 2, item2)
|
||||||
item2.setFlags(item2.flags() & QtCore.Qt.ItemIsEnabled)
|
item2.setFlags(item2.flags() & QtCore.Qt.ItemIsEnabled)
|
||||||
self._changing_items = False
|
self._changing_items = False
|
||||||
|
|
||||||
self.tableWidget.resizeColumnToContents(0)
|
self.tableWidget.resizeColumnToContents(0)
|
||||||
desired_width = self.tableWidget.columnWidth(0) + self.tableWidget.columnWidth(1) + self.tableWidget.columnWidth(2)
|
self.tableWidget.setColumnWidth(0, self.tableWidget.columnWidth(0) + self.row_height)
|
||||||
|
desired_width = self.tableWidget.columnWidth(0) + self.tableWidget.columnWidth(1) + self.tableWidget.columnWidth(2) + 4
|
||||||
self.tableWidget.setMinimumWidth(min(desired_width, self.tableWidget.maximumWidth()))
|
self.tableWidget.setMinimumWidth(min(desired_width, self.tableWidget.maximumWidth()))
|
||||||
|
self.adjustSize()
|
||||||
|
|
||||||
screen = QtGui.QGuiApplication.screenAt(self.pos())
|
screen = QtGui.QGuiApplication.screenAt(self.pos())
|
||||||
x = ((screen.size().width() - self.tableWidget.width()) // 2) + screen.geometry().left()
|
x = ((screen.size().width() - self.tableWidget.width()) // 2) + screen.geometry().left()
|
||||||
y = ((screen.size().height() - self.height()) // 2) + screen.geometry().top()
|
y = ((screen.size().height() - self.height()) // 2) + screen.geometry().top()
|
||||||
self.move(x, y)
|
self.move(x, y)
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def ensure_stati(self):
|
||||||
|
print("ensure_stati")
|
||||||
|
for i in range(len(self._worklog_data)-1):
|
||||||
|
cw = self.tableWidget.cellWidget(i, 0)
|
||||||
|
if type(cw) is not WorklogDialog.ClickWidget:
|
||||||
|
print(f"ensure_stati: {self.tableWidget.item(i, 0).text()}")
|
||||||
|
self.update_status_view(i)
|
||||||
|
#print(cw)
|
||||||
|
|
||||||
def update_status_view(self, row):
|
def update_status_view(self, row):
|
||||||
if self._status[row][0] is Worklog.Status.PROGRESS:
|
print(self.tableWidget.item(row, 0).text())
|
||||||
|
if self._status[row][0] is WorklogDialog.Status.PROGRESS:
|
||||||
icon = ProgressIndicator(self)
|
icon = ProgressIndicator(self)
|
||||||
icon.setMaximumSize(QtCore.QSize(self.row_height * 0.75, self.row_height * 0.75))
|
icon.setMaximumSize(QtCore.QSize(self.row_height * 0.75, self.row_height * 0.75))
|
||||||
icon.setAnimationDelay(70)
|
icon.setAnimationDelay(70)
|
||||||
icon.startAnimation()
|
icon.startAnimation()
|
||||||
else:
|
else:
|
||||||
if self._status[row][0] is Worklog.Status.OK:
|
if self._status[row][0] is WorklogDialog.Status.OK:
|
||||||
item_name = "dialog-ok"
|
item_name = "dialog-ok"
|
||||||
elif self._status[row][0] is Worklog.Status.ERROR:
|
elif self._status[row][0] is WorklogDialog.Status.ERROR:
|
||||||
item_name = "edit-delete-remove"
|
item_name = "edit-delete-remove"
|
||||||
icon = QtWidgets.QLabel()
|
icon = QtWidgets.QLabel()
|
||||||
icon.setPixmap(get_icon(item_name).pixmap(self.row_height * 0.75, self.row_height * 0.75))
|
icon.setPixmap(get_icon(item_name).pixmap(self.row_height * 0.75, self.row_height * 0.75))
|
||||||
@ -204,7 +268,7 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
layout.setContentsMargins(self.row_height * 0.1, self.row_height * 0.1,
|
layout.setContentsMargins(self.row_height * 0.1, self.row_height * 0.1,
|
||||||
self.row_height * 0.1, self.row_height * 0.1)
|
self.row_height * 0.1, self.row_height * 0.1)
|
||||||
|
|
||||||
wdgt = Worklog.ClickWidget(self.tableWidget.item(row, 0), self.tableWidget, self)
|
wdgt = WorklogDialog.ClickWidget(self.tableWidget.item(row, 0), self.tableWidget, self)
|
||||||
wdgt.setLayout(layout)
|
wdgt.setLayout(layout)
|
||||||
self.tableWidget.setCellWidget(row, 0, wdgt)
|
self.tableWidget.setCellWidget(row, 0, wdgt)
|
||||||
|
|
||||||
@ -214,21 +278,55 @@ class Worklog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def disable_buttons(self):
|
def disable_buttons(self):
|
||||||
|
self.previous_button.setEnabled(False)
|
||||||
|
self.next_button.setEnabled(False)
|
||||||
self.upload_button.setEnabled(False)
|
self.upload_button.setEnabled(False)
|
||||||
self.ok_button.setEnabled(False)
|
self.ok_button.setEnabled(False)
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def enable_ok(self):
|
def enable_buttons(self):
|
||||||
self.ok_button.setEnabled(True)
|
self.ok_button.setEnabled(True)
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
|
def update_prev_next(self):
|
||||||
|
prev, next_ = self._worklog.prev_next_avail()
|
||||||
|
self.previous_button.setEnabled(prev)
|
||||||
|
self.next_button.setEnabled(next_)
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def previous(self):
|
||||||
|
self.save()
|
||||||
|
self._worklog.previous()
|
||||||
|
self.update_title()
|
||||||
|
self._focussed = False
|
||||||
|
self.refresh_table()
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def next(self):
|
||||||
|
self.save()
|
||||||
|
self._worklog.next()
|
||||||
|
self.update_title()
|
||||||
|
self._focussed = False
|
||||||
|
self.refresh_table()
|
||||||
|
self.update_prev_next()
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def cell_changed(self, row, _):
|
def cell_changed(self, row, _):
|
||||||
|
#print(f"{datetime.now()} cell_changed: {self._changing_items}")
|
||||||
if self._changing_items:
|
if self._changing_items:
|
||||||
return
|
return
|
||||||
self._report_data[row][0] = self.tableWidget.item(row, 0).text()
|
print(f"{datetime.now()} cell_changed")
|
||||||
self.update_status(row, Worklog.Status.PROGRESS, "Fetching")
|
self._worklog_data[row][0] = self.tableWidget.item(row, 0).text()
|
||||||
|
self.save()
|
||||||
|
self.update_status(row, WorklogDialog.Status.PROGRESS, "Fetching")
|
||||||
self.refresh_table()
|
self.refresh_table()
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def text_edit_changed(self, text, row):
|
def text_edit_changed(self, text, row):
|
||||||
self._report_data[row][1] = text
|
self._worklog_data[row][1] = text
|
||||||
|
|
||||||
|
@QtCore.Slot()
|
||||||
|
def _accept(self):
|
||||||
|
self.save()
|
||||||
|
self.accept()
|
||||||
|
Loading…
Reference in New Issue
Block a user