add support for dynamic printer selection and template resolution in label printing modules
This commit is contained in:
parent
eac50a9ec8
commit
2f423f4281
|
|
@ -9,6 +9,7 @@ archive_synchronizer: present
|
|||
galaxy_camera: absent
|
||||
uvc_camera: absent
|
||||
label_printer: present
|
||||
label_printer_2: present
|
||||
neo_pixels: absent
|
||||
remote_api: absent
|
||||
tecna_t3: present
|
||||
|
|
@ -45,9 +46,14 @@ description_field: descrizione
|
|||
|
||||
[label_printer]
|
||||
platform: linux
|
||||
printer: ZTC-ZD421-300dpi-ZPL-2
|
||||
printer: ZTC-ZD421-300dpi-ZPL
|
||||
risoluzione: 300
|
||||
|
||||
[label_printer_2]
|
||||
platform: linux
|
||||
printer: ZTC-ZD421-203dpi-ZPL
|
||||
risoluzione: 203
|
||||
|
||||
[recipes_defaults]
|
||||
tester_discharge_enable: yes
|
||||
codice_ricetta: specificare ricetta
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class Os_Label_Printer(Component):
|
|||
self.simulate = True
|
||||
|
||||
def config_changed(self):
|
||||
self.platform = self.config[self.name]["platform"]
|
||||
cfg = self.config.get(self.name, {})
|
||||
self.platform = cfg.get("platform", platform.system().lower())
|
||||
# for windows:
|
||||
# cmd
|
||||
# wmic printer list brief
|
||||
|
|
@ -28,33 +29,35 @@ class Os_Label_Printer(Component):
|
|||
# Get-Printer
|
||||
# for cups (linux, osx)
|
||||
# lpstat -p -d
|
||||
self.printer = self.config[self.name]["printer"]
|
||||
# read only the 'printer' key from this section
|
||||
self.printer = cfg.get("printer", "")
|
||||
|
||||
@Component.reconfig_on_error
|
||||
def print_label(self, template, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if self.config["label_printer"]["risoluzione"] == "300":
|
||||
custom_label_folder=f"config/label_templates/{str(self.config.machine_id)}/300/"
|
||||
standard_label_folder=f"config/label_templates/300/"
|
||||
elif self.config["label_printer"]["risoluzione"]== "203":
|
||||
# Use section resolution only
|
||||
cfg = self.config.get(self.name, {})
|
||||
try:
|
||||
res = int(str(cfg.get("risoluzione", "300")).strip())
|
||||
except Exception:
|
||||
res = 300
|
||||
# Resolve folders per inferred resolution
|
||||
if res == 300:
|
||||
custom_label_folder = f"config/label_templates/{str(self.config.machine_id)}/300/"
|
||||
standard_label_folder = f"config/label_templates/300/"
|
||||
else:
|
||||
custom_label_folder = f"config/label_templates/{str(self.config.machine_id)}/203/"
|
||||
standard_label_folder = f"config/label_templates/203/"
|
||||
|
||||
if os.path.exists(custom_label_folder):
|
||||
label_folder = custom_label_folder
|
||||
else:
|
||||
label_folder = standard_label_folder
|
||||
label_path = label_folder+str(template)
|
||||
if os.path.exists(label_path):
|
||||
pass
|
||||
else:
|
||||
label_path = standard_label_folder+str(template)
|
||||
label_folder = custom_label_folder if os.path.exists(custom_label_folder) else standard_label_folder
|
||||
label_path = label_folder + str(template)
|
||||
if not os.path.exists(label_path):
|
||||
label_path = standard_label_folder + str(template)
|
||||
# LOAD LABEL TEMPLATE
|
||||
with open(label_path, "r", errors="surrogateescape", encoding='iso-8859-1') as f:
|
||||
label_file_contents = f.read()
|
||||
# LABEL PRINT
|
||||
#label = label.format(**context)
|
||||
# Replace placeholders with context values
|
||||
for key, val in context.items():
|
||||
key = "{" + key + "}"
|
||||
label_file_contents = label_file_contents.replace(key, val)
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ def read_steps(row, config, defaults=None, unsupported_steps=None):
|
|||
"labeltxt_5": row.get("barcode_input_finelinea", ""),
|
||||
"extra_label": row.get("etichette_supplementari", ""),
|
||||
"barcode": row.get("barcode_stampato",defaults["barcode_format"]),
|
||||
"printer_selection": row.get("printer_selection", config.get("label_printer", {}).get("printer", "")),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ try:
|
|||
"pipe_cutter": {"c": PipeCutterComponent, "k": {"paused": False}},
|
||||
"label_printer": {"c": Os_Label_Printer, "t": False},
|
||||
"extra_label_printer": {"c": Os_Label_Printer, "t": False},
|
||||
"label_printer_2": {"c": BrotherLabelPrinter, "t": False},
|
||||
"label_printer_2": {"c": Os_Label_Printer, "t": False},
|
||||
"multicomp": {"c": Multicomp730424, "k": {"paused": True}},
|
||||
"remote_api": {"c": RemoteAPI, "k": {"main": self}},
|
||||
"screwdriver": {"c": TecnaScrewdriver, "k": {"paused": True}},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ from ui.editor import Editor
|
|||
class Print_Step_Editor(Editor):
|
||||
def __init__(self, action=None, cell_widget=None):
|
||||
super().__init__(action=action, cell_widget=cell_widget)
|
||||
self._templates_203 = []
|
||||
self._templates_300 = []
|
||||
self._printers_resolution = {}
|
||||
self.spec.update({
|
||||
"printer_selection": self.printer_selection,
|
||||
"template": self.label_template_cb,
|
||||
"labeltxt_1": self.labeltxt_1,
|
||||
"labeltxt_2": self.labeltxt_2,
|
||||
|
|
@ -14,3 +18,50 @@ class Print_Step_Editor(Editor):
|
|||
"extra_label": self.extra_label,
|
||||
"barcode": self.barcode,
|
||||
})
|
||||
# Update templates on printer change
|
||||
try:
|
||||
self.printer_selection.currentTextChanged.connect(self._on_printer_changed)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def do_autocomplete(self, autocomplete):
|
||||
# Grab templates lists if provided for dynamic switching
|
||||
if autocomplete is None:
|
||||
return
|
||||
self._templates_203 = list(map(str, autocomplete.get("templates_203", [])))
|
||||
self._templates_300 = list(map(str, autocomplete.get("templates_300", [])))
|
||||
self._printers_resolution = dict(autocomplete.get("printers_resolution", {}))
|
||||
super().do_autocomplete(autocomplete)
|
||||
# After filling combos, ensure templates shown match current printer
|
||||
self._on_printer_changed(self.printer_selection.currentText())
|
||||
|
||||
def render(self, data, field_name=None, row_number=None, crud=None):
|
||||
# Preserve current template choice from data then adjust list for selected printer
|
||||
current_template = data.get("template", None)
|
||||
super().render(data, field_name=field_name, row_number=row_number, crud=crud)
|
||||
# Re-apply templates list based on printer and restore selection
|
||||
self._on_printer_changed(self.printer_selection.currentText(), initial_template=current_template)
|
||||
|
||||
def _on_printer_changed(self, printer_name, initial_template=None):
|
||||
# If no mapping for this printer, keep current list (use machine's default)
|
||||
if not printer_name or printer_name not in self._printers_resolution:
|
||||
return
|
||||
# Decide resolution from mapping provided by recipe_selection
|
||||
try:
|
||||
res = int(self._printers_resolution.get(printer_name, 300))
|
||||
except Exception:
|
||||
res = 300
|
||||
# Build the list accordingly
|
||||
new_items = self._templates_300 if res == 300 else self._templates_203
|
||||
# If no lists provided, leave as-is
|
||||
if not new_items:
|
||||
return
|
||||
# Preserve current selection
|
||||
prev = initial_template if initial_template is not None else self.label_template_cb.currentText()
|
||||
self.label_template_cb.blockSignals(True)
|
||||
self.label_template_cb.clear()
|
||||
self.label_template_cb.addItems(list(map(str, new_items)))
|
||||
# Restore previous selection if present in new list
|
||||
if prev in new_items:
|
||||
self.label_template_cb.setCurrentText(prev)
|
||||
self.label_template_cb.blockSignals(False)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<height>332</height>
|
||||
<height>426</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -37,45 +37,17 @@
|
|||
<string>Etichetta</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Modello</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="label_template_cb"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>Campo testo 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Campo testo 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>Campo testo 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>Campo testo 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="labeltxt_1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -85,7 +57,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Campo testo 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="labeltxt_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -95,7 +74,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>Campo testo 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="labeltxt_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -105,7 +91,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>Campo testo 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="labeltxt_4">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -115,7 +108,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_35">
|
||||
<property name="text">
|
||||
<string>Campo testo 5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="labeltxt_5">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -125,21 +125,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_35">
|
||||
<property name="text">
|
||||
<string>Campo testo 5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Etichette supplementari</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="extra_label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
@ -149,17 +142,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Formato barcode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="barcode"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
|
@ -177,42 +170,21 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>{PART}: Codice Ricetta selezionata</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>{SN5}:Numero incrementale di 5 cifre</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>{MO}:Mese espresso con 2 cifre </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>{YY}:Anno espresso con 2 cifre</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>{DD}:Giorno espresso con 2 cifre</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
|
@ -226,6 +198,44 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>{MO}:Mese espresso con 2 cifre </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>{YY}:Anno espresso con 2 cifre</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>{DD}:Giorno espresso con 2 cifre</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Modello</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Stampante</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="printer_selection"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -74,6 +74,40 @@ class Recipe_Selection(Widget):
|
|||
else:
|
||||
label_folder = standard_label_folder
|
||||
|
||||
# Build both 203 and 300 template lists for dynamic switching in the editor
|
||||
# Machine-specific overrides if available
|
||||
custom_203 = f"config/label_templates/{str(self.config.machine_id)}/203/"
|
||||
custom_300 = f"config/label_templates/{str(self.config.machine_id)}/300/"
|
||||
std_203 = "config/label_templates/203/"
|
||||
std_300 = "config/label_templates/300/"
|
||||
label_folder_203 = custom_203 if os.path.exists(custom_203) else std_203
|
||||
label_folder_300 = custom_300 if os.path.exists(custom_300) else std_300
|
||||
templates_203 = sorted(map(os.path.basename, glob(f"{label_folder_203}*.prn")))
|
||||
templates_300 = sorted(map(os.path.basename, glob(f"{label_folder_300}*.prn")))
|
||||
|
||||
# Available printers from both sections (only 'printer' key) and mapping to resolution
|
||||
lp1 = self.config.get("label_printer", {})
|
||||
lp2 = self.config.get("label_printer_2", {})
|
||||
lp1_p = lp1.get("printer", "")
|
||||
lp2_p = lp2.get("printer", "")
|
||||
printers_list = []
|
||||
seen = set()
|
||||
for p in [lp1_p, lp2_p]:
|
||||
if p and p not in seen:
|
||||
seen.add(p)
|
||||
printers_list.append(p)
|
||||
printers_resolution = {}
|
||||
if lp1_p:
|
||||
try:
|
||||
printers_resolution[lp1_p] = int(str(lp1.get("risoluzione", "300")).strip())
|
||||
except Exception:
|
||||
printers_resolution[lp1_p] = 300
|
||||
if lp2_p:
|
||||
try:
|
||||
printers_resolution[lp2_p] = int(str(lp2.get("risoluzione", "300")).strip())
|
||||
except Exception:
|
||||
printers_resolution[lp2_p] = 300
|
||||
|
||||
step_defaults.update({
|
||||
"vision": {
|
||||
# "recipe": sorted(glob("*.ini", root_dir="./config/vision/recipes/")), # only in python3.10
|
||||
|
|
@ -82,6 +116,10 @@ class Recipe_Selection(Widget):
|
|||
"print": {
|
||||
# "template": sorted(glob("*.prn", root_dir="./config/label_templates/")), # only in python3.10
|
||||
"template": sorted(map(os.path.basename, glob(f"{label_folder}*.prn"))),
|
||||
"templates_203": templates_203,
|
||||
"templates_300": templates_300,
|
||||
"printer_selection": printers_list,
|
||||
"printers_resolution": printers_resolution,
|
||||
},
|
||||
}),
|
||||
self.crud = Crud(
|
||||
|
|
@ -329,6 +367,7 @@ class Recipe_Selection(Widget):
|
|||
"labeltxt_4": row.get("testo_etich_4", ""),
|
||||
"labeltxt_5": row.get("barcode_input_finelinea", ""),
|
||||
"extra_label": row.get("etichette_supplementari", ""),
|
||||
"printer_selection": row.get("printer_selection", self.config.get("label_printer", {}).get("printer", "")),
|
||||
|
||||
},
|
||||
}
|
||||
|
|
@ -486,6 +525,7 @@ class Recipe_Selection(Widget):
|
|||
"labeltxt_3": steps.get("print", Step()).spec.get("labeltxt_3", ""),
|
||||
"labeltxt_4": steps.get("print", Step()).spec.get("labeltxt_4", ""),
|
||||
"labeltxt_5": steps.get("print", Step()).spec.get("labeltxt_5", ""),
|
||||
"printer_selection": steps.get("print",Step()).spec.get("printer_selection",""),
|
||||
}
|
||||
data.append(exportable)
|
||||
if len(data):
|
||||
|
|
|
|||
|
|
@ -992,10 +992,19 @@ class Test(Widget):
|
|||
context[field.upper()] = printer_fields[field]
|
||||
|
||||
# PRINT MAIN PRODUCT LABEL
|
||||
if self.config["hardware_config"]["tecna_t3"] == "absent" and self.config["hardware_config"]["furness_controls"] == "absent":
|
||||
compiled_label = self.components["label_printer_2"].print_label(barcode) # Printing with Brother label printer
|
||||
else:
|
||||
compiled_label = self.components["label_printer"].print_label(label, context=context)
|
||||
# Determine which OS label printer to use based on per-recipe selection
|
||||
selected_printer = printer_fields.get("printer_selection", "")
|
||||
lp2_cfg = self.config.get("label_printer_2", {})
|
||||
lp2_printer = lp2_cfg.get("printer", "")
|
||||
use_comp_name = "label_printer_2" if selected_printer and lp2_printer and selected_printer == lp2_printer else "label_printer"
|
||||
comp = self.components.get(use_comp_name) or self.components.get("label_printer") or self.components.get("label_printer_2")
|
||||
# Set the target device name to selected printer if provided
|
||||
if selected_printer:
|
||||
try:
|
||||
comp.printer = selected_printer
|
||||
except Exception:
|
||||
pass
|
||||
compiled_label = comp.print_label(label, context=context)
|
||||
self.log.info(f"Main label printed: {context!r}")
|
||||
# return fields used to print label for saving into test archive
|
||||
return context
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user