Checker: Add base of checker list view.

mesh
Pierre-Antoine Rouby 2023-06-16 11:43:58 +02:00
parent 768a743f0f
commit fe9eada0ba
8 changed files with 312 additions and 31 deletions

View File

@ -26,6 +26,10 @@ class AbstractModelChecker(object):
def description(self): def description(self):
return self._description return self._description
@property
def summary(self):
return self._summary
# Checker status # Checker status
def is_unknown(self): def is_unknown(self):
@ -53,11 +57,3 @@ class AbstractModelChecker(object):
otherelse otherelse
""" """
raise NotImplementedMethodeError(self, self.run) raise NotImplementedMethodeError(self, self.run)
def summary(self):
"""Return summary message
Returns:
Return summary string
"""
raise NotImplementedMethodeError(self, self.summary)

36
src/Checker/Study.py Normal file
View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from PyQt5.QtCore import QCoreApplication
from Checker.Checker import AbstractModelChecker, STATUS
_translate = QCoreApplication.translate
class StudyNetworkReachChecker(AbstractModelChecker):
def __init__(self):
super(StudyNetworkReachChecker, self).__init__()
self._name = _translate("Checker", "Study network reach checker")
self._description = _translate("Checker", "Check if exists at least one reach for study")
def run(self, study):
if study is None:
self._status = STATUS.ERROR
self._summary = "invalid_study"
return False
river = study.river
if river is None:
self._status = STATUS.ERROR
self._summary = "no_river_found"
return False
if len(river.edges()) == 0:
self._status = STATUS.ERROR
self._summary = "no_reach_defined"
return False
self._summary = "ok"
self._status = STATUS.OK
return True

View File

@ -8,6 +8,7 @@ from Model.Serializable import Serializable
from Model.River import River from Model.River import River
from Checker.Study import *
class Study(Serializable): class Study(Serializable):
def __init__(self): def __init__(self):
@ -31,6 +32,14 @@ class Study(Serializable):
# Study data # Study data
self._river = River(status = self.status) self._river = River(status = self.status)
@classmethod
def checkers(cls):
lst = [
StudyNetworkReachChecker(),
]
return lst
@property @property
def river(self): def river(self):
return self._river return self._river

View File

@ -56,7 +56,7 @@ class AbstractSolver(object):
return lst return lst
@classmethod @classmethod
def checker(cls): def checkers(cls):
lst = [ lst = [
] ]

View File

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
from tools import trace, timer
from PyQt5.QtCore import (
Qt, QVariant, QAbstractTableModel,
QCoreApplication, QModelIndex, pyqtSlot,
QRect,
)
from PyQt5.QtGui import (
QColor, QBrush,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QPushButton, QLineEdit,
QFileDialog, QTableView, QAbstractItemView,
QUndoStack, QShortcut, QAction, QItemDelegate,
QComboBox,
)
_translate = QCoreApplication.translate
class TableModel(QAbstractTableModel):
def __init__(self, data=None):
super(QAbstractTableModel, self).__init__()
self._headers = ["name", "status"]
self._data = data
def flags(self, index):
options = Qt.ItemIsEnabled | Qt.ItemIsSelectable
return options
def rowCount(self, parent):
return len(self._data)
def columnCount(self, parent):
return len(self._headers)
def data(self, index, role):
row = index.row()
column = index.column()
if role == Qt.ForegroundRole:
if self._headers[column] == "status":
color = Qt.gray
if self._data[row].is_ok():
color = Qt.green
elif self._data[row].is_warning():
color = Qt.yellow
elif self._data[row].is_error():
color = Qt.red
return QBrush(color)
return QVariant()
if role != Qt.ItemDataRole.DisplayRole:
return QVariant()
if self._headers[column] == "name":
return self._data[row].name
if self._headers[column] == "status":
return self._data[row].summary
return QVariant()
def headerData(self, section, orientation, role):
if role == Qt.ItemDataRole.DisplayRole and orientation == Qt.Orientation.Horizontal:
return self._headers[section]
return QVariant()
def update(self):
self.layoutChanged.emit()

View File

@ -0,0 +1,135 @@
# -*- coding: utf-8 -*-
import time
import threading
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,
QRect,
)
from PyQt5.QtWidgets import (
QDialogButtonBox, QPushButton, QLineEdit,
QFileDialog, QTableView, QAbstractItemView,
QUndoStack, QShortcut, QAction, QItemDelegate,
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
QProgressBar,
)
from View.CheckList.Table import TableModel
_translate = QCoreApplication.translate
def _run_checker_list(study, checker_list, parent):
parent.start_compute()
for checker in checker_list:
time.sleep(1)
checker.run(study)
parent.progress()
parent.end_compute()
class CheckListWindow(ASubMainWindow, ListedSubWindow):
def __init__(self, title="Check list",
study=None, config=None,
solver=None, parent=None):
self._title = title + " - " + study.name
self._study = study
self._config = config
self._solver = solver
super(CheckListWindow, self).__init__(
name=self._title, ui="CheckList", parent=parent
)
self.ui.setWindowTitle(self._title)
self._checker_list = (
self._study.checkers() + self._solver.checkers()
)
self.setup_table()
self.setup_progress_bar()
self.setup_connections()
self.setup_thread()
def setup_table(self):
table = self.find(QTableView, f"tableView")
self._table = TableModel(
data = self._checker_list,
)
table.setModel(self._table)
table.setSelectionBehavior(QAbstractItemView.SelectRows)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.setAlternatingRowColors(True)
def setup_progress_bar(self):
self._progress = self.find(QProgressBar, f"progressBar")
self._p = 0 # Progress current step
self._progress.setRange(0, len(self._checker_list))
self._progress.setValue(self._p)
def setup_connections(self):
self.find(QPushButton, "pushButton_ok").clicked.connect(self.accept)
self.find(QPushButton, "pushButton_retry").clicked.connect(self.retry)
self.find(QPushButton, "pushButton_cancel").clicked.connect(self.reject)
def setup_thread(self):
self._t1 = threading.Thread(
target=_run_checker_list,
args=(self._study, self._checker_list, self,)
)
self._t1.start()
def progress(self):
self._p += 1
self._progress.setValue(self._p)
# self._table.update()
def start_compute(self):
self._p = 0
self._progress.setValue(self._p)
def end_compute(self):
self._table.layoutChanged.emit()
self.find(QPushButton, "pushButton_retry").setEnabled(True)
errors = list(filter(lambda c: c.is_error(), self._checker_list))
if len(errors) == 0:
self.find(QPushButton, "pushButton_ok").setEnabled(True)
def end(self):
# self._t1.join()
self.close()
def retry(self):
self._t1.join()
self._t1 = threading.Thread(
target=_run_checker_list,
args=(self._study, self._checker_list, self,)
)
self.find(QPushButton, "pushButton_retry").setEnabled(False)
self.find(QPushButton, "pushButton_ok").setEnabled(False)
self._t1.start()
def reject(self):
print("cancel")
self.end()
def accept(self):
print("ok")
self.end()

View File

@ -29,6 +29,7 @@ from View.Stricklers.Window import StricklersWindow
from View.Sections.Window import SectionsWindow from View.Sections.Window import SectionsWindow
from View.SolverParameters.Window import SolverParametersWindow from View.SolverParameters.Window import SolverParametersWindow
from View.RunSolver.Window import SelectSolverWindow from View.RunSolver.Window import SelectSolverWindow
from View.CheckList.Window import CheckListWindow
from Model.Study import Study from Model.Study import Study
@ -382,6 +383,13 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit):
) )
if run.exec(): if run.exec():
solver = run.solver solver = run.solver
check = CheckListWindow(
study = self.model,
config = self.conf,
solver = solver,
parent = self
)
check.show()
# TODO: Delete me ! # TODO: Delete me !
############### ###############

View File

@ -16,7 +16,7 @@
<widget class="QWidget" name="centralwidget"> <widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QListView" name="listView"/> <widget class="QTableView" name="tableView"/>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QProgressBar" name="progressBar"> <widget class="QProgressBar" name="progressBar">
@ -26,31 +26,52 @@
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_retry">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="standardButtons"> <property name="text">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set> <string>Retry</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_ok">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Ok</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item>
</layout>
</widget> </widget>
<widget class="QStatusBar" name="statusbar"/> <widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="action_retry"/>
<addaction name="action_cancel"/>
</widget>
<action name="action_retry"> <action name="action_retry">
<property name="icon"> <property name="icon">
<iconset> <iconset>