from PySide2 import QtCore, QtGui, QtWidgets from datetime import datetime class Report(QtWidgets.QDialog): def __init__(self, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) self._report = None self._report_data = None self._changing_items = False self.setWindowTitle("Report") self.tableWidget = QtWidgets.QTableWidget() self.tableWidget.verticalHeader().hide() self.tableWidget.setColumnCount(3) self.tableWidget.setHorizontalHeaderLabels(["Task", "Start time", "Duration"]) self.tableWidget.cellChanged.connect(self.cell_changed) self.header = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal) self.tableWidget.setHorizontalHeader(self.header) self.previous_button = QtWidgets.QPushButton() self.previous_button.setText("Previous") self.previous_button.setIcon(QtGui.QIcon.fromTheme("arrow-left")) 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.setText("Delete item") del_button.setIcon(QtGui.QIcon.fromTheme("list-remove")) del_button.pressed.connect(self.del_log) ok_button = QtWidgets.QPushButton() ok_button.setText("OK") ok_button.setIcon(QtGui.QIcon.fromTheme("dialog-ok-apply")) ok_button.pressed.connect(self._accept) blayout = QtWidgets.QHBoxLayout() blayout.addWidget(self.previous_button) blayout.addWidget(self.next_button) blayout.addWidget(del_button) blayout.addWidget(ok_button) layout = QtWidgets.QVBoxLayout(self) layout.addWidget(self.tableWidget) layout.addLayout(blayout) self.setLayout(layout) def set_data(self, data): self._report = data self.refresh_table() self.update_prev_next() def save(self): self._report.save(self._report_data) def refresh_table(self): self._report_data = self._report.report() self.tableWidget.setRowCount(len(self._report_data)) self._changing_items = True 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) - 4: item1.setFlags(item1.flags() & QtCore.Qt.ItemIsEnabled) self._changing_items = False self.tableWidget.resizeColumnsToContents() min_width = 0 for i in range(3): min_width += self.header.sectionSize(i) self.tableWidget.setMinimumWidth(min_width * 1.33) self.header.setSectionResizeMode(QtWidgets.QHeaderView.Stretch) if self.tableWidget.rowCount() > 4: self.tableWidget.setMinimumHeight(min((self.tableWidget.rowCount() + 2) * self.tableWidget.rowHeight(0), self.tableWidget.screen().size().height() * 0.8)) def update_prev_next(self): prev, _next = self._report.prev_next_avail() self.previous_button.setEnabled(prev) self.next_button.setEnabled(_next) @QtCore.Slot() def del_log(self): row = self.tableWidget.currentRow() if row > len(self._report_data) - 4: return del self._report_data[row] self.save() self.refresh_table() @QtCore.Slot() def _accept(self): self.save() self.accept() @QtCore.Slot() def previous(self): self.save() self._report.previous() self.refresh_table() self.update_prev_next() @QtCore.Slot() def next(self): self.save() self._report.next() self.refresh_table() self.update_prev_next() @QtCore.Slot() def cell_changed(self, row, column): if self._changing_items: return item = self.tableWidget.item(row, column) try: new_time = datetime.strptime(item.text(), "%H:%M").time() except ValueError: item.setText(self._report_data[row][column]) return self._report_data[row][column] = new_time.strftime("%H:%M") self.save() self.refresh_table()