diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py index a7b40c9f98ed8c35f77c6d357021de31f1a278c3..61a77987ef0ff4a0419e21831daf79549afbda0c 100644 --- a/src/View/ASubWindow.py +++ b/src/View/ASubWindow.py @@ -17,7 +17,7 @@ from PyQt5.QtWidgets import ( QTimeEdit, QSpinBox, QTextEdit, QRadioButton, QComboBox, QFileDialog, QMessageBox, QTableView, QAction, - QDateTimeEdit, + QDateTimeEdit, QWidget, ) from PyQt5.QtCore import ( QTime, QDateTime, @@ -409,7 +409,6 @@ class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit): return self.ui.findChild(qtype, name) - class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit): def __init__(self, name="", ui="dummy", parent=None): super(ASubWindow, self).__init__(parent=parent) @@ -439,3 +438,27 @@ class ASubWindow(QDialog, ASubWindowFeatures, WindowToolKit): qtype = self._qtype_from_component_name(name) return self.ui.findChild(qtype, name) + +class AWidget(QWidget, ASubWindowFeatures): + def __init__(self, ui="", parent=None): + super(AWidget, self).__init__(parent=parent) + self.ui = loadUi( + os.path.join(os.path.dirname(__file__), "ui", "Widgets", f"{ui}.ui"), + self + ) + self.parent = parent + + def find(self, qtype, name): + """Find an ui component + + Args: + qtype: Type of QT component + name: Name for component + + Returns: + return the component + """ + if qtype is None: + qtype = self._qtype_from_component_name(name) + + return self.ui.findChild(qtype, name) diff --git a/src/View/BoundaryCondition/Edit/Plot.py b/src/View/BoundaryCondition/Edit/Plot.py index 39af012c42fd95a7fa02c8af5448e4b2fb4dbb11..efb039e7e989c7dc20b73ba9cb1cbe8b33b9e2c5 100644 --- a/src/View/BoundaryCondition/Edit/Plot.py +++ b/src/View/BoundaryCondition/Edit/Plot.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +from datetime import datetime + from tools import timer, trace from View.Plot.APlot import APlot @@ -19,6 +21,35 @@ class Plot(APlot): toolbar=toolbar ) + def custom_ticks(self): + t0 = datetime.fromtimestamp(0) + nb = len(self.data.data) + mod = int(nb / 5) + + fx = list( + map( + lambda x: x[1], + filter( + lambda x: x[0] % mod == 0, + enumerate(self.data.data) + ) + ) + ) + xx = list(map(lambda v: v[0], fx)) + xt = list( + map( + lambda v: str( + datetime.fromtimestamp(v[0]) - t0 + ).split(",")[0]\ + .replace("days", _translate("BoundaryCondition", "days"))\ + .replace("day", _translate("BoundaryCondition", "day")), + fx + ) + ) + + self.canvas.axes.set_xticks(ticks=xx, labels=xt, rotation=45) + + @timer def draw(self): self.canvas.axes.cla() @@ -38,6 +69,8 @@ class Plot(APlot): picker=30, ) + self.custom_ticks() + # Plot label header = self.data.header self.canvas.axes.set_xlabel( @@ -65,6 +98,8 @@ class Plot(APlot): self._line.set_data(x, y) + self.custom_ticks() + self.canvas.axes.relim() self.canvas.axes.autoscale() self.canvas.figure.tight_layout() diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index a068a247082ef6373b2942bc53fc0af2c09345c2..b6b5f36a8ac23f0d3a3f35df2009748f019be048 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -1,18 +1,21 @@ # -*- coding: utf-8 -*- +from datetime import date, time, datetime, timedelta + from tools import trace, timer -from View.ASubWindow import ASubMainWindow +from View.ASubWindow import ASubMainWindow, AWidget from View.ListedSubWindow import ListedSubWindow from PyQt5.QtCore import ( Qt, QVariant, QAbstractTableModel, QCoreApplication, QModelIndex, pyqtSlot, - QRect, + QRect, QTime, ) from PyQt5.QtWidgets import ( - QTableView, QAbstractItemView, + QTableView, QAbstractItemView, QSpinBox, + QTimeEdit, QItemDelegate, ) from Model.BoundaryCondition.BoundaryConditionTypes import ( @@ -30,6 +33,79 @@ from View.BoundaryCondition.Edit.translate import * _translate = QCoreApplication.translate +class ExtendedTimeEdit(AWidget): + def __init__(self, parent=None): + super(ExtendedTimeEdit, self).__init__( + ui="extendedTimeEdit", + parent=parent + ) + self.parent = parent + + self.spinBox_days = self.find(QSpinBox, "spinBox_days") + self.timeEdit = self.find(QTimeEdit, "timeEdit") + + def set_time(self, time): + days = 0 + stime = time + + if "," in time: + s = time.strip().split(" ") + days = int(s[0]) + stime = s[-1] + + qtime = QTime.fromString( + stime, + "h:mm:ss" + ) + self.spinBox_days.setValue(days) + self.timeEdit.setTime(qtime) + + def get_time(self): + days = self.spinBox_days.value() + time = self.timeEdit.time().toPyTime() + secs = ( + (time.hour * 3600) + + (time.minute * 60) + + time.second + ) + + return timedelta(days=days, seconds=secs) + + +class ExTimeDelegate(QItemDelegate): + def __init__(self, data=None, mode="time", parent=None): + super(ExTimeDelegate, self).__init__(parent) + + self._data = data + self._mode = mode + + def createEditor(self, parent, option, index): + self.editor = ExtendedTimeEdit(parent=parent) + value = index.data(Qt.DisplayRole) + self.editor.set_time(value) + return self.editor + + def setEditorData(self, editor, index): + value = index.data(Qt.DisplayRole) + self.editor.currentTextChanged.connect(self.currentItemChanged) + + def setModelData(self, editor, model, index): + time = editor.get_time() + model.setData(index, int(time.total_seconds())) + editor.close() + editor.deleteLater() + + def updateEditorGeometry(self, editor, option, index): + r = QRect(option.rect) + if self.editor.windowFlags() & Qt.Popup and editor.parent() is not None: + r.setTopLeft(self.editor.parent().mapToGlobal(r.topLeft())) + editor.setGeometry(r) + + @pyqtSlot() + def currentItemChanged(self): + self.commitData.emit(self.sender()) + + class TableModel(QAbstractTableModel): def __init__(self, data=None, undo=None): super(QAbstractTableModel, self).__init__() @@ -65,6 +141,11 @@ class TableModel(QAbstractTableModel): v = self._data.get_i(row)[column] if self._data.get_type_column(column) == float: value = f"{v:.4f}" + elif self._data.header[column] == "time": + t0 = datetime.fromtimestamp(0) + t = datetime.fromtimestamp(v) + value = str(t - t0) + #value = v else: # TODO: Time format value = f"{v}" diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py index 5f0b38e40544c3b88b55d59a6d4c394bc9289e31..8ba8074033ecaba6c09ddd9f4f2bf924a9fbb7aa 100644 --- a/src/View/BoundaryCondition/Edit/Window.py +++ b/src/View/BoundaryCondition/Edit/Window.py @@ -21,7 +21,7 @@ from PyQt5.QtWidgets import ( from View.Plot.MplCanvas import MplCanvas from View.BoundaryCondition.translate import long_types -from View.BoundaryCondition.Edit.Table import TableModel +from View.BoundaryCondition.Edit.Table import TableModel, ExTimeDelegate from View.BoundaryCondition.Edit.Plot import Plot _translate = QCoreApplication.translate @@ -68,6 +68,17 @@ class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow): data = self._data, undo = self._undo_stack ) + + self._delegate_time = ExTimeDelegate( + data = self._data, + mode = "type", + parent=self + ) + + table.setItemDelegateForColumn( + 0, self._delegate_time + ) + table.setModel(self._table) table.setSelectionBehavior(QAbstractItemView.SelectRows) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py index 019f464280066684eea4d98b4b417e1d6cb320e5..ead3ed7a76c43702af16cb48650a89dc10f30fe8 100644 --- a/src/View/BoundaryCondition/Table.py +++ b/src/View/BoundaryCondition/Table.py @@ -50,7 +50,6 @@ class ComboBoxDelegate(QItemDelegate): ) ) ) - print(lst) self.editor.addItems( lst ) diff --git a/src/View/ui/NewStudy.ui b/src/View/ui/NewStudy.ui index f95ff4a1ae561bff381fa641df2e4b126692e4e8..95100b5c6594521cba6e300ffc64775cefd5bfb7 100644 --- a/src/View/ui/NewStudy.ui +++ b/src/View/ui/NewStudy.ui @@ -78,6 +78,9 @@ <property name="enabled"> <bool>false</bool> </property> + <property name="displayFormat"> + <string>dd/MM/yyyy HH:mm:ss</string> + </property> </widget> </item> </layout> diff --git a/src/View/ui/Widgets/extendedTimeEdit.ui b/src/View/ui/Widgets/extendedTimeEdit.ui new file mode 100644 index 0000000000000000000000000000000000000000..493a96a11eece3431108500c8eff0555f019ea81 --- /dev/null +++ b/src/View/ui/Widgets/extendedTimeEdit.ui @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>178</width> + <height>44</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSpinBox" name="spinBox_days"> + <property name="frame"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>days</string> + </property> + </widget> + </item> + <item> + <widget class="QTimeEdit" name="timeEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frame"> + <bool>false</bool> + </property> + <property name="displayFormat"> + <string>HH:mm:ss</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>