Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
774948345e
195
config/instruction_images/st-ten-13/670054812.svg
Normal file
195
config/instruction_images/st-ten-13/670054812.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 464 KiB |
|
|
@ -66,7 +66,7 @@ istruzione_abilitata: x
|
|||
numero nastri (n):0
|
||||
numero sensori anello (sa):0
|
||||
numero sensori presenza (sp):0
|
||||
|
||||
istruzione_abilitata_extra:
|
||||
prova_tenuta_abilitata: x
|
||||
tempo_pre_riempimento: 0
|
||||
pressione_pre_riempimento: 5000
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
from peewee import TextField
|
||||
import time
|
||||
import logging
|
||||
from peewee import TextField, OperationalError
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
|
||||
from . import db, models_reference
|
||||
|
|
@ -18,6 +20,33 @@ class Crud_DB:
|
|||
for column_name, filter in filters.items():
|
||||
self.filter(column_name, filter, filter_storage=self.default_filters)
|
||||
|
||||
def _execute_with_retry(self, func, max_retries=8, base_delay=0.1):
|
||||
"""Execute a DB operation with retry on transient SQLite 'database is locked' errors."""
|
||||
last_exc = None
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return func()
|
||||
except OperationalError as e:
|
||||
msg = str(e).lower()
|
||||
if "database is locked" in msg or "database is busy" in msg:
|
||||
delay = min(base_delay * (2 ** attempt), 1.5)
|
||||
try:
|
||||
logging.getLogger(__name__).warning(
|
||||
f"SQLite busy/locked, retrying commit (attempt {attempt + 1}/{max_retries}) after {delay:.2f}s"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(delay)
|
||||
last_exc = e
|
||||
continue
|
||||
# Not a transient lock error: re-raise immediately
|
||||
raise
|
||||
# Exhausted retries
|
||||
if last_exc is not None:
|
||||
raise last_exc
|
||||
# Fallback if no exception captured (should not happen)
|
||||
return func()
|
||||
|
||||
@db.connection_context()
|
||||
@db.atomic()
|
||||
def commit(self, data, deleted_rows=None):
|
||||
|
|
@ -25,7 +54,7 @@ class Crud_DB:
|
|||
if hasattr(self.table_model, "crud_delete"):
|
||||
deleted = self.table_model.crud_delete(deleted_rows)
|
||||
else:
|
||||
deleted = self.table_model.delete().where(self.table_pk << deleted_rows).execute()
|
||||
deleted = self._execute_with_retry(lambda: self.table_model.delete().where(self.table_pk << deleted_rows).execute())
|
||||
if deleted != len(deleted_rows):
|
||||
raise AssertionError(f"deleted {deleted} rows instead of the expected {len(deleted_rows)}")
|
||||
# SQLITE DOES NOT SUPPORT UPDATE, ONLY REPLACE
|
||||
|
|
@ -42,7 +71,7 @@ class Crud_DB:
|
|||
if hasattr(self.table_model, "crud_update"):
|
||||
self.table_model.crud_update(complete_data)
|
||||
else:
|
||||
self.table_model.insert_many(complete_data).on_conflict_replace().execute()
|
||||
self._execute_with_retry(lambda: self.table_model.insert_many(complete_data).on_conflict_replace().execute())
|
||||
|
||||
def revert(self):
|
||||
self.sorting.clear()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import csv
|
|||
import locale
|
||||
from datetime import datetime
|
||||
import shutil
|
||||
import re
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
from PyQt5.QtWidgets import QFileDialog
|
||||
|
|
@ -248,8 +249,7 @@ def import_recipes(config, csv_path=None, defaults=None, unsupported_steps=None,
|
|||
"instruction": len(
|
||||
row.get("istruzione_abilitata", defaults["istruzione_abilitata"])) and "instruction" not in (
|
||||
unsupported_steps or []),
|
||||
"instruction_extra": len(row.get("istruzione_abilitata_extra", defaults[
|
||||
"istruzione_abilitata_extra"])) and "instruction_extra" not in (unsupported_steps or []),
|
||||
"instruction_extra": (str(row.get("istruzione_abilitata_extra", defaults["istruzione_abilitata_extra"])) or "").strip().lower() == "x" and "instruction_extra" not in (unsupported_steps or []),
|
||||
"pipe_cutter": len(row.get("tagliatubi", defaults["tagliatubi"])) and "pipe_cutter" not in (unsupported_steps or []),
|
||||
"vision": len(
|
||||
row.get("test_visione_abilitato", defaults["test_visione_abilitato"])) and "vision" not in (
|
||||
|
|
@ -376,7 +376,7 @@ def export_recipes(config, csv_path=None, logger=None):
|
|||
"pid_pressure_correction": steps["leak_1"].spec["pid_pressure_correction"],
|
||||
})
|
||||
fieldnames.update(["prova_tenuta_abilitata", "tempo_pre_riempimento", "pressione_pre_riempimento",
|
||||
"tempo_di_test", "pressione_di_test"])
|
||||
"tempo_di_test", "pressione_di_test", "pid_pressure_correction"])
|
||||
|
||||
if "leak_2" in steps:
|
||||
exportable.update({
|
||||
|
|
@ -388,7 +388,7 @@ def export_recipes(config, csv_path=None, logger=None):
|
|||
"pid_pressure_correction": steps["leak_1"].spec["pid_pressure_correction"],
|
||||
})
|
||||
fieldnames.update(["prova_tenuta_abilitata_2", "tempo_pre_riempimento_2", "pressione_pre_riempimento_2",
|
||||
"tempo_di_test_2", "pressione_di_test_2"])
|
||||
"tempo_di_test_2", "pressione_di_test_2", "pid_pressure_correction"])
|
||||
|
||||
if "vision" in steps:
|
||||
exportable.update({
|
||||
|
|
@ -430,21 +430,36 @@ def export_recipes(config, csv_path=None, logger=None):
|
|||
|
||||
def backup_current_recipes(config, logger=None):
|
||||
"""
|
||||
Back up current recipes to a timestamped CSV file in the predefined backup directory.
|
||||
Back up current recipes to a CSV file named after the current machine description.
|
||||
Only one backup file is kept (overwritten on each call).
|
||||
"""
|
||||
# Define the backup directory and file name
|
||||
# Define the backup directory
|
||||
backup_dir = os.path.join('config', 'csv_import', 'backup_csv')
|
||||
timestamp = datetime.now().strftime("%d%m%y%H%M%S")
|
||||
backup_file = f"backup_{timestamp}.csv"
|
||||
|
||||
# Read machine description from config
|
||||
try:
|
||||
machine_desc = (config.get('machine', {}) or {}).get('description')
|
||||
if not machine_desc:
|
||||
# Fallbacks
|
||||
machine_desc = getattr(config, 'machine_id', None) or 'backup_recipes'
|
||||
except Exception:
|
||||
machine_desc = getattr(config, 'machine_id', None) or 'backup_recipes'
|
||||
|
||||
# Sanitize description to create a safe filename
|
||||
safe_desc = re.sub(r"[^A-Za-z0-9._-]+", "_", str(machine_desc).strip())
|
||||
if not safe_desc:
|
||||
safe_desc = 'backup_recipes'
|
||||
|
||||
# Build backup file path (no timestamp => single rotating file)
|
||||
backup_file = f"{safe_desc}.csv"
|
||||
backup_path = os.path.join(backup_dir, backup_file)
|
||||
|
||||
# Ensure the backup directory exists
|
||||
os.makedirs(backup_dir, exist_ok=True)
|
||||
|
||||
# Export current recipes to the backup path
|
||||
export_recipes(config=config, csv_path=backup_path, logger=logger)
|
||||
|
||||
if logger:
|
||||
logger.info(f"Backup created at: {backup_path}")
|
||||
# Export current recipes to the backup path (overwrites existing file)
|
||||
# Suppress internal export logs during automatic backup
|
||||
export_recipes(config=config, csv_path=backup_path, logger=None)
|
||||
|
||||
# Do not log here to avoid duplicate messages; caller will handle final log
|
||||
return backup_path # Return the backup path for reference if needed
|
||||
|
|
|
|||
26
src/main.py
26
src/main.py
|
|
@ -3,6 +3,9 @@ import argparse
|
|||
import faulthandler
|
||||
import logging
|
||||
import os
|
||||
|
||||
from src.lib.helpers.recipe_manager import backup_current_recipes
|
||||
|
||||
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION']="python"
|
||||
import platform
|
||||
import signal
|
||||
|
|
@ -77,7 +80,7 @@ try:
|
|||
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox, QInputDialog, QLineEdit
|
||||
import sip
|
||||
from ui import About, Archive, Login, Main_Window, Test, Users_Management,Logs_Management ,Recipe_Selection, \
|
||||
from ui import About, Archive, Login, Main_Window, Test, Users_Management, Logs_Management, Recipes_Management , Recipe_Selection, \
|
||||
Barcode_Recipe_Selection, LastCommit
|
||||
|
||||
if "--vision" in sys.argv:
|
||||
|
|
@ -215,6 +218,7 @@ try:
|
|||
self.main_window.barcode_selection_a.triggered.connect(self.set_recipe_mode_barcode)
|
||||
self.main_window.ristampa_etichetta_a.triggered.connect(self.reprint_label)
|
||||
self.main_window.tag_a.triggered.connect(self.tag_write)
|
||||
self.main_window.recipes_export_a.triggered.connect(self.trigger_recipe_backup)
|
||||
if "pipe_cutter" in self.components.keys():
|
||||
self.main_window.cut_a.setVisible(True)
|
||||
self.main_window.cut_a.triggered.connect(self.cut_tube)
|
||||
|
|
@ -496,6 +500,26 @@ try:
|
|||
def load_recipe_from_rfid(self, data):
|
||||
self.tag_loaded_recipe = data
|
||||
|
||||
def trigger_recipe_backup(self):
|
||||
"""
|
||||
This method acts as a bridge to call the imported backup function.
|
||||
"""
|
||||
try:
|
||||
# Use the imported function and pass the required objects
|
||||
backup_current_recipes(config=self.config, logger=logging)
|
||||
QMessageBox.information(
|
||||
self.main_window,
|
||||
"Esportazione Riuscita",
|
||||
"Backup delle ricette creato con successo."
|
||||
)
|
||||
except Exception as e:
|
||||
logging.exception("Error during recipe backup")
|
||||
QMessageBox.critical(
|
||||
self.main_window,
|
||||
"Errore di Esportazione",
|
||||
f"Si è verificato un errore durante il salvataggio: {e}"
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,7 @@ class Json_External_Dialog_Editor_Cell_Widget(QPushButton, Cell):
|
|||
class Crud(Widget):
|
||||
modified = pyqtSignal(bool)
|
||||
selected = pyqtSignal(object)
|
||||
committed = pyqtSignal()
|
||||
|
||||
def __init__(self, table_name, readonly=False, select=None, filters=None, fields_aliases=None, autocomplete=None, sort=None, pagination=250, display_name=None, row_upgrader=None, widget_classes=None, row_filter=None):
|
||||
super().__init__()
|
||||
|
|
@ -549,6 +550,11 @@ class Crud(Widget):
|
|||
# INDEX DATA WITH PK
|
||||
try:
|
||||
self.db.commit(data, deleted_rows=self.deleted_rows)
|
||||
# Emit committed signal to notify successful save
|
||||
try:
|
||||
self.committed.emit()
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.log.exception(traceback.format_exc())
|
||||
QMessageBox.critical(None, "Errore Salvataggio DB", str(e))
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>843</width>
|
||||
<height>27</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuAbout">
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
<addaction name="save_tecna_recipes_a"/>
|
||||
<addaction name="diagnostics_a"/>
|
||||
<addaction name="admin_enable_a"/>
|
||||
<addaction name="recipes_export_a"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuStrumenti">
|
||||
<property name="font">
|
||||
|
|
@ -170,6 +171,11 @@
|
|||
<string>Ultima Versione Software</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="recipes_export_a">
|
||||
<property name="text">
|
||||
<string>Backup ricette</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from PyQt5.QtGui import QKeySequence
|
|||
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QShortcut
|
||||
import shutil
|
||||
|
||||
from lib.helpers.recipe_manager import export_recipes, import_recipes,recipe_manager_signals
|
||||
from lib.helpers.recipe_manager import export_recipes, import_recipes, recipe_manager_signals, backup_current_recipes
|
||||
from lib.helpers.step import Step
|
||||
from ui.crud import Crud, Json_External_Dialog_Editor_Cell_Widget
|
||||
from ui.helpers import replace_widget
|
||||
|
|
@ -37,9 +37,16 @@ class Recipe_Selection(Widget):
|
|||
global noner
|
||||
super().__init__()
|
||||
self.config = config
|
||||
self.second_leak_test_enabled = self.config["hardware_config"]["second_leak_test"] == "present"
|
||||
self.second_leak_test_enabled = self.config["hardware_config"].get("second_leak_test", "absent") == "present"
|
||||
self.defaults = self.config.get("recipes_defaults", noner)
|
||||
self.unsupported_steps = unsupported_steps
|
||||
self.unsupported_steps = set(unsupported_steps or set())
|
||||
# Hide instruction_extra entirely unless explicitly enabled in recipes_defaults (istruzione_abilitata_extra: x)
|
||||
try:
|
||||
instr_extra_enabled = str(self.config.get("recipes_defaults", noner)["istruzione_abilitata_extra"]).strip().lower() == "x"
|
||||
except Exception:
|
||||
instr_extra_enabled = False
|
||||
if not instr_extra_enabled:
|
||||
self.unsupported_steps.add("instruction_extra")
|
||||
session = Users.get_session()
|
||||
if session.is_admin:
|
||||
readonly = False
|
||||
|
|
@ -147,11 +154,11 @@ class Recipe_Selection(Widget):
|
|||
self.config.get("recipes_defaults", noner)["verifica_resistenza_connettore_abilitata"]) and "resistance" not in self.unsupported_steps,
|
||||
"screws": len(self.config.get("recipes_defaults", noner)["avvitatura_abilitata"]) and "screws" not in self.unsupported_steps,
|
||||
"instruction": len(self.config.get("recipes_defaults", noner)["istruzione_abilitata"]) and "instruction" not in self.unsupported_steps,
|
||||
"instruction_extra": len(self.config.get("recipes_defaults", noner)["istruzione_abilitata_extra"]) and "instruction_extra" not in self.unsupported_steps,
|
||||
"instruction_extra": (str(self.config.get("recipes_defaults", noner)["istruzione_abilitata_extra"]).strip().lower() == "x") and "instruction_extra" not in self.unsupported_steps,
|
||||
"pipe_cutter": len(self.config.get("recipes_defaults", noner)["tagliatubi_abilitata"]) and "pipe_cutter" not in self.unsupported_steps,
|
||||
"vision": len(self.config.get("recipes_defaults", noner)["test_visione_abilitato"]) and "vision" not in self.unsupported_steps,
|
||||
"leak_1": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata"]) and "leak_1" not in self.unsupported_steps,
|
||||
"leak_2": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata_2"]) and "leak_2" not in self.unsupported_steps,
|
||||
"leak_2": (self.second_leak_test_enabled and len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata_2"]) and "leak_2" not in self.unsupported_steps),
|
||||
"print": len(self.config.get("recipes_defaults", noner)["stampa_etichetta_abilitata"]) and "print" not in self.unsupported_steps,
|
||||
"step_editors": step_defaults,
|
||||
},
|
||||
|
|
@ -168,6 +175,11 @@ class Recipe_Selection(Widget):
|
|||
pagination=25,
|
||||
)
|
||||
replace_widget(self, "crud_w", self.crud)
|
||||
# Backup recipes automatically on successful save in CRUD
|
||||
try:
|
||||
self.crud.committed.connect(self.on_crud_committed)
|
||||
except Exception:
|
||||
pass
|
||||
self.crud_modified = None
|
||||
self.selected = None
|
||||
self.select_b.setEnabled(False)
|
||||
|
|
@ -212,6 +224,20 @@ class Recipe_Selection(Widget):
|
|||
|
||||
recipe_manager_signals.recipes_imported.connect(self.crud.refresh)
|
||||
|
||||
def on_crud_committed(self):
|
||||
"""Triggered after successful save (commit) in the CRUD UI: creates a timestamped CSV backup."""
|
||||
try:
|
||||
backup_path = backup_current_recipes(config=self.config, logger=self.log)
|
||||
try:
|
||||
self.log.info(f"Backup CSV created: {backup_path}")
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
try:
|
||||
self.log.exception(f"Failed to create backup CSV after commit: {e}")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def check_modified(self, modified):
|
||||
self.crud_modified = modified
|
||||
self.check(self.crud_modified, self.selected)
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@ class Test(Widget):
|
|||
# if dependency not in self.components or not self.components[dependency].ready:
|
||||
if dependency not in self.components:
|
||||
self.unsupported_steps.add(step_name)
|
||||
# Enforce second leak test hardware flag
|
||||
if self.config["hardware_config"].get("second_leak_test", "absent") != "present":
|
||||
self.unsupported_steps.add("leak_2")
|
||||
# INIT PIECES COUNTER
|
||||
self.pieces = {"ok": 0, "ko": 0}
|
||||
# INIT CYCLE STATES
|
||||
|
|
@ -164,7 +167,8 @@ class Test(Widget):
|
|||
"leak_1": Test_Assembly(img_path=None, text=None, widget=Test_Leak(config=self.config,components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces, parent=self))
|
||||
if self.config["hardware_config"]["tecna_t3"] != "absent" or self.config["hardware_config"]["furness_controls"] !="absent" else None,
|
||||
"leak_2": Test_Assembly(img_path=None, text=None, widget=Test_Leak(config=self.config,components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces, parent=self))
|
||||
if self.config["hardware_config"]["tecna_t3"] != "absent" or self.config["hardware_config"]["furness_controls"] != "absent" else None,
|
||||
if ((self.config["hardware_config"]["tecna_t3"] != "absent" or self.config["hardware_config"]["furness_controls"] != "absent")
|
||||
and self.config["hardware_config"].get("second_leak_test", "absent") == "present") else None,
|
||||
"flush": Test_Assembly(img_path=None, text=u"SCARICO ARIA IN CORSO - ATTENDERE...", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step)),
|
||||
"instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA",
|
||||
widget=Test_Instructions(config=self.config,components=self.components, recipe=self.recipe, bench_name=self.config.machine_id, step=self.step)),
|
||||
|
|
@ -407,8 +411,13 @@ class Test(Widget):
|
|||
self.set_recipe(recipe=None)
|
||||
if self.config["hardware_config"]["tecna_t3"] == "present" or self.config["hardware_config"][
|
||||
"furness_controls"] == "present":
|
||||
self.cycle_available_steps["leak_1"].widget.recipe_written = False
|
||||
self.cycle_available_steps["leak_2"].widget.recipe_written = False
|
||||
# Reset recipe_written flags for leak widgets if they exist
|
||||
leak1 = self.cycle_available_steps.get("leak_1")
|
||||
if leak1 is not None and getattr(leak1, "widget", None) is not None:
|
||||
leak1.widget.recipe_written = False
|
||||
leak2 = self.cycle_available_steps.get("leak_2")
|
||||
if leak2 is not None and getattr(leak2, "widget", None) is not None:
|
||||
leak2.widget.recipe_written = False
|
||||
self.step = Step(step_type="select_recipe")
|
||||
self.cycle_index = -1
|
||||
self.recipe = None
|
||||
|
|
@ -633,12 +642,12 @@ class Test(Widget):
|
|||
leak1_index = step_types.index("leak_1")
|
||||
leak2_index = step_types.index("leak_2")
|
||||
if leak1_index + 1 == leak2_index: # Ensure 'leak_1' is immediately followed by 'leak_2'
|
||||
if self.config["hardware_config"].get("second_leak_test", "yes") == "no":
|
||||
if recipe and getattr(recipe, 'spec', None) and recipe.spec.get("instruction_extra") and "instruction_extra" not in self.unsupported_steps:
|
||||
steps.insert(leak2_index, Step(step_type="instruction_extra", spec={}))
|
||||
inserted_instruction = True
|
||||
|
||||
# Insert 'instruction_extra' after the first 'instructions' if not inserted between leaks
|
||||
if not inserted_instruction:
|
||||
if not inserted_instruction and recipe and getattr(recipe, 'spec', None) and recipe.spec.get("instruction_extra") and "instruction_extra" not in self.unsupported_steps:
|
||||
for i, step in enumerate(steps):
|
||||
if step.step_type == "instructions":
|
||||
steps.insert(i + 1, Step(step_type="instruction_extra", spec={}))
|
||||
|
|
|
|||
|
|
@ -184,15 +184,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -330,15 +321,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -476,21 +458,13 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -654,15 +628,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -800,15 +765,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -946,21 +902,13 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1130,15 +1078,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -1276,15 +1215,6 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
|
|
@ -1422,21 +1352,13 @@
|
|||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="PlaceholderText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="128">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1468,6 +1390,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1487,6 +1410,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1534,6 +1458,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1546,6 +1471,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1559,6 +1485,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1575,6 +1502,7 @@
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1599,6 +1527,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1623,6 +1552,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1641,6 +1571,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1659,6 +1590,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1672,6 +1604,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1688,6 +1621,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1701,6 +1635,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1714,6 +1649,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1730,6 +1666,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1752,6 +1689,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1776,6 +1714,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1800,6 +1739,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1818,6 +1758,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1837,6 +1778,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1872,6 +1814,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1885,6 +1828,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1901,6 +1845,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1923,6 +1868,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1947,6 +1893,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1965,6 +1912,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -1983,6 +1931,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2017,6 +1966,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>48</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2038,6 +1988,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2054,6 +2005,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2083,6 +2035,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2096,6 +2049,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2109,6 +2063,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2131,6 +2086,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2149,6 +2105,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2171,6 +2128,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2189,6 +2147,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2205,6 +2164,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2218,6 +2178,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2242,6 +2203,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2258,6 +2220,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
@ -2271,37 +2234,7 @@ border: 1px solid black;
|
|||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);
|
||||
border: 1px solid black;
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="4" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="valore_PID">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Valore PID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="7">
|
||||
<widget class="QLabel" name="valore_PID_l">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user