Merge remote-tracking branch 'origin/master'

This commit is contained in:
germano2239 2022-07-26 16:12:38 +02:00
commit 50908f237f
6 changed files with 79 additions and 120 deletions

View File

@ -59,60 +59,8 @@ 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 recipe
Recipes.replace(
id=0,
name="Ferrari 923578",
@ -122,7 +70,6 @@ Recipes.replace(
description="Tubo plastica doppia biforcazione con termorestringente centrale",
archived=False,
).execute()
Recipes.replace(
id=1,
name="BLOW-BY 5802814210",

View File

@ -7,11 +7,11 @@ from .steps import Steps
class Recipes(BaseModel):
id = AutoField(primary_key=True, unique=True, null=False)
name = TextField(null=False)
client = TextField(null=False)
name = TextField(null=True)
client = TextField(null=True)
part_number = 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)
def get_steps(self):

View File

@ -329,6 +329,20 @@ class Crud(Widget):
self._modified = self._modified or is_modified
self.modified.emit(self._modified)
def parse_row(self, rn, fail=False):
r = {}
fails = []
for fn, cn in self.select_index.items():
w = self.db_tw.cellWidget(rn, cn)
try:
r[fn] = w._parse(row_number=rn, crud=self)
except Exception as e:
self.log.exception(traceback.format_exc())
self.set_row_color(rn, "red")
fail = True
fails.append(str(e))
return r, fail, fails
def refresh(self, action=None, page=0):
# IGNORE SIGNALS WHILE UPDATING
self.db_tw.blockSignals(True)
@ -340,12 +354,6 @@ class Crud(Widget):
self.db_tw.setColumnCount(len(self.select))
self.db_tw.setHorizontalHeaderLabels(self.fields_aliases.values())
self.db_tw.setRowCount(1)
self.db_tw.setColumnWidth(0, 25)
self.db_tw.setColumnWidth(1, 200)
self.db_tw.setColumnWidth(2, 200)
self.db_tw.setColumnWidth(3, 200)
self.db_tw.setColumnWidth(4, 200)
self.db_tw.setColumnWidth(5, 400)
if self.readonly is None or self.readonly is True:
self.db_tw.verticalHeader().setHidden(True)
else:
@ -368,16 +376,8 @@ class Crud(Widget):
fails = []
data = []
for rn in range(1, self.db_tw.rowCount()): # start=1 because rn starts from 1 (filters line)
r = {}
for fn, cn in self.select_index.items():
w = self.db_tw.cellWidget(rn, cn)
try:
r[fn] = w._parse(row_number=rn, crud=self)
except Exception as e:
self.log.exception(traceback.format_exc())
self.set_row_color(rn, "red")
fail = True
fails.append(str(e))
r, fail, r_fails = self.parse_row(rn, fail=fail)
fails += r_fails
add_row, r, filter_fail = self.row_filter(r, rn, self)
if filter_fail:
fail = True
@ -436,6 +436,7 @@ class Crud(Widget):
self.db_tw.setCellWidget(rn, cn, w)
# REENABLE EVENTS AFTER UPDATE
self.db_tw.blockSignals(False)
self.show_selection()
return True
def cancel(self):

View File

@ -1,4 +1,5 @@
import sys
from glob import iglob
from lib.db import Recipes, Users
from PyQt5.QtCore import QTimer, pyqtSignal
@ -47,6 +48,14 @@ class Recipe_Selection(Widget):
filters=filters,
fields_aliases=crud_aliases,
autocomplete={
"spec": {
"step_editors": {
"vision": {
# "recipe": iglob("*.ini", root_dir="./config/vision/recipes/"), # only in python3.10
"recipe": list(iglob("./config/vision/recipes/*.ini")),
},
},
},
"archived": False,
},
widget_classes={"spec": lambda *args, **kwargs: Json_External_Dialog_Editor_Cell_Widget(Recipe_Spec_And_Step_Editor, *args, **kwargs), },
@ -60,6 +69,12 @@ class Recipe_Selection(Widget):
self.crud.modified.connect(self.check_modified)
self.crud.selected.connect(self.check_selected)
self.crud.emit()
self.crud.db_tw.setColumnWidth(0, 25)
self.crud.db_tw.setColumnWidth(1, 200)
self.crud.db_tw.setColumnWidth(2, 200)
self.crud.db_tw.setColumnWidth(3, 200)
self.crud.db_tw.setColumnWidth(4, 200)
self.crud.db_tw.setColumnWidth(5, 400)
# TESTING
if "--auto-select" in sys.argv or "--test" in sys.argv:
drawing = "TEST"
@ -79,13 +94,13 @@ class Recipe_Selection(Widget):
self.crud_modified = modified
self.check(self.crud_modified, self.selected)
def check_selected(self, selected):
if len(selected) == 1:
def check_selected(self, selected=None):
if selected is not None and len(selected) == 1:
selected = selected[0] - 1 # - 1 because rn starts from 1 (filters line)
if selected >= 0 and selected < len(self.crud.data_index):
selected = self.crud.data_index[selected]
if selected is not None:
self.selected = self.crud.db.table_model.get_by_id(selected)
self.selected = selected
else:
self.selected = None
else:
@ -97,4 +112,4 @@ class Recipe_Selection(Widget):
def select(self):
if self.selected is not None:
self.ok.emit(self.selected)
self.ok.emit(self.crud.db.table_model.get_by_id(self.selected))

View File

@ -1,4 +1,4 @@
from lib.db import Steps
from lib.db import Recipes, Steps
from playhouse.shortcuts import model_to_dict
from ui.editor import Editor
from ui.helpers import replace_widget
@ -41,21 +41,18 @@ class Recipe_Spec_And_Step_Editor(Editor):
# "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():
self.spec.update({step_name: map["enable"] for step_name, map in self.map.items()})
for map in self.map.values():
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():
for map in self.map.values():
editor = map.get("editor", None)
if editor is not None:
editor.set_readonly(readonly=readonly)
@ -64,16 +61,15 @@ class Recipe_Spec_And_Step_Editor(Editor):
def do_autocomplete(self, autocomplete):
if autocomplete is None:
return
self.step_editors_autocomplete = autocomplete.pop("step_editors", None)
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():
if step_editors_autocomplete is not None:
for step_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))
editor.do_autocomplete(step_editors_autocomplete.get(step_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):
@ -88,52 +84,51 @@ class Recipe_Spec_And_Step_Editor(Editor):
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)
self.get_steps(available_steps=data.get("available_steps", {}))
steps = set(data.get("steps", set()))
for map in self.map.values():
map["enable"].setChecked(map["step"]["id"] in steps)
step = map.get("step", None)
if step is not None:
map["enable"].setChecked(step.id in steps)
self.render_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():
ret["available_steps"] = {}
for step_name, map in self.map.items():
ret["available_steps"][step_name] = map["step"].id
if map["enable"].isChecked():
ret["steps"].append(map["step"]["id"])
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 get_steps(self, available_steps=None):
if available_steps is None:
available_steps = {}
for step_name, map in self.map.items():
if step_name in available_steps:
map["step"] = Steps.get_by_id(available_steps[step_name])
elif map.get("step", None) is None:
map["step"] = Steps(type=map["type"], spec={})
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"])
for step_name, map in self.map.items():
step = map.get("step", None)
if step is not None:
editor = map.get("editor", None)
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()
step = map.get("step", None)
if step is not None:
editor = map.get("editor", None)
if editor is not None:
step.spec = editor.parse()
step.save()
self.reset_steps()

View File

@ -17,6 +17,7 @@ class Test_Barcodes(Test_Test):
def start(self, recipe=None, step=None):
super().start(recipe=recipe, step=step)
self.barcodes = {}
self.visualize()
self.barcodes_le.setPalette(self.status_palettes[None])
self.barcodes_le.setText("")
self.barcodes_le.setFocus()