This commit is contained in:
matteo porta 2022-07-26 12:24:53 +02:00
parent af61cbb6f9
commit 408a1e466f
14 changed files with 300 additions and 250 deletions

View File

@ -59,66 +59,66 @@ if admin is None or not admin.is_admin:
Users.register(username="ADMIN", password="123123", roles=["admin"])
# register or reset user
Users.register(username="USER", password="user")
# register test steps
Steps.replace(
id=0,
name="TEST_LEAK_TEST",
type="leak",
spec={
"pre_filling_time": 5,
"pre_filling_pressure": 1000,
"filling_time": 5,
"settling_time": 10,
"settling_pressure_min_percent": 50,
"settling_pressure_max_percent": 50,
"test_time": 10,
"test_pressure_min_delta": 500,
"test_pressure": 1000,
"test_pressure_max_delta": 500,
"flush_time": 2,
"flush_pressure": 5,
},
description="TEST_DESCRIPTION",
archived=False,
).execute()
Steps.replace(
id=1,
name="TEST_LEAK_TEST",
type="leak",
spec={
"pre_filling_time": 5,
"pre_filling_pressure": 1000,
"filling_time": 5,
"settling_time": 10,
"settling_pressure_min_percent": 50,
"settling_pressure_max_percent": 50,
"test_time": 10,
"test_pressure_min_delta": 500,
"test_pressure": 1000,
"test_pressure_max_delta": 500,
"flush_time": 2,
"flush_pressure": 5,
},
description="TEST_DESCRIPTION",
archived=False,
).execute()
Steps.replace(
id=2,
name="TEST_VISION_TEST",
type="vision",
spec={
"recipe": "1.ini",
},
description="TEST_DESCRIPTION VISION_RECIPE: 1",
archived=False,
).execute()
# # register test steps
# Steps.replace(
# id=0,
# name="TEST_LEAK_TEST",
# type="leak",
# spec={
# "pre_filling_time": 5,
# "pre_filling_pressure": 1000,
# "filling_time": 5,
# "settling_time": 10,
# "settling_pressure_min_percent": 50,
# "settling_pressure_max_percent": 50,
# "test_time": 10,
# "test_pressure_min_delta": 500,
# "test_pressure": 1000,
# "test_pressure_max_delta": 500,
# "flush_time": 2,
# "flush_pressure": 5,
# },
# description="TEST_DESCRIPTION",
# archived=False,
# ).execute()
# Steps.replace(
# id=1,
# name="TEST_LEAK_TEST",
# type="leak",
# spec={
# "pre_filling_time": 5,
# "pre_filling_pressure": 1000,
# "filling_time": 5,
# "settling_time": 10,
# "settling_pressure_min_percent": 50,
# "settling_pressure_max_percent": 50,
# "test_time": 10,
# "test_pressure_min_delta": 500,
# "test_pressure": 1000,
# "test_pressure_max_delta": 500,
# "flush_time": 2,
# "flush_pressure": 5,
# },
# description="TEST_DESCRIPTION",
# archived=False,
# ).execute()
# Steps.replace(
# id=2,
# name="TEST_VISION_TEST",
# type="vision",
# spec={
# "recipe": "1.ini",
# },
# description="TEST_DESCRIPTION VISION_RECIPE: 1",
# archived=False,
# ).execute()
# register test recipe
Recipes.replace(
id=0,
name="TEST",
client="TEST_CLIENT",
part_number="TEST_PART_NUMBER",
spec={"steps": [0, 1, 2, ]},
spec={"steps": []},
description="TEST_DESCRIPTION",
archived=False,
).execute()

View File

@ -6,10 +6,10 @@ from .base_model import BaseModel
class Steps(BaseModel):
id = AutoField(primary_key=True, unique=True, null=False)
name = TextField(null=False)
name = TextField(null=True)
type = TextField(null=False)
spec = JSONField(null=False) # keys inside spec must not overlap withthe model
description = TextField(null=False)
description = TextField(null=True)
archived = BooleanField(null=False, default=False)
@classmethod

View File

@ -6,7 +6,7 @@ from datetime import datetime
from lib.db import Crud_DB
from peewee import TextField
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtCore import QObject, Qt, pyqtSignal
from PyQt5.QtWidgets import (QAbstractItemView, QComboBox, QDialog,
QGridLayout, QHeaderView, QLineEdit, QMessageBox,
QPlainTextEdit, QPushButton)
@ -53,7 +53,7 @@ class Cell:
self.set_readonly(self.readonly)
self.do_autocomplete(self.autocomplete)
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
raise NotImplementedError()
def do_autocomplete(self, autocomplete):
@ -104,7 +104,7 @@ class Line_Edit_Cell_Widget(QLineEdit, Cell):
super().__init__()
Cell.__init__(self, readonly=readonly, autocomplete=autocomplete, field_name=field_name, field_alias=field_alias, field=field, row_number=row_number, crud=crud)
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
self.setReadOnly(readonly)
def connect_modified(self):
@ -123,7 +123,7 @@ class Combo_Box_Cell_Widget(QComboBox, Cell):
super().__init__()
Cell.__init__(self, readonly=readonly, autocomplete=autocomplete, field_name=field_name, field_alias=field_alias, field=field, row_number=row_number, crud=crud)
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
self.setEditable(not readonly)
def do_autocomplete(self, autocomplete):
@ -151,11 +151,14 @@ class External_Dialog_Cell_Widget(QPushButton, Cell):
super().__init__(u"\u238B modifica")
Cell.__init__(self, readonly=readonly, autocomplete=autocomplete, field_name=field_name, field_alias=field_alias, field=field, row_number=row_number, crud=crud)
self.dialog.setWindowTitle(self.field_alias)
self.clicked.connect(self.dialog.show)
self.clicked.connect(self.show_dialog)
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
self.editor.setReadOnly(readonly)
def show_dialog(self):
self.dialog.show()
def connect_modified(self):
self.editor.textChanged.connect(self.check_modified)
@ -175,24 +178,31 @@ class Json_External_Dialog_Cell_Widget(External_Dialog_Cell_Widget):
class Json_External_Dialog_Editor_Cell_Widget(QPushButton, Cell):
def __init__(self, editor_widget_instance, readonly=True, autocomplete=None, field_name=None, field_alias=None, field=None, row_number=None, crud=None):
if not isinstance(editor_widget_instance, Editor):
raise AssertionError(f"editor_widget_instance {editor_widget_instance!r} must be a subclass of {Editor!r}")
self.editor = editor_widget_instance
def __init__(self, editor_widget_class, *args, readonly=True, autocomplete=None, field_name=None, field_alias=None, field=None, row_number=None, crud=None, **kwargs):
if not issubclass(editor_widget_class, Editor):
raise AssertionError(f"editor_widget_class {editor_widget_class!r} must be a subclass of {Editor!r}")
self.editor = editor_widget_class(*args, cell_widget=self, **kwargs)
super().__init__(u"\u238B modifica")
Cell.__init__(self, readonly=readonly, autocomplete=autocomplete, field_name=field_name, field_alias=field_alias, field=field, row_number=row_number, crud=crud)
self.dialog = Dialog()
self.dialog.setAttribute(Qt.WA_DeleteOnClose, on=False)
self.dialog.setCentralWidget(self.editor)
super().__init__(u"\u238B modifica")
Cell.__init__(self, readonly=readonly, autocomplete=autocomplete, field_name=field_name, field_alias=field_alias, field=field, row_number=row_number, crud=crud)
self.dialog.setWindowTitle(self.field_alias)
self.clicked.connect(self.dialog.show)
self.clicked.connect(self.show_dialog)
if hasattr(self.editor, "init"):
self.editor.init()
def set_readonly(self, readonly):
self.editor.set_readonly(readonly)
def set_readonly(self, readonly=True):
self.editor.set_readonly(readonly=readonly)
def do_autocomplete(self, autocomplete):
self.editor.do_autocomplete(autocomplete)
def show_dialog(self):
if hasattr(self.editor, "showing_dialog"):
self.editor.showing_dialog()
self.dialog.show()
def connect_modified(self):
self.editor.connect_modified(self.check_modified)
@ -412,6 +422,8 @@ class Crud(Widget):
for fn, cn in self.select_index.items():
readonly = self.readonly is None or self.readonly is True or (self.readonly is not False and fn in self.readonly)
w = self.widget_classes.get(fn, self.default_widget_class)(readonly=readonly, autocomplete=self.autocomplete.get(fn, None), field_name=fn, field_alias=self.fields_aliases[fn], field=self.db.table_model._meta.fields.get(fn, None), row_number=rn, crud=self)
w.set_readonly(readonly=w.readonly)
w.do_autocomplete(w.autocomplete)
w.modified.connect(self.set_modified)
if fn in r:
w._render(data=r[fn], row_number=rn, crud=self)
@ -434,6 +446,8 @@ class Crud(Widget):
for fn, cn in self.select_index.items():
readonly = self.readonly is None or self.readonly is True or (self.readonly is not False and fn in self.readonly)
w = self.widget_classes.get(fn, self.default_widget_class)(readonly=readonly, autocomplete=self.autocomplete.get(fn, None), field_name=fn, field_alias=self.fields_aliases[fn], field=self.db.table_model._meta.fields.get(fn, None), row_number=rn, crud=self)
w.set_readonly(readonly=w.readonly)
w.do_autocomplete(w.autocomplete)
w.modified.connect(self.set_modified)
self.db_tw.setCellWidget(rn, cn, w)
self.db_tw.scrollToBottom()

View File

@ -6,16 +6,19 @@ from ui.widget import Widget
class Editor(Widget):
def __init__(self):
def __init__(self, cell_widget=None):
super().__init__()
self.cell_widget = cell_widget
self.spec = {}
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
for w in self.spec.values():
if isinstance(w, QComboBox):
w.setDisabled(readonly)
elif isinstance(w, QListWidget):
w.setDisabled(readonly)
elif isinstance(w, QCheckBox):
w.setDisabled(readonly)
elif isinstance(w, QObject):
w.setReadOnly(readonly)

BIN
src/ui/imgs/print.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -2,8 +2,8 @@ from ui.editor import Editor
class Leak_Step_Editor(Editor):
def __init__(self):
super().__init__()
def __init__(self, cell_widget=None):
super().__init__(cell_widget=cell_widget)
self.spec.update({
# pre-filling
"pre_filling_time": self.pre_filling_time_sb,

View File

@ -49,7 +49,7 @@ class Recipe_Selection(Widget):
autocomplete={
"archived": False,
},
widget_classes={"spec": lambda *args, **kwargs: Json_External_Dialog_Editor_Cell_Widget(Recipe_Spec_And_Step_Editor(), *args, **kwargs), },
widget_classes={"spec": lambda *args, **kwargs: Json_External_Dialog_Editor_Cell_Widget(Recipe_Spec_And_Step_Editor, *args, **kwargs), },
)
replace_widget(self, "crud_w", self.crud)
self.crud_modified = None

View File

@ -1,136 +1,139 @@
from lib.db import Steps
from playhouse.shortcuts import model_to_dict
from ui.editor import Editor
from ui.helpers import replace_widget
from ui.leak_step_editor import Leak_Step_Editor
from ui.vision_step_editor import Vision_Step_Editor
class Recipe_Spec_And_Step_Editor(Editor):
def __init__(self):
super().__init__()
# self.spec.update({
# "barcode_editor": self.barcode_editor_w,
# "leak_editor_1": self.leak_editor_1_w,
# "leak_editor_2": self.leak_editor_2_w,
# "vision_editor": self.vision_editor_w,
# "print_editor": self.print_editor_w,
# "barcode_enabled": self.barcode_enabled_cb,
# "leak_enabled_1": self.leak_enabled_1_cb,
# "leak_eabled_2": self.leak_eabled_2_cb,
# "vision_enabled": self.vision_enabled_cb,
# "vision_enabled": self.vision_enabled_cb,
# "print_enabled_cb": self.print_enabled_cb,
# })
# replace_widget(self, "barcode_editor_w", _Editor())
# replace_widget(self, "leak_editor_1_w", _Editor())
# replace_widget(self, "leak_editor_2_w", _Editor())
# replace_widget(self, "vision_editor_w", _Editor())
# replace_widget(self, "print_editor_w", _Editor())
#
# def do_autocomplete(self, autocomplete):
# if autocomplete is None:
# return
# for k, v in autocomplete.items():
# w = self.spec[k]
# if isinstance(w, QCheckBox):
# w.setChecked(bool(v))
# elif isinstance(w, QComboBox):
# # while w.count() > 0:
# # w.removeItem(0)
# # w.clear()
# w.addItems(list(map(str, v)))
# elif isinstance(w, QDoubleSpinBox):
# w.setValue(float(v))
# elif isinstance(w, QLineEdit):
# w.setText(str(v))
# elif isinstance(w, QListWidget):
# # while w.count() > 0:
# # w.takeItem(0)
# # w.clear()
# w.addItems(list(map(str, v)))
# elif isinstance(w, QRadioButton):
# w.setChecked(bool(v))
# elif isinstance(w, QSpinBox):
# w.setValue(int(v))
# elif isinstance(w, QPlainTextEdit):
# w.setPlainText(str(v))
# elif isinstance(w, QObject):
# raise NotImplementedError(f"widget of type {type(w)!r} not implemented")
# else:
# # ignore default values
# pass
#
def __init__(self, cell_widget=None):
super().__init__(cell_widget=cell_widget)
self.map = {
"barcodes": {
"type": "barcodes",
"enable": self.barcode_enabled_cb,
"widget": "barcode_editor_w",
# "editor": _Editor,
},
"leak_1": {
"type": "leak",
"enable": self.leak_enabled_1_cb,
"widget": "leak_editor_1_w",
"editor": Leak_Step_Editor(),
},
"leak_2": {
"type": "leak",
"enable": self.leak_eabled_2_cb,
"widget": "leak_editor_2_w",
"editor": Leak_Step_Editor(),
},
"vision": {
"type": "vision",
"enable": self.vision_enabled_cb,
"widget": "vision_editor_w",
"editor": Vision_Step_Editor(),
},
"print": {
"type": "print",
"enable": self.print_enabled_cb,
"widget": "print_editor_w",
# "editor": _Editor,
},
}
if len(self.map) > 1024:
raise NotImplementedError("self.map must contain at most 1024 steps")
self.spec.update({editor_name: map["enable"] for editor_name, map in self.map.items()})
for editor_name, map in self.map.items():
editor = map.get("editor", None)
if editor is not None:
replace_widget(self, map["widget"], editor)
self.save_steps_b.clicked.connect(self.save_steps)
self.reset_steps_b.clicked.connect(self.reset_steps)
self.recipe_id = None
self.step_editors_autocomplete = {}
def set_readonly(self, readonly=True):
super().set_readonly(readonly=readonly)
for editor_name, map in self.map.items():
editor = map.get("editor", None)
if editor is not None:
editor.set_readonly(readonly=readonly)
self.save_steps_b.setDisabled(readonly)
def do_autocomplete(self, autocomplete):
if autocomplete is None:
return
self.step_editors_autocomplete = autocomplete.pop("step_editors", None)
super().do_autocomplete(autocomplete)
if self.step_editors_autocomplete is not None:
for editor_name, map in self.map.items():
editor = map.get("editor", None)
if editor is not None:
editor.do_autocomplete(self.step_editors_autocomplete.get(editor_name, None))
def init(self):
self.recipe_id = self.cell_widget.crud.data_index[self.cell_widget.row_number - 1] # - 1 because row_number starts from 1 (filters line)
self.get_steps()
def showing_dialog(self):
self.reset_steps()
# def connect_modified(self, check_modified):
# for k, w in self.spec.items():
# if isinstance(w, QCheckBox):
# w.toggled.connect(check_modified)
# elif isinstance(w, QComboBox):
# w.currentTextChanged.connect(check_modified)
# elif isinstance(w, QDoubleSpinBox):
# w.valueChanged.connect(check_modified)
# elif isinstance(w, QLineEdit):
# w.textChanged.connect(check_modified)
# elif isinstance(w, QListWidget):
# w.currentItemChanged.connect(check_modified)
# elif isinstance(w, QRadioButton):
# w.toggled.connect(check_modified)
# elif isinstance(w, QSpinBox):
# w.valueChanged.connect(check_modified)
# elif isinstance(w, QPlainTextEdit):
# w.textChanged.connect(check_modified)
# elif isinstance(w, QObject):
# raise NotImplementedError(f"widget of type {type(w)!r} not implemented")
# else:
# # ignore default values
# pass
#
# def render(self, data, field_name=None, row_number=None, crud=None):
# for k, v in data.items():
# if k not in self.spec:
# continue
# w = self.spec[k]
# if isinstance(w, QCheckBox):
# w.setChecked(bool(v))
# elif isinstance(w, QComboBox):
# w.setCurrentText(str(v))
# elif isinstance(w, QDoubleSpinBox):
# w.setValue(float(v))
# elif isinstance(w, QLineEdit):
# w.setText(str(v))
# elif isinstance(w, QListWidget):
# w.clear()
# w.addItems(list(map(str, v)))
# elif isinstance(w, QRadioButton):
# w.setChecked(bool(v))
# elif isinstance(w, QSpinBox):
# w.setValue(int(v))
# elif isinstance(w, QPlainTextEdit):
# w.setPlainText(str(v))
# elif isinstance(w, QObject):
# raise NotImplementedError(f"widget of type {type(w)!r} not implemented")
# else:
# # ignore default values
# pass
#
# def parse(self, row_number=None, crud=None):
# ret = {}
# for k, w in self.spec.items():
# if isinstance(w, QCheckBox):
# ret[k] = w.isChecked()
# elif isinstance(w, QComboBox):
# ret[k] = w.currentText()
# elif isinstance(w, QDoubleSpinBox):
# ret[k] = w.value()
# elif isinstance(w, QLineEdit):
# ret[k] = w.text()
# elif isinstance(w, QListWidget):
# ret[k] = [w.item(i).data(0) for i in range(w.count())]
# elif isinstance(w, QRadioButton):
# ret[k] = w.isChecked()
# elif isinstance(w, QSpinBox):
# ret[k] = w.value()
# elif isinstance(w, QPlainTextEdit):
# ret[k] = w.toPlainText()
# elif isinstance(w, QObject):
# raise NotImplementedError(f"widget of type {type(w)!r} not implemented")
# else:
# # pass through default values
# ret[k] = w
# return ret
# super().connect_modified(check_modified)
# # for map in self.map.values():
# # editor = map.get("editor", None)
# # if editor is not None:
# # editor.connect_modified(self.check_modified)
def render(self, data, field_name=None, row_number=None, crud=None):
super().render(data, field_name=field_name, row_number=row_number, crud=crud)
steps = set(data.get("steps", set()))
for map in self.map.values():
map["enable"].setChecked(map["step"]["id"] in steps)
def parse(self, row_number=None, crud=None):
ret = super().parse(row_number=row_number, crud=crud)
ret["steps"] = []
for map in self.map.values():
if map["enable"].isChecked():
ret["steps"].append(map["step"]["id"])
return ret
@staticmethod
def get_step_id(recipe_id, step_n):
return recipe_id * 1024 + step_n
def get_steps(self):
for n, [editor_name, map] in enumerate(self.map.items()):
id = self.get_step_id(self.recipe_id, n)
try:
step = model_to_dict(Steps.get_by_id(id))
except Steps.DoesNotExist:
step = {
"id": id,
"type": map["type"],
"spec": {},
}
map["step"] = step
def render_steps(self):
for n, [editor_name, map] in enumerate(self.map.items()):
editor = map.get("editor", None)
step = map["step"]
if editor is not None:
editor.render(step["spec"])
def reset_steps(self):
self.get_steps()
self.render_steps()
def save_steps(self):
steps = []
for map in self.map.values():
editor = map.get("editor", None)
if editor is not None:
map["step"]["spec"] = editor.parse()
steps.append(map["step"])
Steps.replace_many(steps).execute()
self.reset_steps()

View File

@ -6,15 +6,31 @@
<rect>
<x>0</x>
<y>0</y>
<width>247</width>
<height>145</height>
<width>330</width>
<height>163</height>
</rect>
</property>
<property name="windowTitle">
<string>Recipe Spec And Step Editor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<item row="1" column="0">
<widget class="QPushButton" name="save_steps_b">
<property name="text">
<string>Salva configurasione
Fasi di Test</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="reset_steps_b">
<property name="text">
<string>Resetta configurazione
Fasi di Test</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
@ -236,13 +252,6 @@
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="save_b">
<property name="text">
<string>Salva</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -3,15 +3,15 @@ from ui.editor import Editor
class Recipe_Spec_Editor(Editor):
def __init__(self):
super().__init__()
def __init__(self, cell_widget=None):
super().__init__(cell_widget=cell_widget)
self.spec.update({
"steps": self.steps_lw,
})
self.steps_lw.setDragDropMode(QAbstractItemView.InternalMove)
def set_readonly(self, readonly):
super().set_readonly(readonly)
def set_readonly(self, readonly=True):
super().set_readonly(readonly=readonly)
self.steps_lw.setDisabled(readonly)
self.remove_step_b.setDisabled(readonly)
self.steps_available_lw.setDisabled(readonly)

View File

@ -24,6 +24,6 @@ class Recipes_Management(Widget):
autocomplete={
"archived": False,
},
widget_classes={"spec": lambda *args, **kwargs: Json_External_Dialog_Editor_Cell_Widget(Recipe_Spec_Editor(), *args, **kwargs), },
widget_classes={"spec": lambda *args, **kwargs: Json_External_Dialog_Editor_Cell_Widget(Recipe_Spec_Editor, *args, **kwargs), },
)
self.layout().addWidget(self.crud, 0, 0, -1, -1)

View File

@ -1,11 +1,8 @@
from glob import iglob
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QCheckBox, QComboBox, QDoubleSpinBox, QLineEdit,
QPlainTextEdit, QPushButton, QRadioButton,
QSpinBox)
from ui.crud import (Cell, Combo_Box_Cell_Widget, Crud,
Json_External_Dialog_Editor_Cell_Widget)
from PyQt5.QtWidgets import QPushButton
from ui.crud import Cell, Combo_Box_Cell_Widget, Crud
from ui.dialog import Dialog
from ui.leak_step_editor import Leak_Step_Editor
from ui.vision_step_editor import Vision_Step_Editor
@ -15,8 +12,8 @@ from ui.widget import Widget
class Step_Spec_JEDECW(QPushButton, Cell):
def __init__(self, readonly=True, autocomplete=None, field_name=None, field_alias=None, field=None, row_number=None, crud=None):
self.editors = {
"vision": Vision_Step_Editor(),
"leak": Leak_Step_Editor(),
"vision": Vision_Step_Editor(cell_widget=self),
"leak": Leak_Step_Editor(cell_widget=self),
}
self.editor = None
self.editor_type = None
@ -36,9 +33,9 @@ class Step_Spec_JEDECW(QPushButton, Cell):
self.dialog.setCentralWidget(self.editor)
self.dialog.adjustSize()
def set_readonly(self, readonly):
def set_readonly(self, readonly=True):
for editor in self.editors.values():
editor.set_readonly(readonly)
editor.set_readonly(readonly=readonly)
def do_autocomplete(self, autocomplete):
for editor_type, editor in self.editors.items():

View File

@ -38,11 +38,12 @@ class Test(Widget):
self.cycle_available_steps = {
# "assembly_1": Test_Assembly(self.select_step_img("assembly_1"), u"INSERIRE SENSORE"),
"autotest": Test_Assembly(None, u"ESEGUIRE PROCEDURA DI AUTOTEST", Test_Autotest()),
"barcodes": Test_Assembly(None, u"SCANSIONARE IL SERIALE DEL PEZZO DA COLLAUDARE", Test_Barcodes()),
"done": Test_Assembly(self.select_step_img("success"), u"COLLAUDO COMPLETATO - RIMUOVERE IL SENSORE"),
"emergency": Test_Assembly(self.select_step_img("reset_emergency"), u"EMERGENZA INTERVENUTA - RIPRISTINARE PULSANTE E SELEZIONARE \"RESET EMERGENZA\" DAL MEN\u00d9 \"STRUMENTI\""),
"fail": Test_Assembly(self.select_step_img("fail"), u"CICLO INTERROTTO - RIMUOVERE IL SENSORE"),
"leak": Test_Assembly(None, u"ESECUZIONE TEST IN CORSO - ATTENDERE", Test_Leak(components=self.components, recipe=self.recipe, step=self.step)),
"barcodes": Test_Assembly(None, u"SCANSIONARE IL SERIALE DEL PEZZO DA COLLAUDARE", Test_Barcodes()),
"print": Test_Assembly(self.select_step_img("print"), u"STAMPA ETICHETTA IN CORSO"),
"select_recipe": Test_Assembly(None, u"SELEZIONARE IL CODICE DA COLLAUDARE", Recipe_Selection()),
"vision": Test_Assembly(None, u"ESEGUIRE PROCEDURA DI AUTOTEST", Test_Vision(components=self.components, recipe=self.recipe, step=self.step)),
"wait": Test_Assembly(self.select_step_img("wait"), u"ATTENDERE - PAUSA INTER CICLO"),
@ -58,7 +59,8 @@ class Test(Widget):
# else:
self.autotest_period = None
# INIT TEST DATA
self.data = {}
self.data = {"ok": True, "overridden": False}
self.archived = None
# INIT PIECES COUNTER ([pieces_ok, pieces_failed])
self.pieces = [0, 0]
# CONNECT CYCLE CONTROLS
@ -149,7 +151,8 @@ class Test(Widget):
self.step = Steps(type="select_recipe")
self.cycle_index = -1
# RESET TEST DATA
self.data = {}
self.data = {"ok": True, "overridden": False}
self.archived = None
elif action == "fail":
self.log.info(f"cycle next: action: {action!r}")
# COUNT FAIL
@ -158,7 +161,8 @@ class Test(Widget):
self.step = Steps(type="fail")
self.cycle_index = -1
# RESET TEST DATA
self.data = {}
self.data = {"ok": True, "overridden": False}
self.archived = None
elif action is not None:
raise NotImplementedError(f"cycle next: action {action!r} is not a valid action")
# if action did not set the next cycle step
@ -180,6 +184,7 @@ class Test(Widget):
self.step = self.cycle_steps[self.cycle_index]
else:
self.cycle_index = -1
self.archived = None
self.step = Steps(type=None)
# enable/disable cycle controls
self.change_recipe_b.setEnabled(self.recipe is not None)
@ -192,14 +197,18 @@ class Test(Widget):
self.log.info(f"cycle next: next cycle step: {self.step!r}")
# INIT TEST DATA IF STARTING CYCLE LOOP
if self.cycle_index == 0:
self.data = {}
self.data = {"ok": True, "overridden": False}
self.archived = None
w = self.cycle_available_steps[self.step.type]
if hasattr(w, "start"):
w.start(recipe=self.recipe, step=self.cycle_steps[self.cycle_index])
if w is not current_w:
self.setCentralWidget(w)
if self.step.type == "done":
self.done()
self.archived = self.done()
self.next_timer.start(2000)
elif self.step.type == "print":
self.print(self.archived)
self.next_timer.start(2000)
elif self.step.type == "fail":
self.next_timer.start(2000)
@ -213,7 +222,17 @@ class Test(Widget):
if self.recipe is None:
self.cycle_steps = None
else:
self.cycle_steps = [Steps(type="barcodes")] + self.recipe.get_steps() + [Steps(type="done"), Steps(type="wait")]
steps = self.recipe.get_steps()
print_found = False
for i, step in enumerate(steps):
if step.type == "print":
steps.insert(i, Steps(type="done"))
print_found = True
break
if not print_found:
steps.append(Steps(type="done"))
steps.append(Steps(type="wait"))
self.cycle_steps = steps
# UPDATE RECIPE DISPLAY
if self.recipe is not None:
self.recipe_l.setText(self.recipe.name)
@ -233,24 +252,30 @@ class Test(Widget):
if "leak" not in self.data:
self.data["leak"] = []
self.data["leak"].append(leak)
self.data["overridden"] = self.data.get("overridden", False) or leak.get("overridden", False)
self.data["ok"] = self.data.get("ok", True) and leak.get("ok", False)
self.data["overridden"] = self.data["overridden"] or leak.get("overridden", False)
self.data["ok"] = self.data["ok"] and leak.get("ok", False)
self.next()
def set_vision(self, vision=None):
if "vision" not in self.data:
self.data["vision"] = []
self.data["vision"].append(vision)
self.data["overridden"] = self.data.get("overridden", False) or vision.get("overridden", False)
self.data["ok"] = self.data.get("ok", True) and vision.get("ok", False)
self.data["overridden"] = self.data["overridden"] or vision.get("overridden", False)
self.data["ok"] = self.data["ok"] and vision.get("ok", False)
self.next()
def done(self, ok=True):
self.log.info("cycle done")
archived = Archive.archive(self.recipe, self.data, ok and self.data["ok"], overridden=self.data["overridden"])
self.log.info(f"cycle archived locally: {archived!r}")
# COUNT OK
self.pieces[0] += 1
return archived
def print(self, archived=None):
self.log.info("cycle print")
# LABEL PRINT
self.components["label_printer"].print_label("EtichettaR5", context={
context = {
"DATAMATRIX": str(self.data.get("barcodes", {}).get("serial", "")),
"DATAMATRIX_TEXT": str(self.data.get("barcodes", {}).get("serial", "-")),
"PIECE_NUM": str(self.data.get("barcodes", {}).get("serial", "-")),
@ -267,9 +292,8 @@ class Test(Widget):
"TTEST": "-",
"MAXLEAK": "-",
"PTESTMIN": "-",
"RESULT_L1": str(self.data.get("leak", [{}])[0].get("results", {}).get("result", "FAIL")),
"RESULT_L2": str(self.data.get("leak", [{}])[1].get("results", {}).get("result", "FAIL")),
})
self.log.info(f"cycle printed: {archived!r}")
# COUNT OK
self.pieces[0] += 1
"RESULT_L1": str(self.data.get("leak", [{}, {}])[0].get("results", {}).get("result", "FAIL")),
"RESULT_L2": str(self.data.get("leak", [{}, {}])[1].get("results", {}).get("result", "FAIL")),
}
self.components["label_printer"].print_label("EtichettaR5", context=context)
self.log.info(f"cycle printed: {context!r}")

View File

@ -2,8 +2,8 @@ from ui.editor import Editor
class Vision_Step_Editor(Editor):
def __init__(self):
super().__init__()
def __init__(self, cell_widget=None):
super().__init__(cell_widget=cell_widget)
self.spec.update({
"recipe": self.vision_recipe_cb,
})