Fix silent printing and shorten printer display names
- Print directly via win32print API without opening PDF viewer - Shorten printer names to 20 chars in dropdown (strip server prefix for network printers) - Map display names back to full names for printing - PDF backup saved silently without launching viewer
This commit is contained in:
@@ -38,15 +38,42 @@ class LabelPrinterApp(App):
|
|||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.available_printers = self.get_available_printers()
|
# Build printer display names and mapping to full names
|
||||||
|
full_printers = get_available_printers()
|
||||||
|
self.printer_display_map = {} # display_name -> full_name
|
||||||
|
self.available_printers = []
|
||||||
|
for full_name in full_printers:
|
||||||
|
display_name = self._shorten_printer_name(full_name)
|
||||||
|
# Ensure unique display names
|
||||||
|
if display_name in self.printer_display_map:
|
||||||
|
display_name = full_name[:20]
|
||||||
|
self.printer_display_map[display_name] = full_name
|
||||||
|
self.available_printers.append(display_name)
|
||||||
# Clean old PDF backup files on startup
|
# Clean old PDF backup files on startup
|
||||||
self.cleanup_old_pdfs()
|
self.cleanup_old_pdfs()
|
||||||
# Clean old log files on startup
|
# Clean old log files on startup
|
||||||
self.cleanup_old_logs()
|
self.cleanup_old_logs()
|
||||||
|
|
||||||
def get_available_printers(self):
|
def _shorten_printer_name(self, name, max_len=20):
|
||||||
"""Get list of available printers (cross-platform)"""
|
"""Shorten printer name for display (max 20 chars).
|
||||||
return get_available_printers()
|
For network printers like \\\\server\\printer, show just the printer part."""
|
||||||
|
if name.startswith('\\\\'):
|
||||||
|
# Network printer: \\server\printer -> extract printer name
|
||||||
|
parts = name.strip('\\').split('\\')
|
||||||
|
if len(parts) >= 2:
|
||||||
|
short = parts[-1] # Just the printer name
|
||||||
|
else:
|
||||||
|
short = name
|
||||||
|
else:
|
||||||
|
short = name
|
||||||
|
# Truncate to max_len
|
||||||
|
if len(short) > max_len:
|
||||||
|
short = short[:max_len]
|
||||||
|
return short
|
||||||
|
|
||||||
|
def _get_full_printer_name(self, display_name):
|
||||||
|
"""Resolve display name back to full printer name for printing."""
|
||||||
|
return self.printer_display_map.get(display_name, display_name)
|
||||||
|
|
||||||
def cleanup_old_pdfs(self, days=5):
|
def cleanup_old_pdfs(self, days=5):
|
||||||
"""
|
"""
|
||||||
@@ -278,7 +305,8 @@ class LabelPrinterApp(App):
|
|||||||
values=self.available_printers,
|
values=self.available_printers,
|
||||||
size_hint_y=None,
|
size_hint_y=None,
|
||||||
height=45,
|
height=45,
|
||||||
font_size='12sp'
|
font_size='12sp',
|
||||||
|
sync_height=True,
|
||||||
)
|
)
|
||||||
self.printer_spinner = printer_spinner
|
self.printer_spinner = printer_spinner
|
||||||
form_layout.add_widget(printer_spinner)
|
form_layout.add_widget(printer_spinner)
|
||||||
@@ -320,7 +348,8 @@ class LabelPrinterApp(App):
|
|||||||
sap_nr = self.sap_input.text.strip()
|
sap_nr = self.sap_input.text.strip()
|
||||||
quantity = self.qty_input.text.strip()
|
quantity = self.qty_input.text.strip()
|
||||||
cable_id = self.cable_id_input.text.strip()
|
cable_id = self.cable_id_input.text.strip()
|
||||||
printer = self.printer_spinner.text
|
# Resolve display name to full printer name
|
||||||
|
printer = self._get_full_printer_name(self.printer_spinner.text)
|
||||||
|
|
||||||
# Validate input
|
# Validate input
|
||||||
if not sap_nr and not quantity and not cable_id:
|
if not sap_nr and not quantity and not cable_id:
|
||||||
|
|||||||
@@ -249,38 +249,58 @@ def print_to_printer(printer_name, file_path):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
elif SYSTEM == "Windows":
|
elif SYSTEM == "Windows":
|
||||||
# Windows: Use win32print API for reliable printing (supports UNC paths)
|
# Windows: Print directly without opening PDF viewer
|
||||||
try:
|
try:
|
||||||
if WIN32_AVAILABLE:
|
if WIN32_AVAILABLE:
|
||||||
import win32print
|
import win32print
|
||||||
import win32api
|
import win32api
|
||||||
|
|
||||||
# Set the target printer as default temporarily, then print
|
if file_path.endswith('.pdf'):
|
||||||
# This approach works reliably with both local and UNC printer paths
|
# Use SumatraPDF command-line or direct raw printing
|
||||||
try:
|
# Try printing via subprocess to avoid opening a PDF viewer window
|
||||||
old_default = win32print.GetDefaultPrinter()
|
|
||||||
except:
|
|
||||||
old_default = None
|
|
||||||
|
|
||||||
|
# Method: Use win32print raw API to send to printer silently
|
||||||
try:
|
try:
|
||||||
win32print.SetDefaultPrinter(printer_name)
|
hprinter = win32print.OpenPrinter(printer_name)
|
||||||
win32api.ShellExecute(0, "print", file_path, None, ".", 0)
|
try:
|
||||||
|
# Start a print job
|
||||||
|
job_info = ("Label Print", None, "RAW")
|
||||||
|
hjob = win32print.StartDocPrinter(hprinter, 1, job_info)
|
||||||
|
win32print.StartPagePrinter(hprinter)
|
||||||
|
|
||||||
|
# Read PDF file and send to printer
|
||||||
|
with open(file_path, 'rb') as f:
|
||||||
|
pdf_data = f.read()
|
||||||
|
win32print.WritePrinter(hprinter, pdf_data)
|
||||||
|
|
||||||
|
win32print.EndPagePrinter(hprinter)
|
||||||
|
win32print.EndDocPrinter(hprinter)
|
||||||
print(f"Label sent to printer: {printer_name}")
|
print(f"Label sent to printer: {printer_name}")
|
||||||
finally:
|
finally:
|
||||||
# Restore original default printer
|
win32print.ClosePrinter(hprinter)
|
||||||
if old_default:
|
return True
|
||||||
|
except Exception as raw_err:
|
||||||
|
print(f"Raw print failed ({raw_err}), trying ShellExecute silently...")
|
||||||
|
# Fallback: Use ShellExecute with printto (minimized, auto-closes)
|
||||||
try:
|
try:
|
||||||
win32print.SetDefaultPrinter(old_default)
|
win32api.ShellExecute(
|
||||||
except:
|
0, "printto", file_path,
|
||||||
pass
|
f'"{printer_name}"', ".", 0
|
||||||
|
)
|
||||||
|
print(f"Label sent to printer: {printer_name}")
|
||||||
|
return True
|
||||||
|
except Exception as shell_err:
|
||||||
|
print(f"ShellExecute print failed: {shell_err}")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# Fallback: Open with default printer
|
# Non-PDF files: print silently with notepad
|
||||||
if file_path.endswith('.pdf'):
|
subprocess.run(['notepad', '/p', file_path],
|
||||||
os.startfile(file_path, "print")
|
check=False,
|
||||||
|
creationflags=subprocess.CREATE_NO_WINDOW)
|
||||||
|
print(f"Label sent to printer: {printer_name}")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
subprocess.run(['notepad', '/p', file_path], check=False)
|
print("win32print not available, PDF saved as backup only")
|
||||||
print(f"Label sent to default printer")
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Windows print error: {e}")
|
print(f"Windows print error: {e}")
|
||||||
|
|||||||
Reference in New Issue
Block a user