Results: Add tables and open window.

mesh
Pierre-Antoine Rouby 2023-08-09 08:45:44 +02:00
parent b31be5ac36
commit d499636cb6
7 changed files with 167 additions and 4 deletions

View File

@ -34,6 +34,11 @@ class Results(object):
"creation_date": datetime.now(), "creation_date": datetime.now(),
} }
@property
def date(self):
date = self._meta_data["creation_date"]
return f"{date.isoformat(sep=' ')}"
@property @property
def river(self): def river(self):
return self._river return self._river

View File

@ -26,6 +26,14 @@ class Profile(object):
self._profile = profile # Source profile in the study self._profile = profile # Source profile in the study
self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...} self._data = {} # Dict of dict {<ts>: {<key>: <value>, ...}, ...}
@property
def name(self):
return self._profile.name
@property
def kp(self):
return self._profile.kp
def set(self, timestamp, key, data): def set(self, timestamp, key, data):
if timestamp not in self._data: if timestamp not in self._data:
self._data[timestamp] = {} self._data[timestamp] = {}
@ -54,10 +62,17 @@ class Reach(object):
) )
) )
@property
def name(self):
return self._reach.name
@property @property
def profiles(self): def profiles(self):
return self._profiles.copy() return self._profiles.copy()
def profile(self, id):
return self._profiles[id]
def set(self, profile_id, timestamp, key, data): def set(self, profile_id, timestamp, key, data):
self._profiles[profile_id].set(timestamp, key, data) self._profiles[profile_id].set(timestamp, key, data)
@ -70,7 +85,10 @@ class River(object):
@property @property
def reachs(self): def reachs(self):
return self.reachs.copy() return self._reachs.copy()
def reach(self, id):
return self._reachs[id]
def add(self, reach_id): def add(self, reach_id):
reachs = self._study.river.enable_edges() reachs = self._study.river.enable_edges()

View File

@ -52,6 +52,7 @@ from View.Frictions.Window import FrictionsWindow
from View.SolverParameters.Window import SolverParametersWindow from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow from View.RunSolver.Window import SelectSolverWindow, SolverLogWindow
from View.CheckList.Window import CheckListWindow from View.CheckList.Window import CheckListWindow
from View.Results.Window import ResultsWindow
from View.Debug.Window import ReplWindow from View.Debug.Window import ReplWindow
from Model.Study import Study from Model.Study import Study
@ -105,6 +106,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
# Model # Model
self.model = None self.model = None
# Results
self._last_results = None
# UI # UI
self.ui = loadUi( self.ui = loadUi(
os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"), os.path.join(os.path.dirname(__file__), "ui", "MainWindow.ui"),
@ -304,6 +308,9 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
for action in model_action: for action in model_action:
self.enable_actions(action, not no_model) self.enable_actions(action, not no_model)
def set_results(self, results):
self._last_results = results
############ ############
# FEATURES # # FEATURES #
############ ############
@ -638,6 +645,32 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
sol.show() sol.show()
def open_solver_results(self, solver, results = None):
# If no specific results, get last results
if results is None:
results = self._last_results
# No results available
if results is None:
return
# Windows already opened
res = self.sub_win_filter_first(
"Results",
contain = [solver.name, results.date]
)
if res is None:
res = ResultsWindow(
study = self.model,
solver = solver,
results = results,
parent = self
)
res.show()
else:
res.activateWindow()
######### #########
# DEBUG # # DEBUG #
######### #########

View File

@ -15,3 +15,93 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import logging
import traceback
from tools import timer, trace
from PyQt5.QtGui import (
QKeySequence, QColor
)
from PyQt5.QtCore import (
Qt, QAbstractTableModel, QModelIndex,
QVariant, pyqtSlot, QCoreApplication,
)
from PyQt5.QtWidgets import (
QMessageBox, QUndoCommand, QUndoStack,
QStyledItemDelegate, QLineEdit, QAbstractItemView,
QComboBox,
)
from View.Results.translate import *
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)
def columnCount(self, parent=QModelIndex()):
return len(self._headers)
def data(self, index, role=Qt.DisplayRole):
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
row = index.row()
column = index.column()
if self._mode == "reach":
if self._headers[column] == "name":
v = self._results.river.reach(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
return str(v)
elif self._headers[column] == "kp":
v = current_reach.profile(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

View File

@ -75,7 +75,8 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
self._title = ( self._title = (
title + " - " title + " - "
+ self._study.name + " - " + self._study.name + " - "
+ self._solver.name + self._solver.name + " - "
+ self._results.date
) )
def setup_sc(self): def setup_sc(self):
@ -153,7 +154,7 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
.selectionChanged\ .selectionChanged\
.connect(fun[t]) .connect(fun[t])
self._table.dataChanged.connect(fun[t]) self._table[t].dataChanged.connect(fun[t])
def _set_current_reach(self): def _set_current_reach(self):
return return

View File

@ -15,3 +15,16 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from PyQt5.QtCore import QCoreApplication
_translate = QCoreApplication.translate
table_headers_reach = {
"name": _translate("Results", "Reach name"),
}
table_headers_profile = {
"name": _translate("Results", "Name"),
"kp": _translate("Results", "KP (m)"),
}

View File

@ -219,6 +219,7 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
self._process = self.new_process(self._parent) self._process = self.new_process(self._parent)
self._log(" *** Start", color="blue") self._log(" *** Start", color="blue")
self._results = None
self._solver.start(self._process) self._solver.start(self._process)
self.find(QAction, "action_start").setEnabled(False) self.find(QAction, "action_start").setEnabled(False)
@ -251,7 +252,9 @@ class SolverLogWindow(ASubMainWindow, ListedSubWindow):
self.find(QAction, "action_log_file").setEnabled(True) self.find(QAction, "action_log_file").setEnabled(True)
def results(self): def results(self):
if self._results is None:
self._results = self._solver.results(self._study, self._workdir, qlog = self._output) self._results = self._solver.results(self._study, self._workdir, qlog = self._output)
self._parent.open_solver_results(self._solver, self._results)
def log_file(self): def log_file(self):
file_name = os.path.join(self._workdir, self._solver.log_file()) file_name = os.path.join(self._workdir, self._solver.log_file())