wip
This commit is contained in:
parent
af61cbb6f9
commit
408a1e466f
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
BIN
src/ui/imgs/print.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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/>
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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():
|
||||
|
||||
@ -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}")
|
||||
|
||||
@ -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,
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user