From 408a1e466f78ee7973b89ef483b78d6ca9abdcdc Mon Sep 17 00:00:00 2001 From: matteo porta Date: Tue, 26 Jul 2022 12:24:53 +0200 Subject: [PATCH] wip --- src/lib/db/__init__.py | 108 +++---- src/lib/db/models/steps.py | 4 +- src/ui/crud/crud.py | 44 ++- src/ui/editor/editor.py | 7 +- src/ui/imgs/print.png | Bin 0 -> 11029 bytes src/ui/leak_step_editor/leak_step_editor.py | 4 +- src/ui/recipe_selection/recipe_selection.py | 2 +- .../recipe_spec_and_step_editor.py | 263 +++++++++--------- .../recipe_spec_and_step_editor.ui | 29 +- .../recipe_spec_editor/recipe_spec_editor.py | 8 +- .../recipes_management/recipes_management.py | 2 +- src/ui/steps_management/steps_management.py | 15 +- src/ui/test/test.py | 60 ++-- .../vision_step_editor/vision_step_editor.py | 4 +- 14 files changed, 300 insertions(+), 250 deletions(-) create mode 100644 src/ui/imgs/print.png diff --git a/src/lib/db/__init__.py b/src/lib/db/__init__.py index 9bf0cd9..d8f0a4f 100644 --- a/src/lib/db/__init__.py +++ b/src/lib/db/__init__.py @@ -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() diff --git a/src/lib/db/models/steps.py b/src/lib/db/models/steps.py index 7c73d87..3417dc6 100644 --- a/src/lib/db/models/steps.py +++ b/src/lib/db/models/steps.py @@ -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 diff --git a/src/ui/crud/crud.py b/src/ui/crud/crud.py index 78a2db4..c831ad7 100755 --- a/src/ui/crud/crud.py +++ b/src/ui/crud/crud.py @@ -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() diff --git a/src/ui/editor/editor.py b/src/ui/editor/editor.py index 2cf9d30..38973f8 100644 --- a/src/ui/editor/editor.py +++ b/src/ui/editor/editor.py @@ -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) diff --git a/src/ui/imgs/print.png b/src/ui/imgs/print.png new file mode 100644 index 0000000000000000000000000000000000000000..52b2a72f7cadb64bb7019b409273bd2ae5a93a0b GIT binary patch literal 11029 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 daC&ivX71iMcj5>uxcCY|Hx<<7^RJsf_ 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() diff --git a/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.ui b/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.ui index 2710a3f..30efe43 100644 --- a/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.ui +++ b/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.ui @@ -6,15 +6,31 @@ 0 0 - 247 - 145 + 330 + 163 Recipe Spec And Step Editor - + + + + Salva configurasione +Fasi di Test + + + + + + + Resetta configurazione +Fasi di Test + + + + 0 @@ -236,13 +252,6 @@ - - - - Salva - - - diff --git a/src/ui/recipe_spec_editor/recipe_spec_editor.py b/src/ui/recipe_spec_editor/recipe_spec_editor.py index 3f6291d..6a14dad 100644 --- a/src/ui/recipe_spec_editor/recipe_spec_editor.py +++ b/src/ui/recipe_spec_editor/recipe_spec_editor.py @@ -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) diff --git a/src/ui/recipes_management/recipes_management.py b/src/ui/recipes_management/recipes_management.py index 1452cd8..c0b1b3f 100644 --- a/src/ui/recipes_management/recipes_management.py +++ b/src/ui/recipes_management/recipes_management.py @@ -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) diff --git a/src/ui/steps_management/steps_management.py b/src/ui/steps_management/steps_management.py index 486b251..4a5735a 100644 --- a/src/ui/steps_management/steps_management.py +++ b/src/ui/steps_management/steps_management.py @@ -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(): diff --git a/src/ui/test/test.py b/src/ui/test/test.py index 4d23191..297d699 100755 --- a/src/ui/test/test.py +++ b/src/ui/test/test.py @@ -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}") diff --git a/src/ui/vision_step_editor/vision_step_editor.py b/src/ui/vision_step_editor/vision_step_editor.py index 20c2c9e..5dbaf32 100644 --- a/src/ui/vision_step_editor/vision_step_editor.py +++ b/src/ui/vision_step_editor/vision_step_editor.py @@ -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, })