diff --git a/src/fime/icons/__init__.py b/src/fime/icons/__init__.py index 84ad714..ac24377 100644 --- a/src/fime/icons/__init__.py +++ b/src/fime/icons/__init__.py @@ -9,6 +9,48 @@ except ImportError: from PySide2 import QtCore qt_resource_data = b"\ +\x00\x00\x02x\ +<\ +svg xmlns=\x22http:\ +//www.w3.org/200\ +0/svg\x22 viewBox=\x22\ +0 0 24 24\x22 width\ +=\x2224\x22 height=\x2224\ +\x22>\x0a \x0a \x0a\ + .ColorSche\ +me-Text {\x0a \ + color:#232629;\ +\x0a }\x0a <\ +/style>\x0a \x0a \x0a \x0a \x0a\ +\x0a\ \x00\x00\x02\xdd\ <\ svg xmlns=\x22http:\ @@ -120,6 +162,47 @@ Scheme-Text {\x0a \ rScheme-Text\x22 fi\ ll=\x22currentColor\ \x22/>\x0a\x0a\ +\x00\x00\x02g\ +<\ +svg xmlns=\x22http:\ +//www.w3.org/200\ +0/svg\x22 version=\x22\ +1.1\x22 viewBox=\x220 \ +0 24 24\x22 width=\x22\ +24\x22 height=\x2224\x22>\ +\x0a \x0a \x0a \ +\x0a \x0a<\ +/svg>\x0a\ \x00\x00\x01K\ <\ svg viewBox=\x220 0\ @@ -300,6 +383,10 @@ qt_resource_name = b"\ \x00o\xa6S\ \x00i\ \x00c\x00o\x00n\x00s\ +\x00\x10\ +\x03\x84Y\x07\ +\x00c\ +\x00l\x00o\x00u\x00d\x00-\x00u\x00p\x00l\x00o\x00a\x00d\x00.\x00s\x00v\x00g\ \x00\x11\ \x03S\x8a\x87\ \x00d\ @@ -314,6 +401,11 @@ qt_resource_name = b"\ \x0f\x22iG\ \x00a\ \x00r\x00r\x00o\x00w\x00-\x00r\x00i\x00g\x00h\x00t\x00.\x00s\x00v\x00g\ +\x00\x16\ +\x0e\x92\x91G\ +\x00e\ +\x00d\x00i\x00t\x00-\x00d\x00e\x00l\x00e\x00t\x00e\x00-\x00r\x00e\x00m\x00o\x00v\ +\x00e\x00.\x00s\x00v\x00g\ \x00\x0e\ \x08\xfa8\xa7\ \x00a\ @@ -344,25 +436,29 @@ qt_resource_name = b"\ qt_resource_struct = b"\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x00\x00\x00\x02\x00\x00\x00\x09\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00\x02\ \x00\x00\x00\x00\x00\x00\x00\x00\ -\x00\x00\x01<\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xe9\ +\x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x00\x13\xd0\ \x00\x00\x01}.b\xfd-\ -\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x006\x00\x00\x00\x00\x00\x01\x00\x00\x02|\ \x00\x00\x01}.a\xe4+\ -\x00\x00\x008\x00\x00\x00\x00\x00\x01\x00\x00\x02\xe1\ +\x00\x00\x00^\x00\x00\x00\x00\x00\x01\x00\x00\x05]\ \x00\x00\x01}.\x1a\xb9\xf9\ -\x00\x00\x00\x88\x00\x00\x00\x00\x00\x01\x00\x00\x06\x95\ +\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01}b-h:\ +\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x0b|\ \x00\x00\x01}.b $\ -\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x0d\x82\ +\x00\x00\x01t\x00\x00\x00\x00\x00\x01\x00\x00\x12i\ \x00\x00\x01}.a\xce_\ -\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x07\xe4\ +\x00\x00\x01\x02\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xcb\ \x00\x00\x01}.b\xe1.\ -\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x01\x00\x00\x09\xce\ +\x00\x00\x01 \x00\x00\x00\x00\x00\x01\x00\x00\x0e\xb5\ \x00\x00\x01}/\x83\xea~\ -\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x0c2\ +\x00\x00\x01X\x00\x00\x00\x00\x00\x01\x00\x00\x11\x19\ \x00\x00\x01}.b\x05\xfc\ -\x00\x00\x00d\x00\x00\x00\x00\x00\x01\x00\x00\x05E\ +\x00\x00\x00\xae\x00\x00\x00\x00\x00\x01\x00\x00\x09\x11\ +\x00\x00\x01}a\xb5\x12\xd7\ +\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x01\x00\x00\x07\xc1\ \x00\x00\x01}.b1)\ " diff --git a/src/fime/icons/cloud-upload.svg b/src/fime/icons/cloud-upload.svg new file mode 100644 index 0000000..9ac42c0 --- /dev/null +++ b/src/fime/icons/cloud-upload.svg @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/fime/icons/edit-delete-remove.svg b/src/fime/icons/edit-delete-remove.svg new file mode 100644 index 0000000..99d8260 --- /dev/null +++ b/src/fime/icons/edit-delete-remove.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/fime/icons/resources.qrc b/src/fime/icons/resources.qrc index 412805d..6ea08da 100644 --- a/src/fime/icons/resources.qrc +++ b/src/fime/icons/resources.qrc @@ -5,8 +5,10 @@ appointment-new-light.svg arrow-left.svg arrow-right.svg + cloud-upload.svg dialog-cancel.svg dialog-ok.svg + edit-delete-remove.svg go-next.svg list-add.svg list-remove.svg diff --git a/src/fime/worklog.py b/src/fime/worklog.py index 58bdf24..ff1a432 100644 --- a/src/fime/worklog.py +++ b/src/fime/worklog.py @@ -1,4 +1,7 @@ +import enum + from fime.progressindicator import ProgressIndicator +from fime.util import get_icon, get_screen_height try: from PySide6 import QtCore, QtGui, QtWidgets @@ -37,35 +40,12 @@ class Worklog(QtWidgets.QDialog): editor = self.table.cellWidget(self.table.currentRow(), self.table.currentColumn()) editor.setFocus() - def __init__(self, parent, *args, **kwargs): - super().__init__(parent, *args, **kwargs) - - self.setWindowTitle("Worklog") - - self._changing_items = False - - self.tableWidget = Worklog.TabTable(self) - self.tableWidget.setColumnCount(3) - self.tableWidget.setHorizontalHeaderLabels(["Task", "Comment", "Duration"]) - self.tableWidget.cellChanged.connect(self.cell_changed) - self.hheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal) - self.hheader.setMinimumSectionSize(1) - self.hheader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) - self.tableWidget.setHorizontalHeader(self.hheader) - self.hheader.setSectionResizeMode(self.hheader.logicalIndex(1), QtWidgets.QHeaderView.Stretch) - self.vheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Vertical) - self.vheader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) - self.vheader.hide() - self.tableWidget.setVerticalHeader(self.vheader) - - layout = QtWidgets.QVBoxLayout(self) - layout.addWidget(self.tableWidget) - self.setLayout(layout) - self.refresh_table() - class TableTextEdit(QtWidgets.QTextEdit): - def __init__(self, text, parent, *args, **kwargs): + text_changed = QtCore.Signal(str, int) + + def __init__(self, text, row, parent, *args, **kwargs): super().__init__(parent, *args, **kwargs) + self.row = row self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setLineWrapMode(QtWidgets.QTextEdit.WidgetWidth) self.setAcceptRichText(False) @@ -79,61 +59,131 @@ class Worklog(QtWidgets.QDialog): @QtCore.Slot() def on_text_changed(self): self.setFixedHeight(self.document().size().toSize().height()) + self.text_changed.emit(self.document().toPlainText(), self.row) + + class Status(enum.Enum): + PROGRESS = enum.auto() + OK = enum.auto() + ERROR = enum.auto() + + def __init__(self, parent, *args, **kwargs): + super().__init__(parent, *args, **kwargs) + + self.setWindowTitle("Worklog") + + self._changing_items = False + self._report_data = [] + self._status = [] + self.row_height = None + + self.tableWidget = Worklog.TabTable(self) + self.tableWidget.setColumnCount(3) + self.tableWidget.setHorizontalHeaderLabels(["Task", "Comment", "Duration"]) + self.tableWidget.cellChanged.connect(self.cell_changed) + self.hheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Horizontal) + self.hheader.setMinimumSectionSize(10) + self.tableWidget.setHorizontalHeader(self.hheader) + self.hheader.setSectionResizeMode(self.hheader.logicalIndex(0), QtWidgets.QHeaderView.Stretch) + 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.setSectionResizeMode(self.hheader.logicalIndex(2), QtWidgets.QHeaderView.ResizeToContents) + self.vheader = QtWidgets.QHeaderView(QtCore.Qt.Orientation.Vertical) + self.vheader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) + self.vheader.hide() + self.tableWidget.setVerticalHeader(self.vheader) + self.tableWidget.setMaximumWidth(get_screen_width(self) * 0.8) + + self.upload_button = QtWidgets.QPushButton() + self.upload_button.setText("Upload") + self.upload_button.setIcon(get_icon("cloud-upload")) + #self.upload_button.pressed.connect(self.del_log) + self.upload_button.setAutoDefault(False) + self.upload_button.setMinimumWidth(self.upload_button.minimumSizeHint().width() * 1.33) + + self.ok_button = QtWidgets.QPushButton() + self.ok_button.setText("OK") + self.ok_button.setIcon(get_icon("dialog-ok")) + #self.ok_button.pressed.connect(self._accept) + self.ok_button.setAutoDefault(True) + + alayout = QtWidgets.QHBoxLayout() + alayout.addSpacerItem(QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Expanding)) + alayout.addWidget(self.upload_button) + alayout.addWidget(self.ok_button) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(self.tableWidget) + layout.addLayout(alayout) + self.setLayout(layout) + + def set_data(self, data): + self._report_data = data + for i, _ in enumerate(self._report_data): + self._status.append( + (Worklog.Status.PROGRESS, "Fetching") + ) + self.refresh_table() + + def update_status(self, row, new_status, status_text="Could not find specified issue"): + self._status[row] = (new_status, status_text) + self.update_status_view(row) def refresh_table(self): self._changing_items = True - self._report_data = [ - ["ASG-8690 Ansible - Debian 11 Support", "Impl\nMore impl", "01:23"], - ["ASG-8342 Ansible - MariaDB Rolle überarbeiten ", "Test", "03:57"], - ["ASG-8685 CATS Testsystem: Debian Upgrades Server mit Version kleiner 10 ", "Doing", "02:12"], - ] + if not self.row_height: + self.tableWidget.setRowCount(1) + item = QtWidgets.QTableWidgetItem("test") + self.tableWidget.setItem(0, 0, item) + self.row_height = self.tableWidget.rowHeight(0) self.tableWidget.setRowCount(len(self._report_data)) for row, _ in enumerate(self._report_data): item0 = QtWidgets.QTableWidgetItem(self._report_data[row][0]) self.tableWidget.setItem(row, 0, item0) - size = self.tableWidget.rowHeight(row) - if row == 1: - icon = ProgressIndicator(self) - icon.setMaximumSize(QtCore.QSize(size * 0.75, size * 0.75)) - icon.setAnimationDelay(70) - icon.startAnimation() - else: - if row == 0: - item_name = "dialog-ok" - elif row == 2: - item_name = "edit-delete-remove" - icon = QtWidgets.QLabel() - icon.setPixmap(QtGui.QIcon.fromTheme(item_name).pixmap(size * 0.75, size * 0.75)) - icon.setToolTip("something has gone wrong") - layout = QtWidgets.QHBoxLayout() - layout.addWidget(icon, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) - layout.setContentsMargins(size * 0.1, size * 0.1, size * 0.1, size * 0.1) - wdgt = Worklog.ClickWidget(item0, self.tableWidget, self) - wdgt.setLayout(layout) - self.tableWidget.setCellWidget(row, 0, wdgt) - #item1 = QtWidgets.QTableWidgetItem(self._report_data[row][1]) - #self.tableWidget.setItem(row, 1, item1) - #print(self.tableWidget.cellWidget(0, 0).height()) - text_edit = Worklog.TableTextEdit(self._report_data[row][1], self) + self.update_status_view(row) + text_edit = Worklog.TableTextEdit(self._report_data[row][1], row, self) 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: text_edit.setFocus() item2 = QtWidgets.QTableWidgetItem(self._report_data[row][2]) self.tableWidget.setItem(row, 2, item2) item2.setFlags(item2.flags() & QtCore.Qt.ItemIsEnabled) - self.tableWidget.resizeColumnToContents(0) - # TODO integrate entered text and max screen width - comment_width = get_screen_width(self) * 0.2 - self.tableWidget.setMinimumWidth(self.tableWidget.columnWidth(0) + comment_width + self.tableWidget.columnWidth(2)) - self.tableWidget.setColumnWidth(0, self.tableWidget.columnWidth(0) * 1.05) - # broken - #self.tableWidget.setTabOrder(self.tableWidget.cellWidget(0, 1), self.tableWidget.cellWidget(1, 1)) - QtWidgets.QWidget.setTabOrder(self.tableWidget.cellWidget(0, 1), self.tableWidget.cellWidget(1, 1)) self._changing_items = False + self.tableWidget.resizeColumnToContents(0) + desired_width = self.tableWidget.columnWidth(0) + self.tableWidget.columnWidth(1) + self.tableWidget.columnWidth(2) + self.tableWidget.setMinimumWidth(min(desired_width, self.tableWidget.maximumWidth())) + screen = QtGui.QGuiApplication.screenAt(self.pos()) + x = ((screen.size().width() - self.tableWidget.width()) // 2) + screen.geometry().left() + y = ((screen.size().height() - self.height()) // 2) + screen.geometry().top() + self.move(x, y) + + def update_status_view(self, row): + if self._status[row][0] is Worklog.Status.PROGRESS: + icon = ProgressIndicator(self) + icon.setMaximumSize(QtCore.QSize(self.row_height * 0.75, self.row_height * 0.75)) + icon.setAnimationDelay(70) + icon.startAnimation() + else: + if self._status[row][0] is Worklog.Status.OK: + item_name = "dialog-ok" + elif self._status[row][0] is Worklog.Status.ERROR: + item_name = "edit-delete-remove" + icon = QtWidgets.QLabel() + icon.setPixmap(get_icon(item_name).pixmap(self.row_height * 0.75, self.row_height * 0.75)) + icon.setToolTip(self._status[row][1]) + layout = QtWidgets.QHBoxLayout() + layout.addWidget(icon, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + layout.setContentsMargins(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.setLayout(layout) + self.tableWidget.setCellWidget(row, 0, wdgt) + @QtCore.Slot() def on_resize(self): self.tableWidget.resizeRowsToContents() @@ -147,8 +197,13 @@ class Worklog(QtWidgets.QDialog): pass @QtCore.Slot() - def cell_changed(self, row, column): + def cell_changed(self, row, _): if self._changing_items: return - print(f"cell changed: {row}, {column}") + self._report_data[row][0] = self.tableWidget.item(row, 0).text() + self.update_status(row, Worklog.Status.PROGRESS, "Fetching") self.refresh_table() + + @QtCore.Slot() + def text_edit_changed(self, text, row): + self._report_data[row][1] = text