diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py
index cca0ebe9b162229850ef5d7b2edaaecabe83b09a..6101591786b5d7bac23044dfc749b3e75866ece9 100644
--- a/src/Model/BoundaryCondition/BoundaryCondition.py
+++ b/src/Model/BoundaryCondition/BoundaryCondition.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-from tools import trace, timer
+from tools import trace, timer, old_pamhyr_date_to_timestamp
 
 from Model.Except import NotImplementedMethodeError
 
@@ -13,7 +13,21 @@ class BoundaryCondition(object):
         self._node = None
         self._data = []
         self._header = []
-        self._types = [int, float]
+        self._types = [float, float]
+
+    def __len__(self):
+        return len(self._data)
+
+    @classmethod
+    def compatibility(cls):
+        return ["liquid", "solid", "suspenssion"]
+
+    @classmethod
+    def time_convert(cls, data):
+        if type(data) == str and data.count(":") == 3:
+            return old_pamhyr_date_to_timestamp(data)
+
+        return int(data)
 
     @property
     def name(self):
@@ -46,23 +60,49 @@ class BoundaryCondition(object):
     def data(self):
         return self._data.copy()
 
+    def get_type_column(self, column):
+        if 0 <= column < 2:
+            return self._types[column]
+        return None
+
+    @property
     def _default_0(self):
         return self._types[0](0)
 
+    @property
     def _default_1(self):
         return self._types[1](0.0)
 
     def is_define(self):
         return self._data is not None
 
+    def new_from_data(self, header, data):
+        new_0 = self._default_0
+        new_1 = self._default_1
+
+        if len(header) != 0:
+            for i in [0,1]:
+                for j in range(len(header)):
+                    if self._header[i] == header[j]:
+                        if i == 0:
+                            new_0 = self._types[i](data[j].replace(",", "."))
+                        else:
+                            new_1 = self._types[i](data[j].replace(",", "."))
+        else:
+            new_0 = self._types[0](data[0])
+            new_1 = self._types[1](data[1])
+
+        return (new_0, new_1)
+
     def add(self, index:int):
-        value = (self.default_0, self_default_1)
+        value = (self._default_0, self._default_1)
         self._data.insert(index, value)
+        return value
 
     def insert(self, index:int, value):
         self._data.insert(index, value)
 
-    def delete(self, indexes):
+    def delete_i(self, indexes):
         self._data = list(
             map(
                 lambda e: e[1],
@@ -73,12 +113,30 @@ class BoundaryCondition(object):
             )
         )
 
-    def sort(self, _reverse):
-        self._data.sort(reverse=_reverse)
+    def delete(self, els):
+        self._data = list(
+            filter(
+                lambda e: e not in els,
+                self.data
+            )
+        )
+
+    def sort(self, _reverse=False, key=None):
+        if key is None:
+            self._data.sort(reverse=_reverse)
+        else:
+            self._data.sort(reverse=_reverse, key=key)
 
     def get_i(self, index):
         return self.data[index]
 
+    def get_range(self, _range):
+        l = []
+        for r in _range:
+            l.append(r)
+        return l
+
+
     def _set_i_c_v(self, index, column, value):
         v = list(self._data[index])
         v[column] = self._types[column](value)
@@ -103,3 +161,15 @@ class BoundaryCondition(object):
                         new._set_i_c_v(ind, j, v[i])
 
         return new
+
+    def move_up(self, index):
+        if index < len(self):
+            next = index - 1
+            d = self._data
+            d[index], d[next] = d[next], d[index]
+
+    def move_down(self, index):
+        if index >= 0:
+            prev = index + 1
+            d = self._data
+            d[index], d[prev] = d[prev], d[index]
diff --git a/src/Model/BoundaryCondition/BoundaryConditionList.py b/src/Model/BoundaryCondition/BoundaryConditionList.py
index a44629d44ff7a18ad686f4441379f77da66aa7e5..4b14d9242e98fb4ba23c951379ef90a6291a04c0 100644
--- a/src/Model/BoundaryCondition/BoundaryConditionList.py
+++ b/src/Model/BoundaryCondition/BoundaryConditionList.py
@@ -11,56 +11,82 @@ from Model.BoundaryCondition.BoundaryConditionTypes import (
     TimeOverZ, TimeOverDebit, ZOverDebit
 )
 
-class BoundaryConditionList(list):
+class BoundaryConditionList(object):
     def __init__(self):
         super(BoundaryConditionList, self).__init__()
 
-    def new(self, index):
+        self._tabs = {
+            "liquid" : [],
+            "solid" : [],
+            "suspenssion" : []
+        }
+
+    def len(self, lst):
+        return len(self._tabs[lst])
+
+    def get_tab(self, lst):
+        return self._tabs[lst].copy()
+
+    def get(self, lst, row):
+        return self._tabs[lst][row]
+
+    def set(self, lst, row, new):
+        self._tabs[lst][row] = new
+
+    def new(self, lst, index):
         n = NotDefined()
-        self.insert(index, n)
+        self._tabs[lst].insert(index, n)
         return n
 
-    def delete(self, bcs):
+    def insert(self, lst, index, new):
+        self._tabs[lst].insert(index, new)
+
+    def delete(self, lst, bcs):
         for bc in bcs:
-            self.remove(bc)
+            self._tabs[lst].remove(bc)
 
-    def delete_i(self, indexes):
+    def delete_i(self, lst, indexes):
         bcs = list(
             map(
                 lambda x: x[1],
                 filter(
                     lambda x: x[0] in indexes,
-                    enumerate(self)
+                    enumerate(self._tabs[lst])
                 )
             )
         )
-        self.delete(bcs)
+        self.delete(lst, bcs)
+
+    def sort(self, lst, reverse=False, key=None):
+        self._tabs[lst].sort(reverse=reverse, key=key)
 
-    def move_up(self, index):
-        if index < len(self):
+    def move_up(self, lst, index):
+        if index < len(self._tabs[lst]):
             next = index - 1
 
-            self[index], self[next] = self[next], self[index]
+            l = self._tabs[lst]
+            l[index], l[next] = l[next], l[index]
 
-    def move_down(self, index):
+    def move_down(self, lst, index):
         if index >= 0:
             prev = index + 1
 
-            self[index], self[prev] = self[prev], self[index]
+            l = self._tabs[lst]
+            l[index], l[prev] = l[prev], l[index]
 
     def __copy__(self):
         new = BoundaryConditionList()
 
-        for bc in self:
-            new.append(bc)
+        for l in self._tabs:
+            new.tabs[l] = self._tabs[l].copy()
 
         return new
 
     def __deepcopy__(self):
         new = BoundaryConditionList()
 
-        for bc in self:
-            new.append(deepcopy(bc))
+        for l in self._tabs:
+            new.tabs[l] = self._tabs[l].deepcopy()
 
         return new
 
diff --git a/src/Model/BoundaryCondition/BoundaryConditionTypes.py b/src/Model/BoundaryCondition/BoundaryConditionTypes.py
index 209e9ac77bb1dca83576b27901ace0294a2eb9d8..4bc1d53830f920dfe4452bbb99b72d8ff8d385cc 100644
--- a/src/Model/BoundaryCondition/BoundaryConditionTypes.py
+++ b/src/Model/BoundaryCondition/BoundaryConditionTypes.py
@@ -10,7 +10,11 @@ class NotDefined(BoundaryCondition):
         super(NotDefined, self).__init__(name=name)
 
         self._type = "ND"
-        self._header = ["", ""]
+        self._header = ["x", "y"]
+
+    @property
+    def _default_0(self):
+        return 0.0
 
 class PonctualContribution(BoundaryCondition):
     def __init__(self, name:str = ""):
@@ -18,6 +22,11 @@ class PonctualContribution(BoundaryCondition):
 
         self._type = "PC"
         self._header = ["time", "debit"]
+        self._types = [PonctualContribution.time_convert, float]
+
+    @classmethod
+    def compatibility(cls):
+        return ["liquid"]
 
 class TimeOverZ(BoundaryCondition):
     def __init__(self, name:str = ""):
@@ -25,6 +34,11 @@ class TimeOverZ(BoundaryCondition):
 
         self._type = "TZ"
         self._header = ["time", "z"]
+        self._types = [TimeOverZ.time_convert, float]
+
+    @classmethod
+    def compatibility(cls):
+        return ["liquid"]
 
 class TimeOverDebit(BoundaryCondition):
     def __init__(self, name:str = ""):
@@ -32,6 +46,11 @@ class TimeOverDebit(BoundaryCondition):
 
         self._type = "TD"
         self._header = ["time", "debit"]
+        self._types = [TimeOverDebit.time_convert, float]
+
+    @classmethod
+    def compatibility(cls):
+        return ["liquid"]
 
 class ZOverDebit(BoundaryCondition):
     def __init__(self, name:str = ""):
@@ -41,5 +60,10 @@ class ZOverDebit(BoundaryCondition):
         self._header = ["z", "debit"]
         self._types = [float, float]
 
+    @classmethod
+    def compatibility(cls):
+        return ["liquid"]
+
+    @property
     def _default_0(self):
         return 0.0
diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index 0fff437ce1cb305e7cddefb828bfcc8bb3a6cf73..16ee09f893ff81e818fabaea0e9f7df4570fbb9c 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -16,7 +16,7 @@ from Model.Geometry.ProfileXYZ import ProfileXYZ
 from Model.Except import FileFormatError, exception_message_box
 
 class Reach:
-    def __init__(self, parent):
+    def __init__(self, parent=None):
         self._parent = parent
         self._profiles: List[Profile] = []
 
@@ -39,6 +39,9 @@ class Reach:
 
     @property
     def name(self):
+        if self._parent == None:
+            return ""
+
         return self._parent.name
 
     @property
diff --git a/src/Model/Study.py b/src/Model/Study.py
index 59a2ec9c7deff56f9bfabcff844271c8552da2e6..f1a501310c19e08164d6172ce381aaf9f750e67d 100644
--- a/src/Model/Study.py
+++ b/src/Model/Study.py
@@ -13,6 +13,9 @@ class Study(Serializable):
         # Study general information
         self.name = ""
         self.description = ""
+        # Time system
+        self._time_system = "time"
+        self._date = datetime.fromtimestamp(0)
 
         self.creation_date = datetime.now()
         self.last_modification_date = datetime.now()
@@ -21,13 +24,35 @@ class Study(Serializable):
         # Study data
         self.river = None
 
+    @property
+    def time_system(self):
+        return self._time_system
+
+    def use_time(self):
+        self._time_system = "time"
+
+    def use_date(self, date:datetime):
+        self._time_system = "date"
+        self._date = date
+
+    @property
+    def date(self):
+        return self._date
+
+    @date.setter
+    def date(self, timestamp):
+        self._date = timestamp
+
     @classmethod
     def new(cls):
         return cls()
 
     @classmethod
-    def new(cls, name, description):
+    def new(cls, name, description, date = None):
         me = cls()
         me.name = name
         me.description = description
+        if date is not None:
+            me.use_date()
+            me.date = date
         return me
diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py
index 3e1a138f4ff633124331c45e949815c728a77932..61a77987ef0ff4a0419e21831daf79549afbda0c 100644
--- a/src/View/ASubWindow.py
+++ b/src/View/ASubWindow.py
@@ -4,6 +4,7 @@ import os
 import csv
 
 from io import StringIO
+from datetime import datetime
 
 from tools import trace
 
@@ -16,9 +17,10 @@ from PyQt5.QtWidgets import (
     QTimeEdit, QSpinBox, QTextEdit,
     QRadioButton, QComboBox, QFileDialog,
     QMessageBox, QTableView, QAction,
+    QDateTimeEdit, QWidget,
 )
 from PyQt5.QtCore import (
-    QTime,
+    QTime, QDateTime,
 )
 from PyQt5.uic import loadUi
 
@@ -350,6 +352,31 @@ class ASubWindowFeatures(object):
         """
         return self.find(QComboBox, name).currentText()
 
+    def get_datetime_edit(self, name:str):
+        """Get datetime of datetime edit
+
+        Args:
+            name: The datetime edit component name
+
+        Returns:
+            The datetime
+        """
+        return self.find(QDateTimeEdit, name).dateTime().toPyDateTime()
+
+    def set_datetime_edit(self, name:str, date:datetime):
+        """Set datetime of a datetime edit
+
+        Args:
+            name: The datetime edit component name
+            date: The new datetime
+
+        Returns:
+            Nothing
+        """
+        qdate = QDateTime.fromString(date.isoformat(), "yyyy-MM-ddThh:mm:ss")
+        self.find(QDateTimeEdit, name).setDateTime(qdate)
+
+
 # Top level interface
 
 class ASubMainWindow(QMainWindow, ASubWindowFeatures, WindowToolKit):
@@ -382,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)
@@ -412,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/BCUndoCommand.py b/src/View/BoundaryCondition/BCUndoCommand.py
index dfddf82cbd315c01875b9b41b3dea9efba8516c1..7b1c7f5e995c97dc91997b6c50f0723c0698084e 100644
--- a/src/View/BoundaryCondition/BCUndoCommand.py
+++ b/src/View/BoundaryCondition/BCUndoCommand.py
@@ -11,105 +11,114 @@ from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition
 from Model.BoundaryCondition.BoundaryConditionList import BoundaryConditionList
 
 class SetNameCommand(QUndoCommand):
-    def __init__(self, lst, index, new_value):
+    def __init__(self, bcs, tab, index, new_value):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._index = index
-        self._old = self._lst[self._index].name
+        self._old = self._bcs.get(self._tab, self._index).name
         self._new = new_value
 
     def undo(self):
-        self._lst[self._index].name = self._old
+        self._bcs.get(self._tab, self._index).name = self._old
 
     def redo(self):
-        self._lst[self._index].name = self._new
+        self._bcs.get(self._tab, self._index).name = self._new
 
 class SetNodeCommand(QUndoCommand):
-    def __init__(self, lst, index, node):
+    def __init__(self, bcs, tab, index, node):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._index = index
-        self._old = self._lst[index].node
+        self._old = self._bcs.get(self._tab, self._index).node
         self._new = node
 
     def undo(self):
-        self._lst[self._index].node = self._old
+        self._bcs.get(self._tab, self._index).node = self._old
 
     def redo(self):
-        self._lst[self._index].node = self._new
+        self._bcs.get(self._tab, self._index).node = self._new
 
 class SetTypeCommand(QUndoCommand):
-    def __init__(self, lst, index, _type):
+    def __init__(self, bcs, tab, index, _type):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._index = index
         self._type = _type
-        self._old = self._lst[index]
-        self._new = self._lst[index].convert(self._type)
+        self._old = self._bcs.get(self._tab, self._index)
+        self._new = self._bcs.get(self._tab, self._index)\
+                             .convert(self._type)
 
     def undo(self):
-        self._lst[self._index] = self._old
+        self._bcs.set(self._tab, self._index, self._old)
 
     def redo(self):
-        self._lst[self._index] = self._new
+        self._bcs.set(self._tab, self._index, self._new)
 
 class AddCommand(QUndoCommand):
-    def __init__(self, lst, index):
+    def __init__(self, bcs, tab, index):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._index = index
         self._new = None
 
     def undo(self):
-        self._lst.delete_i([self._index])
+        self._bcs.delete_i(self._tab, [self._index])
 
     def redo(self):
         if self._new is None:
-            self._new = self._lst.new(self._index)
+            self._new = self._bcs.new(self._tab, self._index)
         else:
-            self._lst.insert(self._index, self._new)
+            self._bcs.insert(self._tab, self._index, self._new)
 
 class DelCommand(QUndoCommand):
-    def __init__(self, lst, rows):
+    def __init__(self, bcs, tab, rows):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._rows = rows
 
         self._bc = []
         for row in rows:
-            self._bc.append((row, self._lst[row]))
+            self._bc.append((row, self._bcs.get(self._tab, row)))
         self._bc.sort()
 
     def undo(self):
         for row, el in self._bc:
-            self._lst.insert(row, el)
+            self._bcs.insert(self._tab, row, el)
 
     def redo(self):
-        self._lst.delete_i(self._rows)
+        self._bcs.delete_i(self._tab, self._rows)
 
 class SortCommand(QUndoCommand):
-    def __init__(self, lst, _reverse):
+    def __init__(self, bcs, tab, _reverse):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._reverse = _reverse
 
-        self._old = self._lst.copy()
+        self._old = self._bcs.get_tab(self._tab)
         self._indexes = None
 
     def undo(self):
-        ll = self._lst.copy()
-        self._lst.sort(
+        ll = self._bcs.get_tab(self._tab)
+        self._bcs.sort(
+            self._tab,
             key=lambda x: self._indexes[ll.index(x)]
         )
 
     def redo(self):
-        self._lst.sort(
+        self._bcs.sort(
+            self._tab,
             reverse=self._reverse,
             key=lambda x: x.name
         )
@@ -117,62 +126,65 @@ class SortCommand(QUndoCommand):
             self._indexes = list(
                 map(
                     lambda p: self._old.index(p),
-                    self._lst
+                    self._bcs.get_tab(self._tab)
                 )
             )
             self._old = None
 
 
 class MoveCommand(QUndoCommand):
-    def __init__(self, lst, up, i):
+    def __init__(self, bcs, tab, up, i):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._up = up == "up"
         self._i = i
 
     def undo(self):
         if self._up:
-            self._lst.move_up(self._i)
+            self._bcs.move_up(self._tab, self._i)
         else:
-            self._lst.move_down(self._i)
+            self._bcs.move_down(self._tab, self._i)
 
     def redo(self):
         if self._up:
-            self._lst.move_up(self._i)
+            self._bcs.move_up(self._tab, self._i)
         else:
-            self._lst.move_down(self._i)
+            self._bcs.move_down(self._tab, self._i)
 
 
 class PasteCommand(QUndoCommand):
-    def __init__(self, lst, row, bc):
+    def __init__(self, bcs, tab, row, bc):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._row = row
         self._bc = deepcopy(bc)
         self._bc.reverse()
 
     def undo(self):
-        self._lst.delete(self._bc)
+        self._bcs.delete(self._tab, self._bc)
 
     def redo(self):
         for bc in self._bc:
-            self._lst.insert(self._row, bc)
+            self._bcs.insert(self._tab, self._row, bc)
 
 
 class DuplicateCommand(QUndoCommand):
-    def __init__(self, lst, rows, bc):
+    def __init__(self, bcs, tab, rows, bc):
         QUndoCommand.__init__(self)
 
-        self._lst = lst
+        self._bcs = bcs
+        self._tab = tab
         self._rows = rows
         self._bc = deepcopy(bc)
         self._bc.reverse()
 
     def undo(self):
-        self._lst.delete(self._bc)
+        self._bcs.delete(self._tab, self._bc)
 
     def redo(self):
-        for profile in self._profiles:
-            self._lst.insert(self._rows[0], profile)
+        for bc in self._bcs:
+            self._bcs.insert(self._tab, self._rows[0], bc)
diff --git a/src/View/BoundaryCondition/BoundaryConditionWindow.py b/src/View/BoundaryCondition/BoundaryConditionWindow.py
index de56722de107521295e2079646edaa885638ce18..9a22cf812de9c352a18ccc38d00b52ffc0df2ca6 100644
--- a/src/View/BoundaryCondition/BoundaryConditionWindow.py
+++ b/src/View/BoundaryCondition/BoundaryConditionWindow.py
@@ -19,7 +19,7 @@ from PyQt5.QtWidgets import (
     QDialogButtonBox, QPushButton, QLineEdit,
     QFileDialog, QTableView, QAbstractItemView,
     QUndoStack, QShortcut, QAction, QItemDelegate,
-    QComboBox,
+    QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
 )
 
 from View.BoundaryCondition.BCUndoCommand import (
@@ -27,231 +27,21 @@ from View.BoundaryCondition.BCUndoCommand import (
     AddCommand, DelCommand, SortCommand,
     MoveCommand, PasteCommand, DuplicateCommand,
 )
+
 from Model.BoundaryCondition.BoundaryConditionTypes import (
     NotDefined, PonctualContribution,
     TimeOverZ, TimeOverDebit, ZOverDebit
 )
-from View.BoundaryCondition.EditBoundaryConditionWindow import EditBoundaryConditionWindow
-
-_translate = QCoreApplication.translate
-
-long_types = {
-    "ND": _translate("BoundaryCondition", "Not defined"),
-    "PC": _translate("BoundaryCondition", "Ponctual contribution"),
-    "TZ": _translate("BoundaryCondition", "Time over Z"),
-    "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
-}
-
-
-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
-            )
-        )
+from View.BoundaryCondition.Table import (
+    TableModel, ComboBoxDelegate
+)
 
-        self.endMoveRows()
-        self.layoutChanged.emit()
+from View.Network.GraphWidget import GraphWidget
+from View.BoundaryCondition.translate import *
+from View.BoundaryCondition.Edit.Window import EditBoundaryConditionWindow
 
-    def undo(self):
-        self._undo.undo()
-        self.layoutChanged.emit()
-
-    def redo(self):
-        self._undo.redo()
-        self.layoutChanged.emit()
+_translate = QCoreApplication.translate
 
 
 class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
@@ -261,10 +51,11 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
         )
 
         self._study = study
-        self._lst = self._study.river.boundary_condition
+        self._bcs = self._study.river.boundary_condition
 
         self.setup_sc()
         self.setup_table()
+        self.setup_graph()
         self.setup_connections()
 
         self.ui.setWindowTitle(title)
@@ -278,32 +69,50 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
         self.paste_sc = QShortcut(QKeySequence.Paste, self)
 
     def setup_table(self):
-        table = self.find(QTableView, "tableView")
-        self._table = TableModel(
-            data = self._study.river,
-            undo = self._undo_stack
-        )
-        table.setModel(self._table)
+        self._table = {}
+
+        for t in ["liquid", "solid", "suspenssion"]:
+            table = self.find(QTableView, f"tableView_{t}")
+            self._table[t] = TableModel(
+                data = self._study.river,
+                undo = self._undo_stack,
+                tab = t,
+            )
+            table.setModel(self._table[t])
 
-        self._delegate_type = ComboBoxDelegate(
-            data = self._study.river,
-            mode = "type"
-        )
-        self._delegate_node = ComboBoxDelegate(
-            data = self._study.river,
-            mode = "node"
-        )
+            self._delegate_type = ComboBoxDelegate(
+                data = self._study.river,
+                mode = "type",
+                tab = t,
+                parent=self
+            )
+            self._delegate_node = ComboBoxDelegate(
+                data = self._study.river,
+                mode = "node",
+                tab = t,
+                parent=self
+            )
 
-        table.setItemDelegateForColumn(
-            1, self._delegate_type
-        )
-        table.setItemDelegateForColumn(
-            2, self._delegate_node
-        )
+            table.setItemDelegateForColumn(
+                1, self._delegate_type
+            )
+            table.setItemDelegateForColumn(
+                2, self._delegate_node
+            )
 
-        table.setSelectionBehavior(QAbstractItemView.SelectRows)
-        table.setAlternatingRowColors(True)
+            table.setSelectionBehavior(QAbstractItemView.SelectRows)
+            table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+            table.setAlternatingRowColors(True)
 
+    def setup_graph(self):
+        self.graph_widget = GraphWidget(
+            self._study.river,
+            min_size=None, size=(200,200),
+            only_display=True,
+            parent=self
+        )
+        self.graph_layout = self.find(QVBoxLayout, "verticalLayout")
+        self.graph_layout.addWidget(self.graph_widget)
 
     def setup_connections(self):
         self.find(QAction, "action_add").triggered.connect(self.add)
@@ -316,16 +125,24 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
         self.copy_sc.activated.connect(self.copy)
         self.paste_sc.activated.connect(self.paste)
 
+    def current_tab(self):
+        return self.find(QTabWidget, "tabWidget")\
+                   .currentWidget()\
+                   .objectName()\
+                   .replace("tab_", "")
 
     def index_selected_row(self):
-        table = self.find(QTableView, "tableView")
+        tab = self.current_tab()
+        table = self.find(QTableView, f"tableView_{tab}")
         return table.selectionModel()\
                     .selectedRows()[0]\
                     .row()
 
     def index_selected_rows(self):
-        table = self.find(QTableView, "tableView")
+        tab = self.current_tab()
+        table = self.find(QTableView, f"tableView_{tab}")
         return list(
+            # Delete duplicate
             set(
                 map(
                     lambda i: i.row(),
@@ -335,30 +152,34 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
         )
 
     def add(self):
+        tab = self.current_tab()
         rows = self.index_selected_rows()
-        if len(self._lst) == 0 or len(rows) == 0:
-            self._table.add(0)
+        if self._bcs.len(tab) == 0 or len(rows) == 0:
+            self._table[tab].add(0)
         else:
-            self._table.add(rows[0])
+            self._table[tab].add(rows[0])
 
     def delete(self):
+        tab = self.current_tab()
         rows = self.index_selected_rows()
         if len(rows) == 0:
             return
 
-        self._table.delete(rows)
+        self._table[tab].delete(rows)
 
     def sort(self):
-        self._table.sort(False)
+        tab = self.current_tab()
+        self._table[tab].sort(False)
 
     def move_up(self):
+        tab = self.current_tab()
         row = self.index_selected_row()
-        self._table.move_up(row)
+        self._table[tab].move_up(row)
 
     def move_down(self):
+        tab = self.current_tab()
         row = self.index_selected_row()
-        self._table.move_down(row)
-
+        self._table[tab].move_down(row)
 
     def copy(self):
         print("TODO")
@@ -367,16 +188,20 @@ class BoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
         print("TODO")
 
     def undo(self):
-        self._table.undo()
+        tab = self.current_tab()
+        self._table[tab].undo()
 
     def redo(self):
-        self._table.redo()
+        tab = self.current_tab()
+        self._table[tab].redo()
 
     def edit(self):
+        tab = self.current_tab()
         rows = self.index_selected_rows()
         for row in rows:
             win = EditBoundaryConditionWindow(
-                data=self._lst[row],
+                data=self._bcs.get(tab, row),
+                study=self._study,
                 parent=self
             )
             win.show()
diff --git a/src/View/BoundaryCondition/Edit/Plot.py b/src/View/BoundaryCondition/Edit/Plot.py
new file mode 100644
index 0000000000000000000000000000000000000000..66878b7c8840c48fb782fda34a2b9f47ff2d5df3
--- /dev/null
+++ b/src/View/BoundaryCondition/Edit/Plot.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+
+from datetime import datetime
+
+from tools import timer, trace
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+from View.BoundaryCondition.Edit.translate import *
+
+_translate = QCoreApplication.translate
+
+class Plot(APlot):
+    def __init__(self, canvas=None, data=None,
+                 mode = "time", toolbar=None):
+        super(Plot, self).__init__(
+            canvas=canvas,
+            data=data,
+            toolbar=toolbar
+        )
+
+        self._mode = mode
+
+    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))
+        if self._mode == "time":
+            xt = list(
+                map(
+                    lambda v: str(
+                        datetime.fromtimestamp(v[0]) - t0
+                    ).split(",")[0]\
+                    .replace("days", _translate("BoundaryCondition", "days"))\
+                    .replace("day", _translate("BoundaryCondition", "day")),
+                    fx
+                )
+            )
+        else:
+            xt = list(
+                map(
+                    lambda v: str(datetime.fromtimestamp(v[0]).date()),
+                    fx
+                )
+            )
+
+        self.canvas.axes.set_xticks(ticks=xx, labels=xt, rotation=45)
+
+
+    @timer
+    def draw(self):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if len(self.data) == 0:
+            self._init = False
+            return
+
+        # Plot data
+        x = list(map(lambda v: v[0], self.data.data))
+        y = list(map(lambda v: v[1], self.data.data))
+        self._line, = self.canvas.axes.plot(
+            x, y,
+            color='r', lw=1.,
+            markersize=5, marker='+',
+            picker=30,
+        )
+
+        self.custom_ticks()
+
+        # Plot label
+        header = self.data.header
+        self.canvas.axes.set_xlabel(
+            table_headers[header[0]], color='black', fontsize=10
+        )
+        self.canvas.axes.set_ylabel(
+            table_headers[header[1]], color='black', fontsize=10
+        )
+
+        self.canvas.axes.autoscale_view(True, True, True)
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        #self.toolbar.update()
+
+        self._init = True
+
+    @timer
+    def update(self, ind=None):
+        if self._init == False:
+            self.draw()
+            return
+
+        x = list(map(lambda v: v[0], self.data.data))
+        y = list(map(lambda v: v[1], self.data.data))
+
+        self._line.set_data(x, y)
+
+        self.custom_ticks()
+
+        self.canvas.axes.relim()
+        self.canvas.axes.autoscale()
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..d41a3551b286428d90b59bfaf6315a4b078a8063
--- /dev/null
+++ b/src/View/BoundaryCondition/Edit/Table.py
@@ -0,0 +1,278 @@
+# -*- coding: utf-8 -*-
+
+from datetime import date, time, datetime, timedelta
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow, AWidget
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel,
+    QCoreApplication, QModelIndex, pyqtSlot,
+    QRect, QTime,
+)
+
+from PyQt5.QtWidgets import (
+    QTableView, QAbstractItemView, QSpinBox,
+    QTimeEdit, QItemDelegate,
+)
+
+from Model.BoundaryCondition.BoundaryConditionTypes import (
+    NotDefined, PonctualContribution,
+    TimeOverZ, TimeOverDebit, ZOverDebit
+)
+
+from View.BoundaryCondition.Edit.UndoCommand import (
+    SetDataCommand, AddCommand, DelCommand,
+    SortCommand, MoveCommand, PasteCommand,
+    DuplicateCommand,
+)
+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, time format is 'DD days, HH:MM:SS',
+        # otherelse is 'HH:MM:SS'
+        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, mode="time", undo=None):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = data.header
+        self._data = data
+        self._mode = mode
+        self._undo = undo
+
+    def flags(self, index):
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return len(self._data)
+
+    def columnCount(self, parent):
+        return len(self._headers)
+
+    def data(self, index, role):
+        if role == Qt.TextAlignmentRole:
+            return Qt.AlignHCenter | Qt.AlignVCenter
+
+        if role != Qt.ItemDataRole.DisplayRole:
+            return QVariant()
+
+        row = index.row()
+        column = index.column()
+
+        value = QVariant()
+
+        if 0 <= column < 2:
+            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":
+                if self._mode == "time":
+                    t0 = datetime.fromtimestamp(0)
+                    t = datetime.fromtimestamp(v)
+                    value = str(t - t0)
+                else:
+                    value = str(datetime.fromtimestamp(v))
+            else:
+                value = f"{v}"
+
+        return value
+
+    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()
+
+        self._undo.push(
+            SetDataCommand(
+                self._data, row, column, 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._data, row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._data, rows
+            )
+        )
+
+        self.endRemoveRows()
+
+    def sort(self, _reverse, parent=QModelIndex()):
+        self.layoutAboutToBeChanged.emit()
+
+        self._undo.push(
+            SortCommand(
+                self._data, _reverse
+            )
+        )
+
+        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._data, "up", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def move_down(self, index, parent=QModelIndex()):
+        if row > len(self._data):
+            return
+
+        target = row
+
+        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._data, "down", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def paste(self, row, header, data):
+        if len(data) == 0:
+            return
+
+        self.layoutAboutToBeChanged.emit()
+
+        self._undo.push(
+            PasteCommand(
+                self._data, row,
+                list(
+                    map(
+                        lambda d: self._data.new_from_data(header, d),
+                        data
+                    )
+                )
+            )
+        )
+
+        self.layoutAboutToBeChanged.emit()
+        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/Edit/UndoCommand.py b/src/View/BoundaryCondition/Edit/UndoCommand.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2eb09acfd3648a34e752cc243dc3a5466090820
--- /dev/null
+++ b/src/View/BoundaryCondition/Edit/UndoCommand.py
@@ -0,0 +1,147 @@
+# -*- coding: utf-8 -*-
+
+from copy import deepcopy
+from tools import trace, timer
+
+from PyQt5.QtWidgets import (
+    QMessageBox, QUndoCommand, QUndoStack,
+)
+
+from Model.BoundaryCondition.BoundaryCondition import BoundaryCondition
+
+class SetDataCommand(QUndoCommand):
+    def __init__(self, data, index, column, new_value):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._index = index
+        self._column = column
+        self._old = self._data.get_i(self._index)[self._column]
+        self._new = new_value
+
+    def undo(self):
+        self._data._set_i_c_v(self._index, self._column, self._old)
+
+    def redo(self):
+        self._data._set_i_c_v(self._index, self._column, self._new)
+
+class AddCommand(QUndoCommand):
+    def __init__(self, data, index):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._index = index
+        self._new = None
+
+    def undo(self):
+        self._data.delete_i([self._index])
+
+    def redo(self):
+        if self._new is None:
+            self._new = self._data.add(self._index)
+        else:
+            self._data.insert(self._index, self._new)
+
+class DelCommand(QUndoCommand):
+    def __init__(self, data, rows):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._rows = rows
+
+        self._bc = []
+        for row in rows:
+            self._bc.append((row, self._data.get_i(row)))
+        self._bc.sort()
+
+    def undo(self):
+        for row, el in self._bc:
+            self._data.insert(row, el)
+
+    def redo(self):
+        self._data.delete_i(self._rows)
+
+class SortCommand(QUndoCommand):
+    def __init__(self, data, _reverse):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._reverse = _reverse
+
+        self._old = self._data.data
+        self._indexes = None
+
+    def undo(self):
+        ll = self._data.data
+        self._data.sort(
+            key=lambda x: self._indexes[ll.index(x)]
+        )
+
+    def redo(self):
+        self._data.sort(
+            _reverse=self._reverse,
+            key=lambda x: x[0]
+        )
+        if self._indexes is None:
+            self._indexes = list(
+                map(
+                    lambda p: self._old.index(p),
+                    self._data.data
+                )
+            )
+            self._old = None
+
+
+class MoveCommand(QUndoCommand):
+    def __init__(self, data, up, i):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._up = up == "up"
+        self._i = i
+
+    def undo(self):
+        if self._up:
+            self._data.move_up(self._i)
+        else:
+            self._data.move_down(self._i)
+
+    def redo(self):
+        if self._up:
+            self._data.move_up(self._i)
+        else:
+            self._data.move_down(self._i)
+
+
+class PasteCommand(QUndoCommand):
+    def __init__(self, data, row, bcs):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._row = row
+        self._bcs = bcs
+        self._bcs.reverse()
+
+    def undo(self):
+        self._data.delete(self._bcs)
+
+    def redo(self):
+        for bc in self._bcs:
+            self._data.insert(self._row, bc)
+
+
+class DuplicateCommand(QUndoCommand):
+    def __init__(self, data, rows, bc):
+        QUndoCommand.__init__(self)
+
+        self._data = data
+        self._rows = rows
+        self._bc = deepcopy(bc)
+        self._bc.reverse()
+
+    def undo(self):
+        self._data.delete(self._bc)
+
+    def redo(self):
+        for bc in self._bcs:
+            self._data.insert(self._rows[0], bc)
diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cd8fbad90e08d07013c05b2a12861ed3d40e4d4
--- /dev/null
+++ b/src/View/BoundaryCondition/Edit/Window.py
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+    QKeySequence,
+)
+
+from PyQt5.QtCore import (
+    Qt, QVariant, QAbstractTableModel, QCoreApplication,
+)
+
+from PyQt5.QtWidgets import (
+    QDialogButtonBox, QPushButton, QLineEdit,
+    QFileDialog, QTableView, QAbstractItemView,
+    QUndoStack, QShortcut, QAction, QItemDelegate,
+    QHeaderView,
+)
+
+from View.Plot.MplCanvas import MplCanvas
+
+from View.BoundaryCondition.translate import long_types
+from View.BoundaryCondition.Edit.Table import TableModel, ExTimeDelegate
+from View.BoundaryCondition.Edit.Plot import Plot
+
+_translate = QCoreApplication.translate
+
+class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
+    def __init__(self, title="Edit BoundaryConditions",
+                 data=None, study=None, parent=None):
+        super(EditBoundaryConditionWindow, self).__init__(
+            name=title, ui="EditBoundaryConditions", parent=parent
+        )
+
+        self._data = data
+        self._study = study
+        self._title = title
+
+        self.setup_window()
+        self.setup_sc()
+        self.setup_table()
+        self.setup_plot()
+        self.setup_connections()
+
+    def setup_window(self):
+        if self._data is not None:
+            node_name = (self._data.node.name if self._data.node is not None
+                         else _translate("BoundaryCondition", "Not associate"))
+            title = (
+                _translate("BoundaryCondition", self._title) +
+                f" - {self._data.name} " +
+                f"({long_types[self._data.bctype]} - {node_name})"
+            )
+            self.ui.setWindowTitle(title)
+        else:
+            self.ui.setWindowTitle(_translate("BoundaryCondition", self._title))
+
+    def setup_sc(self):
+        self._undo_stack = QUndoStack()
+
+        self.undo_sc = QShortcut(QKeySequence.Undo, self)
+        self.redo_sc = QShortcut(QKeySequence.Redo, self)
+        self.copy_sc = QShortcut(QKeySequence.Copy, self)
+        self.paste_sc = QShortcut(QKeySequence.Paste, self)
+
+    def setup_table(self):
+        table = self.find(QTableView, "tableView")
+        self._table = TableModel(
+            data = self._data,
+            undo = self._undo_stack,
+            mode = self._study.time_system
+        )
+
+        if self._data.header[0] == "time":
+            self._delegate_time = ExTimeDelegate(
+                data = self._data,
+                mode = self._study.time_system,
+                parent = self
+            )
+
+            table.setItemDelegateForColumn(
+                0, self._delegate_time
+            )
+
+        table.setModel(self._table)
+        table.setSelectionBehavior(QAbstractItemView.SelectRows)
+        table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+        table.setAlternatingRowColors(True)
+
+    def setup_plot(self):
+        self.canvas = MplCanvas(width=5, height=4, dpi=100)
+        self.canvas.setObjectName("canvas")
+        self.verticalLayout.addWidget(self.canvas)
+
+        self.plot = Plot(
+            canvas = self.canvas,
+            data = self._data,
+            mode = self._study.time_system,
+        )
+        self.plot.draw()
+
+
+    def setup_connections(self):
+        self.find(QAction, "action_add").triggered.connect(self.add)
+        self.find(QAction, "action_del").triggered.connect(self.delete)
+        self.find(QAction, "action_sort").triggered.connect(self.sort)
+
+        self.undo_sc.activated.connect(self.undo)
+        self.redo_sc.activated.connect(self.redo)
+        self.copy_sc.activated.connect(self.copy)
+        self.paste_sc.activated.connect(self.paste)
+
+        self._table.dataChanged.connect(self.update)
+
+    def update(self):
+        self.plot.update()
+
+    def index_selected_row(self):
+        table = self.find(QTableView, "tableView")
+        return table.selectionModel()\
+                    .selectedRows()[0]\
+                    .row()
+
+    def index_selected_rows(self):
+        table = self.find(QTableView, "tableView")
+        return list(
+            # Delete duplicate
+            set(
+                map(
+                    lambda i: i.row(),
+                    table.selectedIndexes()
+                )
+            )
+        )
+
+
+    def add(self):
+        rows = self.index_selected_rows()
+        if len(self._data) == 0 or len(rows) == 0:
+            self._table.add(0)
+        else:
+            self._table.add(rows[0])
+
+        self.plot.update()
+
+    def delete(self):
+        rows = self.index_selected_rows()
+        if len(rows) == 0:
+            return
+
+        self._table.delete(rows)
+        self.plot.update()
+
+    def sort(self):
+        self._table.sort(False)
+        self.plot.update()
+
+    def move_up(self):
+        row = self.index_selected_row()
+        self._table.move_up(row)
+        self.plot.update()
+
+    def move_down(self):
+        row = self.index_selected_row()
+        self._table.move_down(row)
+        self.plot.update()
+
+
+    def copy(self):
+        rows = self.index_selected_rows()
+
+        table = []
+        table.append(self._data.header)
+
+        data = self._data.data
+        for row in rows:
+            table.append(list(data[row]))
+
+        self.copyTableIntoClipboard(table)
+
+    def paste(self):
+        header, data = self.parseClipboardTable()
+
+        if len(data) == 0:
+            return
+
+        row = 0
+        rows = self.index_selected_rows()
+        if len(rows) != 0:
+            row = rows[0]
+
+        self._table.paste(row, header, data)
+        self.plot.update()
+
+    def undo(self):
+        self._table.undo()
+        self.plot.update()
+
+    def redo(self):
+        self._table.redo()
+        self.plot.update()
diff --git a/src/View/BoundaryCondition/Edit/translate.py b/src/View/BoundaryCondition/Edit/translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..9ab28f9c5f68c323b6ebb9c4405cdef40adc8911
--- /dev/null
+++ b/src/View/BoundaryCondition/Edit/translate.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+_translate = QCoreApplication.translate
+
+table_headers = {
+    "x": _translate("BoundaryCondition", "X"),
+    "y": _translate("BoundaryCondition", "Y"),
+    "time": _translate("BoundaryCondition", "Time"),
+    "debit": _translate("BoundaryCondition", "Debit"),
+    "z": _translate("BoundaryCondition", "Z (m)")
+}
diff --git a/src/View/BoundaryCondition/EditBoundaryConditionWindow.py b/src/View/BoundaryCondition/EditBoundaryConditionWindow.py
deleted file mode 100644
index 3695d260b90fffbf5939734f7c25815ef5e97fd9..0000000000000000000000000000000000000000
--- a/src/View/BoundaryCondition/EditBoundaryConditionWindow.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from View.ASubWindow import ASubMainWindow
-from View.ListedSubWindow import ListedSubWindow
-
-from PyQt5.QtCore import (
-    Qt, QVariant, QAbstractTableModel, QCoreApplication,
-)
-
-from PyQt5.QtWidgets import (
-    QDialogButtonBox, QPushButton, QLineEdit,
-    QFileDialog, QTableView, QAbstractItemView,
-)
-
-_translate = QCoreApplication.translate
-
-class EditBoundaryConditionWindow(ASubMainWindow, ListedSubWindow):
-    def __init__(self, title="Edit BoundaryConditions", data=None, parent=None):
-        super(EditBoundaryConditionWindow, self).__init__(
-            name=title, ui="EditBoundaryConditions", parent=parent
-        )
-
-        self._data = data
-        self._title = title
-
-        self.setup_window()
-
-    def setup_window(self):
-        if self._data is not None:
-            node_name = (self._data.node.name if self._data.node is not None
-                         else _translate("BoundaryCondition", "Not associate"))
-            title = (
-                _translate("BoundaryCondition", self._title) +
-                f"{self._data.name} " +
-                f"({self._data.name} - {node_name})"
-            )
-            self.ui.setWindowTitle(title)
-        else:
-            self.ui.setWindowTitle(_translate("BoundaryCondition", self._title))
diff --git a/src/View/BoundaryCondition/Table.py b/src/View/BoundaryCondition/Table.py
new file mode 100644
index 0000000000000000000000000000000000000000..ead3ed7a76c43702af16cb48650a89dc10f30fe8
--- /dev/null
+++ b/src/View/BoundaryCondition/Table.py
@@ -0,0 +1,239 @@
+# -*- 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", tab="", parent=None):
+        super(ComboBoxDelegate, self).__init__(parent)
+
+        self._data = data
+        self._mode = mode
+        self._tab = tab
+
+    def createEditor(self, parent, option, index):
+        self.editor = QComboBox(parent)
+
+        if self._mode == "type":
+            lst = list(
+                map(
+                    lambda k: long_types[k],
+                    filter(
+                        lambda k: self._tab in BC_types[k].compatibility(),
+                        BC_types.keys()
+                    )
+                )
+            )
+            self.editor.addItems(
+                lst
+            )
+        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, tab=""):
+        super(QAbstractTableModel, self).__init__()
+        self._headers = list(table_headers.keys())
+        self._data = data
+        self._undo = undo
+        self._tab = tab
+        self._bcs = self._data.boundary_condition
+
+    def flags(self, index):
+        options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        options |= Qt.ItemIsEditable
+
+        return options
+
+    def rowCount(self, parent):
+        return self._bcs.len(self._tab)
+
+    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._bcs.get(self._tab, row).name
+        elif self._headers[column] == "type":
+            t = self._bcs.get(self._tab, row).bctype
+            return long_types[t]
+        elif self._headers[column] == "node":
+            n = self._bcs.get(self._tab, 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._bcs, self._tab,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._bcs, self._tab,row, BC_types[key]
+                )
+            )
+        elif self._headers[column] == "node":
+            self._undo.push(
+                SetNodeCommand(
+                    self._bcs, self._tab,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._bcs, self._tab,row
+            )
+        )
+
+        self.endInsertRows()
+        self.layoutChanged.emit()
+
+    def delete(self, rows, parent=QModelIndex()):
+        self.beginRemoveRows(parent, rows[0], rows[-1])
+
+        self._undo.push(
+            DelCommand(
+                self._bcs, self._tab,rows
+            )
+        )
+
+        self.endRemoveRows()
+        self.layoutChanged.emit()
+
+    def sort(self, _reverse, parent=QModelIndex()):
+        self.layoutAboutToBeChanged.emit()
+
+        self._undo.push(
+            SortCommand(
+                self._bcs, self._tab,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._bcs, self._tab,"up", row
+            )
+        )
+
+        self.endMoveRows()
+        self.layoutChanged.emit()
+
+    def move_down(self, index, parent=QModelIndex()):
+        if row > len(self._bcs):
+            return
+
+        target = row
+
+        self.beginMoveRows(parent, row + 1, row + 1, parent, target)
+
+        self._undo_stack.push(
+            MoveCommand(
+                self._bcs, self._tab,"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
new file mode 100644
index 0000000000000000000000000000000000000000..762ca867bde99eaa0b53d2d16fb244366842758e
--- /dev/null
+++ b/src/View/BoundaryCondition/translate.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+from Model.BoundaryCondition.BoundaryConditionTypes import (
+    NotDefined, PonctualContribution,
+    TimeOverZ, TimeOverDebit, ZOverDebit
+)
+
+_translate = QCoreApplication.translate
+
+long_types = {
+    "ND": _translate("BoundaryCondition", "Not defined"),
+    "PC": _translate("BoundaryCondition", "Ponctual contribution"),
+    "TZ": _translate("BoundaryCondition", "Time over Z"),
+    "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
+}
diff --git a/src/View/Main/NewStudyWindow.py b/src/View/Main/NewStudyWindow.py
index 905815ea78555f794d86d2404d80d2bf9e33eacf..6d313199e55034d67ef9cb46362649d401eaf443 100644
--- a/src/View/Main/NewStudyWindow.py
+++ b/src/View/Main/NewStudyWindow.py
@@ -3,6 +3,11 @@
 from Model.Study import Study
 from View.ASubWindow import ASubWindow
 
+from PyQt5.QtWidgets import (
+    QRadioButton, QLabel, QDateTimeEdit,
+)
+
+
 class NewStudyWindow(ASubWindow):
     def __init__(self, study=None, title="New Study", parent=None):
         super(NewStudyWindow, self).__init__(name=title, ui="NewStudy", parent=parent)
@@ -13,16 +18,50 @@ class NewStudyWindow(ASubWindow):
         self.study = study
 
         if not self.study is None:
-            self.set_line_edit_text("lineEdit_name", study.name)
-            self.set_text_edit_text("textEdit_description", study.description)
+            self.set_line_edit_text("lineEdit_name", self.study.name)
+            self.set_text_edit_text("textEdit_description", self.study.description)
+            self.set_datetime_edit("dateTimeEdit_date", self.study.date)
+            if self.study.time_system == "date":
+                self.set_radio_button("radioButton_date", True)
+                self.find(QLabel, "label_date").setEnabled(True)
+                self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True)
+
+        self.connection()
+
+    def connection(self):
+        time = self.find(QRadioButton, "radioButton_time")
+        date = self.find(QRadioButton, "radioButton_date")
+
+        time.toggled.connect(self.set_time)
+        date.toggled.connect(self.set_date)
+
+    def set_time(self):
+        if self.get_radio_button("radioButton_time"):
+            self.find(QLabel, "label_date").setEnabled(False)
+            self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(False)
+
+    def set_date(self):
+        if self.get_radio_button("radioButton_date"):
+            self.find(QLabel, "label_date").setEnabled(True)
+            self.find(QDateTimeEdit, "dateTimeEdit_date").setEnabled(True)
+
 
     def accept(self):
         name = self.get_line_edit_text("lineEdit_name")
         description = self.get_text_edit_text("textEdit_description")
 
         if self.study is None:
-            self.parent.set_model(Study.new(name, description))
+            study = Study.new(name, description)
+            if self.get_radio_button("radioButton_date"):
+                date = self.get_datetime_edit("dateTimeEdit_date")
+                study.use_date(date)
+            self.parent.set_model(study)
         else:
             self.study.name = name
             self.study.description = description
+            if self.get_radio_button("radioButton_date"):
+                date = self.get_datetime_edit("dateTimeEdit_date")
+                self.study.use_date(date)
+            else:
+                self.study.use_time()
         self.done(True)
diff --git a/src/View/Network/GraphWidget.py b/src/View/Network/GraphWidget.py
index e6281c0f06ca566633fe581efc80bd4a7ef81151..522f3210648f44e0ee384f1e1e62ff99a4bd9419 100644
--- a/src/View/Network/GraphWidget.py
+++ b/src/View/Network/GraphWidget.py
@@ -79,12 +79,18 @@ class NodeItem(QGraphicsItem):
 
     def mousePressEvent(self, event):
         self.update()
-        super(NodeItem, self).mousePressEvent(event)
+        if not self.graph._only_display:
+            super(NodeItem, self).mousePressEvent(event)
 
     def mouseReleaseEvent(self, event):
         self.update()
         super(NodeItem, self).mouseReleaseEvent(event)
 
+    def mouseMoveEvent(self, event):
+        self.update()
+        if not self.graph._only_display:
+            super(NodeItem, self).mouseMoveEvent(event)
+
 class EdgeItem(QGraphicsItem):
     Type = QGraphicsItem.UserType + 2
 
@@ -252,12 +258,15 @@ class GraphWidget(QGraphicsView):
     changeEdge = pyqtSignal(object)
     changeNode = pyqtSignal(object)
 
-    def __init__(self, graph, parent=None):
+    def __init__(self, graph, parent=None,
+                 min_size=(400, 400), max_size=None,
+                 size=None, only_display=False):
         super(GraphWidget, self).__init__(parent=parent)
 
         self.timerId = 0
         self.parent = parent
         self._state = "move"
+        self._only_display = only_display
 
         self.graph = graph
 
@@ -286,7 +295,13 @@ class GraphWidget(QGraphicsView):
 
         self.scale(1, 1)
         self.previousScale = 1
-        self.setMinimumSize(400, 400)
+
+        if min_size:
+            self.setMinimumSize(*min_size)
+        if max_size:
+            self.setMaximumSize(*max_size)
+        if size:
+            self.resize(*size)
 
         self.create_items()
 
diff --git a/src/View/ui/BoundaryConditions.ui b/src/View/ui/BoundaryConditions.ui
index 8a0f8f962687b9a6df0057fbc166206932967c99..3097fd6363951c9822296f9a089f2e188e04d762 100644
--- a/src/View/ui/BoundaryConditions.ui
+++ b/src/View/ui/BoundaryConditions.ui
@@ -26,16 +26,44 @@
    <layout class="QGridLayout" name="gridLayout">
     <item row="0" column="0">
      <widget class="QSplitter" name="splitter">
-      <property name="sizePolicy">
-       <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
-        <horstretch>0</horstretch>
-        <verstretch>0</verstretch>
-       </sizepolicy>
-      </property>
       <property name="orientation">
        <enum>Qt::Horizontal</enum>
       </property>
-      <widget class="QTableView" name="tableView"/>
+      <widget class="QTabWidget" name="tabWidget">
+       <property name="currentIndex">
+        <number>0</number>
+       </property>
+       <widget class="QWidget" name="tab_liquid">
+        <attribute name="title">
+         <string>Liquid</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="0">
+          <widget class="QTableView" name="tableView_liquid"/>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="tab_solid">
+        <attribute name="title">
+         <string>Solid</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_3">
+         <item row="0" column="0">
+          <widget class="QTableView" name="tableView_solid"/>
+         </item>
+        </layout>
+       </widget>
+       <widget class="QWidget" name="tab_suspenssion">
+        <attribute name="title">
+         <string>Suspenssion</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout_4">
+         <item row="0" column="0">
+          <widget class="QTableView" name="tableView_suspenssion"/>
+         </item>
+        </layout>
+       </widget>
+      </widget>
       <widget class="QWidget" name="verticalLayoutWidget">
        <layout class="QVBoxLayout" name="verticalLayout"/>
       </widget>
diff --git a/src/View/ui/NewStudy.ui b/src/View/ui/NewStudy.ui
index 1805c10eda84fab293b4e6245ac96cc6ff8c6540..95100b5c6594521cba6e300ffc64775cefd5bfb7 100644
--- a/src/View/ui/NewStudy.ui
+++ b/src/View/ui/NewStudy.ui
@@ -13,60 +13,107 @@
   <property name="windowTitle">
    <string>Dialog</string>
   </property>
-  <layout class="QGridLayout" name="gridLayout_2">
+  <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
-    <layout class="QVBoxLayout" name="verticalLayout_3">
-     <item>
-      <layout class="QVBoxLayout" name="verticalLayout_2">
-       <item>
-        <layout class="QGridLayout" name="gridLayout">
-         <item row="0" column="0">
-          <widget class="QLabel" name="label">
-           <property name="text">
-            <string>Name</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="0">
-          <widget class="QLabel" name="label_2">
-           <property name="text">
-            <string>Description</string>
-           </property>
-          </widget>
-         </item>
-         <item row="0" column="1">
-          <widget class="QLineEdit" name="lineEdit_name">
-           <property name="text">
-            <string>MyNewStudy</string>
-           </property>
-          </widget>
-         </item>
-         <item row="1" column="1">
-          <widget class="QTextEdit" name="textEdit_description">
-           <property name="autoFillBackground">
-            <bool>false</bool>
-           </property>
-           <property name="tabChangesFocus">
-            <bool>false</bool>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </item>
-      </layout>
-     </item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Name</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1" colspan="2">
+    <widget class="QLineEdit" name="lineEdit_name">
+     <property name="text">
+      <string>MyNewStudy</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0" colspan="2">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Time system</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <layout class="QVBoxLayout" name="verticalLayout">
      <item>
-      <widget class="QDialogButtonBox" name="buttonBox">
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
+      <widget class="QRadioButton" name="radioButton_time">
+       <property name="text">
+        <string>Time</string>
        </property>
-       <property name="standardButtons">
-        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+       <property name="checked">
+        <bool>true</bool>
        </property>
       </widget>
      </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <widget class="QRadioButton" name="radioButton_date">
+         <property name="text">
+          <string>Date</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QLabel" name="label_date">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="text">
+          <string>Staring date</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QDateTimeEdit" name="dateTimeEdit_date">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
+         <property name="displayFormat">
+          <string>dd/MM/yyyy HH:mm:ss</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
     </layout>
    </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Description</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="2">
+    <widget class="QTextEdit" name="textEdit_description">
+     <property name="autoFillBackground">
+      <bool>false</bool>
+     </property>
+     <property name="tabChangesFocus">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="3">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
  <resources/>
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>
diff --git a/src/tools.py b/src/tools.py
index d2f119174dbb528d7056e30e47b90478927481bf..be41a5b35c5b4d2db1b3b0ccb17882555cb0a8b2 100644
--- a/src/tools.py
+++ b/src/tools.py
@@ -131,3 +131,25 @@ def flatten(lst):
         return []
 
     return reduce(list.__add__, lst)
+
+def old_pamhyr_date_to_timestamp(date:str):
+    v = date.split(":")
+    if len(v) != 4:
+        return 0
+
+    m = [
+        (24 * 60 * 60),         # Day to sec
+        (60 * 60),              # Hour to sec
+        60,                     # Minute to sec
+        1                       # Sec
+    ]
+
+    ts = reduce(
+        lambda acc, x: acc + x,
+        map(
+            lambda v, m: int(v) * int(m),
+            v, m
+        )
+    )
+
+    return ts