From 9d3830850c0f685c2706a95973e6707d6b70e219 Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Thu, 4 May 2023 16:08:19 +0200
Subject: [PATCH] BC: New file Table.

---
 .../BoundaryConditionWindow.py                | 216 +----------------
 src/View/BoundaryCondition/Table.py           | 225 ++++++++++++++++++
 src/View/BoundaryCondition/translate.py       |  19 ++
 3 files changed, 249 insertions(+), 211 deletions(-)
 create mode 100644 src/View/BoundaryCondition/Table.py

diff --git a/src/View/BoundaryCondition/BoundaryConditionWindow.py b/src/View/BoundaryCondition/BoundaryConditionWindow.py
index 0688b700..d1597c13 100644
--- a/src/View/BoundaryCondition/BoundaryConditionWindow.py
+++ b/src/View/BoundaryCondition/BoundaryConditionWindow.py
@@ -33,221 +33,15 @@ from Model.BoundaryCondition.BoundaryConditionTypes import (
     TimeOverZ, TimeOverDebit, ZOverDebit
 )
 
-from View.BoundaryCondition.translate import long_types
+from View.BoundaryCondition.Table import (
+    TableModel, ComboBoxDelegate
+)
+
+from View.BoundaryCondition.translate import *
 from View.BoundaryCondition.Edit.Window import EditBoundaryConditionWindow
 
 _translate = QCoreApplication.translate
 
-table_headers = {
-    "name": _translate("BoundaryCondition", "Name"),
-    "type": _translate("BoundaryCondition", "Type"),
-    "node": _translate("BoundaryCondition", "Node")
-}
-
-BC_types = {
-    "ND": NotDefined,
-    "PC": PonctualContribution,
-    "TZ": TimeOverZ,
-    "TD": TimeOverDebit,
-    "ZD": ZOverDebit
-}
-
-
-class ComboBoxDelegate(QItemDelegate):
-    def __init__(self, data=None, mode="type", parent=None):
-        super(ComboBoxDelegate, self).__init__(parent)
-
-        self._data = data
-        self._mode = mode
-
-    def createEditor(self, parent, option, index):
-        self.editor = QComboBox(parent)
-
-        if self._mode == "type":
-            self.editor.addItems([long_types[k] for k in BC_types.keys()])
-        else:
-            self.editor.addItems(
-                [_translate("BoundaryCondition", "Not associate")] +
-                self._data.nodes_names()
-            )
-
-        self.editor.setCurrentText(index.data(Qt.DisplayRole))
-        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):
-        text = str(editor.currentText())
-        model.setData(index, text)
-        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__()
-        self._headers = list(table_headers.keys())
-        self._data = data
-        self._undo = undo
-        self._lst = self._data.boundary_condition
-
-    def flags(self, index):
-        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
-        options |= Qt.ItemIsEditable
-
-        return options
-
-    def rowCount(self, parent):
-        return len(self._lst)
-
-    def columnCount(self, parent):
-        return len(self._headers)
-
-    def data(self, index, role):
-        if role != Qt.ItemDataRole.DisplayRole:
-            return QVariant()
-
-        row = index.row()
-        column = index.column()
-
-        if self._headers[column] == "name":
-            return self._lst[row].name
-        elif self._headers[column] == "type":
-            t = self._lst[row].bctype
-            return long_types[t]
-        elif self._headers[column] == "node":
-            n = self._lst[row].node
-            if n is None:
-                return _translate("BoundaryCondition", "Not associate")
-            return n.name
-
-        return QVariant()
-
-    def headerData(self, section, orientation, role):
-        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
-            return table_headers[self._headers[section]]
-
-        return QVariant()
-
-    def setData(self, index, value, role=Qt.EditRole):
-        if not index.isValid() or role != Qt.EditRole:
-            return False
-
-        row = index.row()
-        column = index.column()
-
-        if self._headers[column] == "name":
-            self._undo.push(
-                SetNameCommand(
-                    self._lst, row, value
-                )
-            )
-        elif self._headers[column] == "type":
-            key = next(k for k, v in long_types.items() if v == value)
-            self._undo.push(
-                SetTypeCommand(
-                    self._lst, row, BC_types[key]
-                )
-            )
-        elif self._headers[column] == "node":
-            self._undo.push(
-                SetNodeCommand(
-                    self._lst, row, self._data.node(value)
-                )
-            )
-
-        self.dataChanged.emit(index, index)
-        return True
-
-    def add(self, row, parent=QModelIndex()):
-        self.beginInsertRows(parent, row, row - 1)
-
-        self._undo.push(
-            AddCommand(
-                self._lst, row
-            )
-        )
-
-        self.endInsertRows()
-        self.layoutChanged.emit()
-
-    def delete(self, rows, parent=QModelIndex()):
-        self.beginRemoveRows(parent, rows[0], rows[-1])
-
-        self._undo.push(
-            DelCommand(
-                self._lst, rows
-            )
-        )
-
-        self.endRemoveRows()
-
-    def sort(self, _reverse, parent=QModelIndex()):
-        self.layoutAboutToBeChanged.emit()
-
-        self._undo.push(
-            SortCommand(
-                self._lst, False
-            )
-        )
-
-        self.layoutAboutToBeChanged.emit()
-        self.layoutChanged.emit()
-
-    def move_up(self, row, parent=QModelIndex()):
-        if row <= 0:
-            return
-
-        target = row + 2
-
-        self.beginMoveRows(parent, row - 1, row - 1, parent, target)
-
-        self._undo_stack.push(
-            MoveCommand(
-                self._lst, "up", row
-            )
-        )
-
-        self.endMoveRows()
-        self.layoutChanged.emit()
-
-    def move_down(self, index, parent=QModelIndex()):
-        if row > len(self._lst):
-            return
-
-        target = row
-
-        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
-
-        self._undo_stack.push(
-            MoveCommand(
-                self._lst, "down", row
-            )
-        )
-
-        self.endMoveRows()
-        self.layoutChanged.emit()
-
-    def undo(self):
-        self._undo.undo()
-        self.layoutChanged.emit()
-
-    def redo(self):
-        self._undo.redo()
-        self.layoutChanged.emit()
-
 
 class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
     def __init__(self, title="BoundaryConditions", study=None, parent=None):
diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py
new file mode 100644
index 00000000..850d3b21
--- /dev/null
+++ b/src/View/BoundaryCondition/Table.py
@@ -0,0 +1,225 @@
+# -*- coding: utf-8 -*-
+
+from tools import trace, timer
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QComboBox,
+)
+
+from View.BoundaryCondition.BCUndoCommand import (
+    SetNameCommand, SetNodeCommand, SetTypeCommand,
+    AddCommand, DelCommand, SortCommand,
+    MoveCommand, PasteCommand, DuplicateCommand,
+)
+
+from Model.BoundaryCondition.BoundaryConditionTypes import (
+    NotDefined, PonctualContribution,
+    TimeOverZ, TimeOverDebit, ZOverDebit
+)
+from View.BoundaryCondition.translate import *
+
+_translate = QCoreApplication.translate
+
+class ComboBoxDelegate(QItemDelegate):
+    def __init__(self, data=None, mode="type", parent=None):
+        super(ComboBoxDelegate, self).__init__(parent)
+
+        self._data = data
+        self._mode = mode
+
+    def createEditor(self, parent, option, index):
+        self.editor = QComboBox(parent)
+
+        if self._mode == "type":
+            self.editor.addItems([long_types[k] for k in BC_types.keys()])
+        else:
+            self.editor.addItems(
+                [_translate("BoundaryCondition", "Not associate")] +
+                self._data.nodes_names()
+            )
+
+        self.editor.setCurrentText(index.data(Qt.DisplayRole))
+        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):
+        text = str(editor.currentText())
+        model.setData(index, text)
+        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__()
+        self._headers = list(table_headers.keys())
+        self._data = data
+        self._undo = undo
+        self._lst = self._data.boundary_condition
+
+    def flags(self, index):
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return len(self._lst)
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            return self._lst[row].name
+        elif self._headers[column] == "type":
+            t = self._lst[row].bctype
+            return long_types[t]
+        elif self._headers[column] == "node":
+            n = self._lst[row].node
+            if n is None:
+                return _translate("BoundaryCondition", "Not associate")
+            return n.name
+
+        return QVariant()
+
+    def headerData(self, section, orientation, role):
+        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
+            return table_headers[self._headers[section]]
+
+        return QVariant()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if not index.isValid() or role != Qt.EditRole:
+            return False
+
+        row = index.row()
+        column = index.column()
+
+        if self._headers[column] == "name":
+            self._undo.push(
+                SetNameCommand(
+                    self._lst, row, value
+                )
+            )
+        elif self._headers[column] == "type":
+            key = next(k for k, v in long_types.items() if v == value)
+            self._undo.push(
+                SetTypeCommand(
+                    self._lst, row, BC_types[key]
+                )
+            )
+        elif self._headers[column] == "node":
+            self._undo.push(
+                SetNodeCommand(
+                    self._lst, row, self._data.node(value)
+                )
+            )
+
+        self.dataChanged.emit(index, index)
+        return True
+
+    def add(self, row, parent=QModelIndex()):
+        self.beginInsertRows(parent, row, row - 1)
+
+        self._undo.push(
+            AddCommand(
+                self._lst, row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._lst, rows
+            )
+        )
+
+        self.endRemoveRows()
+
+    def sort(self, _reverse, parent=QModelIndex()):
+        self.layoutAboutToBeChanged.emit()
+
+        self._undo.push(
+            SortCommand(
+                self._lst, False
+            )
+        )
+
+        self.layoutAboutToBeChanged.emit()
+        self.layoutChanged.emit()
+
+    def move_up(self, row, parent=QModelIndex()):
+        if row <= 0:
+            return
+
+        target = row + 2
+
+        self.beginMoveRows(parent, row - 1, row - 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._lst, "up", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def move_down(self, index, parent=QModelIndex()):
+        if row > len(self._lst):
+            return
+
+        target = row
+
+        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._lst, "down", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def undo(self):
+        self._undo.undo()
+        self.layoutChanged.emit()
+
+    def redo(self):
+        self._undo.redo()
+        self.layoutChanged.emit()
diff --git a/src/View/BoundaryCondition/translate.py b/src/View/BoundaryCondition/translate.py
index bcd1be54..762ca867 100644
--- a/src/View/BoundaryCondition/translate.py
+++ b/src/View/BoundaryCondition/translate.py
@@ -2,6 +2,11 @@
 
 from PyQt5.QtCore import QCoreApplication
 
+from Model.BoundaryCondition.BoundaryConditionTypes import (
+    NotDefined, PonctualContribution,
+    TimeOverZ, TimeOverDebit, ZOverDebit
+)
+
 _translate = QCoreApplication.translate
 
 long_types = {
@@ -11,3 +16,17 @@ long_types = {
     "TD": _translate("BoundaryCondition", "Time over Debit"),
     "ZD": _translate("BoundaryCondition", "Z over Debit"),
 }
+
+table_headers = {
+    "name": _translate("BoundaryCondition", "Name"),
+    "type": _translate("BoundaryCondition", "Type"),
+    "node": _translate("BoundaryCondition", "Node")
+}
+
+BC_types = {
+    "ND": NotDefined,
+    "PC": PonctualContribution,
+    "TZ": TimeOverZ,
+    "TD": TimeOverDebit,
+    "ZD": ZOverDebit
+}
-- 
GitLab