diff --git a/src/View/Results/PlotAC.py b/src/View/Results/PlotAC.py
new file mode 100644
index 00000000..7c882e6e
--- /dev/null
+++ b/src/View/Results/PlotAC.py
@@ -0,0 +1,17 @@
+# PlotAC.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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py
new file mode 100644
index 00000000..c044d35e
--- /dev/null
+++ b/src/View/Results/PlotKPC.py
@@ -0,0 +1,17 @@
+# PlotKPC.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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py
new file mode 100644
index 00000000..a8c4b206
--- /dev/null
+++ b/src/View/Results/PlotXY.py
@@ -0,0 +1,17 @@
+# PlotXY.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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/Results/Table.py b/src/View/Results/Table.py
new file mode 100644
index 00000000..bfe2dbaa
--- /dev/null
+++ b/src/View/Results/Table.py
@@ -0,0 +1,17 @@
+# Table.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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/Results/UndoCommand.py b/src/View/Results/UndoCommand.py
new file mode 100644
index 00000000..ca18efaa
--- /dev/null
+++ b/src/View/Results/UndoCommand.py
@@ -0,0 +1,17 @@
+# UndoCommand.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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
new file mode 100644
index 00000000..90955df5
--- /dev/null
+++ b/src/View/Results/Window.py
@@ -0,0 +1,174 @@
+# Window.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 .
+
+# -*- coding: utf-8 -*-
+
+import logging
+
+from tools import trace, timer
+
+from View.ASubWindow import ASubMainWindow
+from View.ListedSubWindow import ListedSubWindow
+
+from PyQt5.QtGui import (
+ QKeySequence,
+)
+
+from PyQt5.QtCore import (
+ Qt, QVariant, QAbstractTableModel,
+ QCoreApplication, QModelIndex, pyqtSlot,
+)
+
+from PyQt5.QtWidgets import (
+ QDialogButtonBox, QPushButton, QLineEdit,
+ QFileDialog, QTableView, QAbstractItemView,
+ QUndoStack, QShortcut, QAction, QItemDelegate,
+ QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
+)
+
+from View.Plot.MplCanvas import MplCanvas
+from View.Geometry.PlotKPC import PlotKPC
+
+from View.Results.Table import TableModel
+from View.Results.translate import *
+from View.Stricklers.Window import StricklersWindow
+
+_translate = QCoreApplication.translate
+
+logger = logging.getLogger()
+
+class ResultsWindow(ASubMainWindow, ListedSubWindow):
+ def __init__(self, title="Results",
+ study=None, solver=None, results=None,
+ parent=None):
+ self._study = study
+ self._solver = solver
+ self._results = results
+
+ self.setup_title(title)
+
+ super(ResultsWindow, self).__init__(
+ name=title, ui="Results", parent=parent
+ )
+
+ self.setup_sc()
+ self.setup_table()
+ self.setup_graph()
+ self.setup_connections()
+
+ self.ui.setWindowTitle(self._title)
+
+ def setup_title(self, title):
+ self._title = (
+ title + " - "
+ + self._study.name + " - "
+ + self._solver.name
+ )
+
+ 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):
+ 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,
+ undo = self._undo_stack,
+ )
+ table.setModel(self._table[t])
+
+ table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+ table.setAlternatingRowColors(True)
+
+ def setup_graph(self):
+ self.canvas = MplCanvas(width=5, height=4, dpi=100)
+ self.canvas.setObjectName("canvas")
+ self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
+ self.plot_layout.addWidget(self.canvas)
+
+ # self.plot = PlotKPC(
+ # canvas = self.canvas,
+ # data = self._reach.reach,
+ # toolbar = None,
+ # display_current = False
+ # )
+ # self.plot.draw()
+
+ self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
+ self.canvas_2.setObjectName("canvas_2")
+ self.plot_layout_2 = self.find(QVBoxLayout, "verticalLayout_2")
+ self.plot_layout_2.addWidget(self.canvas_2)
+
+ # self.plot_2 = PlotStricklers(
+ # canvas = self.canvas_2,
+ # data = self._reach,
+ # toolbar = None
+ # )
+ # self.plot_2.draw()
+
+ self.canvas_3 = MplCanvas(width=5, height=4, dpi=100)
+ self.canvas_3.setObjectName("canvas_3")
+ self.plot_layout_3 = self.find(QVBoxLayout, "verticalLayout_3")
+ self.plot_layout_3.addWidget(self.canvas_3)
+
+
+ def setup_connections(self):
+ 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)
+
+ fun = {
+ "reach": self._set_current_reach,
+ "profile": self._set_current_profile,
+ }
+
+ for t in ["reach", "profile"]:
+ table = self.find(QTableView, f"tableView_{t}")
+
+ table.selectionModel()\
+ .selectionChanged\
+ .connect(fun[t])
+
+ self._table.dataChanged.connect(fun[t])
+
+ def _set_current_reach(self):
+ return
+
+ def _set_current_profile(self):
+ return
+
+ def copy(self):
+ logger.info("TODO: copy")
+
+ def paste(self):
+ logger.info("TODO: paste")
+
+ def undo(self):
+ self._table.undo()
+
+ def redo(self):
+ self._table.redo()
diff --git a/src/View/Results/translate.py b/src/View/Results/translate.py
new file mode 100644
index 00000000..dad67d85
--- /dev/null
+++ b/src/View/Results/translate.py
@@ -0,0 +1,17 @@
+# 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 .
+
+# -*- coding: utf-8 -*-
diff --git a/src/View/ui/Results.ui b/src/View/ui/Results.ui
new file mode 100644
index 00000000..2f886339
--- /dev/null
+++ b/src/View/ui/Results.ui
@@ -0,0 +1,96 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 942
+ 655
+
+
+
+ MainWindow
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ Qt::Vertical
+
+
+
+
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ true
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+