diff --git a/doc/dev/documentation.org b/doc/dev/documentation.org
index 8ca3ff05af50ad2ef65437110803f521752e3b2c..e50fe58e0cdd5fea4f11889f5f990b74aba7d44b 100644
--- a/doc/dev/documentation.org
+++ b/doc/dev/documentation.org
@@ -671,7 +671,7 @@ method to draw the plot from scratch, the second to update the plot if
 data has changed.
 
 #+begin_src python :python python3 :results output :noweb yes
-  from View.Plot.APlot import APlot
+  from View.Tools.PamhyrPlot import PamhyrPlot
 
   class MyPlot(APlot):
       def __init__(self, canvas=None, data=None, toolbar=None):
diff --git a/src/Model/Results/Results.py b/src/Model/Results/Results.py
index 67698f4ee607b86d9c5dca556ee7dc6b9e705ba0..3258b0e170e94418fb32706368c9a1d361f13bf2 100644
--- a/src/Model/Results/Results.py
+++ b/src/Model/Results/Results.py
@@ -43,6 +43,10 @@ class Results(object):
     def river(self):
         return self._river
 
+    @property
+    def study(self):
+        return self._study
+
     def set(self, key, value):
         self._meta_data[key] = value
 
diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py
index 9f72f7318cb033f79db8113919615b6acd220de4..80cd8450505421b6436a46b0d8fc610c33acd53f 100644
--- a/src/Model/Results/River/River.py
+++ b/src/Model/Results/River/River.py
@@ -26,6 +26,9 @@ class Profile(object):
         self._profile = profile # Source profile in the study
         self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
 
+    def __len__(self):
+        return len(self._data)
+
     @property
     def name(self):
         return self._profile.name
@@ -66,6 +69,9 @@ class Reach(object):
             )
         )
 
+    def __len__(self):
+        return len(self._profiles)
+
     @property
     def name(self):
         return self._reach.name
@@ -91,6 +97,9 @@ class River(object):
         # Dict with timestamps as key
         self._reachs = []
 
+    def __len__(self):
+        return len(self._reachs)
+
     @property
     def reachs(self):
         return self._reachs.copy()
diff --git a/src/View/CheckList/Translate.py b/src/View/CheckList/Translate.py
new file mode 100644
index 0000000000000000000000000000000000000000..b3ce856d4c1caee1c559f25d4376d9d859191deb
--- /dev/null
+++ b/src/View/CheckList/Translate.py
@@ -0,0 +1,32 @@
+# Translate.py -- Pamhyr
+# Copyright (C) 2023  INRAE
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+# -*- coding: utf-8 -*-
+
+from PyQt5.QtCore import QCoreApplication
+
+from View.Tools.PamhyrTranslate import PamhyrTranslate
+
+_translate = QCoreApplication.translate
+
+class CheckListTranslate(PamhyrTranslate):
+    def __init__(self):
+        super(CheckListTranslate, self).__init__()
+
+        self._sub_dict["table_headers"] = {
+            "name": _translate("CheckList", "Name"),
+            "status": _translate("CheckList", "Status"),
+        }
diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py
index 20f4f065a17b672ce011fa09210681f06bc93c27..e2a8859cefe4fb64d8160cb55fc13c8680d4a6a3 100644
--- a/src/View/MainWindow.py
+++ b/src/View/MainWindow.py
@@ -55,7 +55,7 @@ from View.SedimentLayers.Reach.Window import ReachSedimentLayersWindow
 from View.SolverParameters.Window import SolverParametersWindow
 from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
 from View.CheckList.Window import CheckListWindow
-# from View.Results.Window import ResultsWindow
+from View.Results.Window import ResultsWindow
 from View.Debug.Window import ReplWindow
 
 from Model.Study import Study
diff --git a/src/View/Results/PlotAC.py b/src/View/Results/PlotAC.py
index f0e4b0e287ae351699c5a531aba8aae22f5db797..ed3d99ad8fa52d5e6ebe7aa35724d354857e6fa4 100644
--- a/src/View/Results/PlotAC.py
+++ b/src/View/Results/PlotAC.py
@@ -17,7 +17,7 @@
 # -*- coding: utf-8 -*-
 
 from tools import timer
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
 
 _translate = QCoreApplication.translate
 
-class PlotAC(APlot):
-    def __init__(self, canvas=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None):
+class PlotAC(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 parent=None):
         super(PlotAC, self).__init__(
-            canvas=canvas,
-            data=results,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self._current_timestamp = max(results.get("timestamps"))
diff --git a/src/View/Results/PlotH.py b/src/View/Results/PlotH.py
index 557c7cec2b986f20fe682355e759c8fadbc40af4..99a59f88cd3c01a7ac7a696c5dcfe431feb39cb9 100644
--- a/src/View/Results/PlotH.py
+++ b/src/View/Results/PlotH.py
@@ -22,7 +22,7 @@ from functools import reduce
 from datetime import datetime
 
 from tools import timer, trace
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -32,14 +32,16 @@ _translate = QCoreApplication.translate
 
 logger = logging.getLogger()
 
-class PlotH(APlot):
-    def __init__(self, canvas=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None):
+class PlotH(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 parent=None):
         super(PlotH, self).__init__(
-            canvas=canvas,
-            data=results,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self._mode = "time"
diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py
index 68f6fb4e043e8873d232857bd2ff3863c42ba719..61de649d4bea0e4ef66b205a72b956b0883a5079 100644
--- a/src/View/Results/PlotKPC.py
+++ b/src/View/Results/PlotKPC.py
@@ -17,7 +17,7 @@
 # -*- coding: utf-8 -*-
 
 from tools import timer
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -25,14 +25,16 @@ from PyQt5.QtCore import (
 
 _translate = QCoreApplication.translate
 
-class PlotKPC(APlot):
-    def __init__(self, canvas=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None):
+class PlotKPC(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 parent=None):
         super(PlotKPC, self).__init__(
-            canvas=canvas,
-            data=results,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self._current_timestamp = max(results.get("timestamps"))
diff --git a/src/View/Results/PlotSedProfile.py b/src/View/Results/PlotSedProfile.py
index 62f4e29059972bd35b0b70bf2dea9cccb433a12d..3163931bccd55eb953811d41b47df16e17373060 100644
--- a/src/View/Results/PlotSedProfile.py
+++ b/src/View/Results/PlotSedProfile.py
@@ -5,7 +5,7 @@ import logging
 from functools import reduce
 
 from tools import timer
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
 
 logger = logging.getLogger()
 
-class PlotSedProfile(APlot):
-    def __init__(self, canvas=None, study=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None):
+class PlotSedProfile(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 parent=None):
         super(PlotSedProfile, self).__init__(
-            canvas=canvas,
-            data=study,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self._results = results
diff --git a/src/View/Results/PlotSedReach.py b/src/View/Results/PlotSedReach.py
index 657b70e855a8c10c393e028428fa45c33132a1b8..c63c80ec900034442163704a32a0ebd3f21be795 100644
--- a/src/View/Results/PlotSedReach.py
+++ b/src/View/Results/PlotSedReach.py
@@ -5,7 +5,7 @@ import logging
 from functools import reduce
 
 from tools import timer
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -15,14 +15,16 @@ _translate = QCoreApplication.translate
 
 logger = logging.getLogger()
 
-class PlotSedReach(APlot):
-    def __init__(self, canvas=None, study=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None):
+class PlotSedReach(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 parent=None):
         super(PlotSedReach, self).__init__(
-            canvas=canvas,
-            data=study,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self._results = results
diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py
index 3e7a88f3d0daf53b860eeb0deba0e9525f77c3c8..4271677610c23556a0ee418ff2e38345dda1d40d 100644
--- a/src/View/Results/PlotXY.py
+++ b/src/View/Results/PlotXY.py
@@ -21,7 +21,7 @@ import logging
 from functools import reduce
 
 from tools import timer, trace
-from View.Plot.APlot import APlot
+from View.Tools.PamhyrPlot import PamhyrPlot
 
 from PyQt5.QtCore import (
     QCoreApplication
@@ -31,14 +31,16 @@ _translate = QCoreApplication.translate
 
 logger = logging.getLogger()
 
-class PlotXY(APlot):
-    def __init__(self, canvas=None, results=None,
-                 reach_id=0, profile_id=0,
-                 toolbar=None, display_current=True):
+class PlotXY(PamhyrPlot):
+    def __init__(self, canvas=None, trad=None, toolbar=None,
+                 results=None, reach_id=0, profile_id=0,
+                 display_current=True, parent=None):
         super(PlotXY, self).__init__(
-            canvas=canvas,
-            data=results,
-            toolbar=toolbar
+            canvas = canvas,
+            trad = trad,
+            data = results,
+            toolbar = toolbar,
+            parent = parent
         )
 
         self.display_current = display_current
diff --git a/src/View/Results/Table.py b/src/View/Results/Table.py
index 8e167459593af03d444b0cfa113d87202544e2a0..f4d7b81ae731dae9ca51cab61172dcd9b20c94ef 100644
--- a/src/View/Results/Table.py
+++ b/src/View/Results/Table.py
@@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (
     QComboBox,
 )
 
+from View.Tools.PamhyrTable import PamhyrTableModel
 from View.Results.translate import *
 
 logger = logging.getLogger()
@@ -41,33 +42,16 @@ logger = logging.getLogger()
 _translate = QCoreApplication.translate
 
 
-class TableModel(QAbstractTableModel):
-    def __init__(self, results = None, study = None, mode = None, undo=None):
-        super(QAbstractTableModel, self).__init__()
-
-        self._results = results
-        self._study = study
-        self._mode = mode
-        self._undo_stack = undo
-
-        self._table_headers = table_headers_reach
-        if mode != "reach":
-            self._table_headers = table_headers_profile
-
-        self._headers = list(self._table_headers.keys())
-
-        self._selected = 0
-        self._timestamp = 0
-
-    def rowCount(self, parent=QModelIndex()):
-        if self._mode == "reach":
-            return len(self._results.river.reachs)
-
-        current_reach = self._results.river.reach(self._selected)
-        return len(current_reach.profiles)
+class TableModel(PamhyrTableModel):
+    def _setup_lst(self):
+        _river = self._data.river
+        if self._opt_data == "reach":
+            self._lst = _river.reachs
+        else:
+            self._lst = _river.reach(0).profiles
 
-    def columnCount(self, parent=QModelIndex()):
-        return len(self._headers)
+    def __init__(self, **kwargs):
+        super(TableModel, self).__init__(**kwargs)
 
     def data(self, index, role=Qt.DisplayRole):
         if role != Qt.ItemDataRole.DisplayRole:
@@ -76,32 +60,23 @@ class TableModel(QAbstractTableModel):
         row = index.row()
         column = index.column()
 
-        if self._mode == "reach":
+        if self._opt_data == "reach":
             if self._headers[column] == "name":
-                v = self._results.river.reach(row).name
+                v = self._lst[row].name
                 return str(v)
         else:
-            current_reach = self._results.river.reach(self._selected)
             if self._headers[column] == "name":
-                v = current_reach.profile(row).name
+                v = self._lst[row].name
                 return str(v)
             elif self._headers[column] == "kp":
-                v = current_reach.profile(row).kp
+                v = self._lst[row].kp
                 return f"{v:.4f}"
 
         return QVariant()
 
-    def headerData(self, section, orientation, role=Qt.DisplayRole):
-        if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
-            return self._table_headers[self._headers[section]]
-
-        return QVariant()
-
-    def index(self, row, column, parent=QModelIndex()):
-        if not self.hasIndex(row, column, parent):
-            return QModelIndex()
-
-        return self.createIndex(row, column, QModelIndex())
-
-    def flags(self, index):
-        return Qt.ItemIsEnabled | Qt.ItemIsSelectable
+    def update(self, reach):
+        _river = self._data.river
+        if self._opt_data == "reach":
+            self._lst = _river.reachs
+        else:
+            self._lst = _river.reach(reach).profiles
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index 4009c83624fe4daebbd49f35ac2186c82a2f57ed..61e9f22b7e7f20529fad7f60bfe124fba5417a73 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -41,8 +41,8 @@ from PyQt5.QtWidgets import (
     QSlider, QLabel,
 )
 
-from View.Plot.MplCanvas import MplCanvas
-from View.Plot.PamhyrToolbar import PamhyrPlotToolbar
+from View.Tools.Plot.PamhyrCanvas import MplCanvas
+from View.Tools.Plot.PamhyrToolbar import PamhyrPlotToolbar
 
 from View.Results.PlotXY import PlotXY
 from View.Results.PlotAC import PlotAC
@@ -52,10 +52,7 @@ from View.Results.PlotSedReach import PlotSedReach
 from View.Results.PlotSedProfile import PlotSedProfile
 
 from View.Results.Table import TableModel
-from View.Results.translate import (
-    table_headers_reach, table_headers_profile,
-    retranslate,
-)
+from View.Results.translate import ResultsTranslate
 from View.Stricklers.Window import StricklersWindow
 
 _translate = QCoreApplication.translate
@@ -85,42 +82,27 @@ class ResultsWindow(PamhyrWindow):
             title = name,
             study = study,
             config = config,
+            trad = ResultsTranslate(),
             parent=parent
         )
 
         self.setup_table()
-        self.setup_graph()
+        self.setup_plot()
         self.setup_slider()
         self.setup_statusbar()
         self.setup_connections()
 
-        self.ui.setWindowTitle(self._title)
-
-    def setup_title(self, title):
-        self._title = (
-            title + " - "
-            + self._study.name + " - "
-            + self._solver.name + " - "
-            + self._results.date
-        )
-
     def setup_table(self):
-        retranslate()
         self._table = {}
-
         for t in ["reach", "profile"]:
             table = self.find(QTableView, f"tableView_{t}")
             self._table[t] = TableModel(
-                results = self._results,
-                study = self._study,
-                mode = t,
+                table_view = table,
+                table_headers = self._trad.get_dict(f"table_headers_{t}"),
+                data = self._results,
                 undo = self._undo_stack,
+                opt_data = t
             )
-            table.setModel(self._table[t])
-
-            table.setSelectionBehavior(QAbstractItemView.SelectRows)
-            table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
-            table.setAlternatingRowColors(True)
 
     def setup_slider(self):
         self._slider_profile = self.find(QSlider, f"verticalSlider_profile")
@@ -132,7 +114,7 @@ class ResultsWindow(PamhyrWindow):
         self._slider_time.setMaximum(len(self._timestamps) - 1)
         self._slider_time.setValue(len(self._timestamps) - 1)
 
-    def setup_graph(self):
+    def setup_plot(self):
         self.canvas = MplCanvas(width=5, height=4, dpi=100)
         self.canvas.setObjectName("canvas")
         self.toolbar = PamhyrPlotToolbar(
@@ -219,7 +201,6 @@ class ResultsWindow(PamhyrWindow):
             self.plot_sed_reach = PlotSedReach(
                 canvas = self.canvas_5,
                 results = self._results,
-                study = self._study,
                 reach_id = 0,
                 profile_id = 0,
                 toolbar = self.toolbar_5
@@ -239,7 +220,6 @@ class ResultsWindow(PamhyrWindow):
             self.plot_sed_profile = PlotSedProfile(
                 canvas = self.canvas_6,
                 results = self._results,
-                study = self._study,
                 reach_id = 0,
                 profile_id = 0,
                 toolbar = self.toolbar_6
diff --git a/src/View/Results/translate.py b/src/View/Results/translate.py
index 37351b669762db80d4fba5d30a50e2bee5511229..14f55ba36ba4467b4f002d7665a91481c761dd67 100644
--- a/src/View/Results/translate.py
+++ b/src/View/Results/translate.py
@@ -18,19 +18,19 @@
 
 from PyQt5.QtCore import QCoreApplication
 
-_translate = QCoreApplication.translate
+from View.Tools.PamhyrTranslate import PamhyrTranslate
 
-table_headers_reach = {
-    "name": _translate("Results", "Reach name"),
-}
+_translate = QCoreApplication.translate
 
-table_headers_profile = {
-    "name": _translate("Results", "Name"),
-    "kp": _translate("Results", "KP (m)"),
-}
+class ResultsTranslate(PamhyrTranslate):
+    def __init__(self):
+        super(ResultsTranslate, self).__init__()
 
-def retranslate():
-    table_headers_reach["name"] = _translate("Results", "Reach name")
+        self._sub_dict["table_headers_reach"] = {
+            "name": _translate("Results", "Reach name"),
+        }
 
-    table_headers_profile["name"] = _translate("Results", "Name")
-    table_headers_profile["kp"] = _translate("Results", "KP (m)")
+        self._sub_dict["table_headers_profile"] = {
+            "name": _translate("Results", "Name"),
+            "kp": _translate("Results", "KP (m)"),
+        }