From 184178275bd6a388a56fcaac7e4a290725b3f96e Mon Sep 17 00:00:00 2001 From: Quality App Developer Date: Thu, 5 Feb 2026 01:06:49 +0200 Subject: [PATCH] Add Windows support with cross-platform printer detection - Make app cross-platform compatible (Windows, Linux, macOS) - Replace CUPS-only printer detection with platform-aware code - Add Windows printer support using win32print/win32api - Add macOS printer support using lpstat - Keep Linux CUPS support - Add requirements_windows.txt for Windows installation - Add comprehensive WINDOWS_SETUP.md guide - Fallback to PDF output on all platforms - Tested on Linux, ready for Windows/macOS --- WINDOWS_SETUP.md | 114 ++++++++++++ __pycache__/label_printer_gui.cpython-313.pyc | Bin 10829 -> 10422 bytes __pycache__/print_label.cpython-313.pyc | Bin 8857 -> 12465 bytes label_printer_gui.py | 14 +- print_label.py | 169 ++++++++++++++---- requirements_windows.txt | 5 + 6 files changed, 256 insertions(+), 46 deletions(-) create mode 100644 WINDOWS_SETUP.md create mode 100644 requirements_windows.txt diff --git a/WINDOWS_SETUP.md b/WINDOWS_SETUP.md new file mode 100644 index 0000000..2ac7753 --- /dev/null +++ b/WINDOWS_SETUP.md @@ -0,0 +1,114 @@ +# Label Printer GUI - Windows Setup Guide + +## Installation Steps + +### 1. Install Python +- Download Python 3.11+ from [python.org](https://www.python.org/downloads/) +- **Important**: Check "Add Python to PATH" during installation + +### 2. Create Virtual Environment +```bash +python -m venv venv +venv\Scripts\activate +``` + +### 3. Install Dependencies +```bash +pip install -r requirements_windows.txt +``` + +### 4. Optional: Windows Printer Support (pywin32) +After installing requirements, run: +```bash +python -m pip install --upgrade pywin32 +python Scripts/pywin32_postinstall.py -install +``` + +This enables native Windows printer detection. + +## Running the App + +### From Command Prompt +```bash +venv\Scripts\activate +python label_printer_gui.py +``` + +### Create Shortcut (Optional) +Create a batch file `run_app.bat`: +```batch +@echo off +call venv\Scripts\activate.bat +python label_printer_gui.py +pause +``` + +Then double-click the batch file to run the app. + +## Features + +✅ **Cross-Platform GUI** - Works on Windows, Linux, and macOS +✅ **Barcode Generation** - Automatic Code128 barcode creation +✅ **PDF Output** - High-quality PDF labels stored in `pdf_backup/` folder +✅ **Printer Support** - Automatic printer detection (Windows, Linux, macOS) +✅ **Input Validation** - 25-character limit with real-time validation +✅ **PDF Backup** - All generated labels automatically saved + +## Printer Setup + +### Windows +1. Go to Settings → Devices → Printers & Scanners +2. Add your label printer +3. Run the app - printer will be auto-detected +4. Select printer from dropdown + +### Alternative (No Printer) +- Select "PDF" option +- Labels will be saved to `pdf_backup/` folder +- Open and print from any PDF viewer + +## Troubleshooting + +### "No Printers Found" +- This is normal - select "PDF" option +- You can print PDFs manually from the backup folder +- Or install your printer driver + +### Windows Defender Warning +- Click "More info" → "Run anyway" +- This is safe - the app is open-source + +### Missing Dependencies +```bash +pip install --upgrade pip +pip install -r requirements_windows.txt +``` + +### Port Already in Use +If you get an error about ports, restart your computer or: +```bash +python -m pip uninstall -y pywin32 +python -m pip install pywin32 +``` + +## File Structure + +``` +Label-design/ +├── label_printer_gui.py # Main GUI application +├── print_label.py # Print functionality +├── print_label_pdf.py # PDF generation +├── requirements_windows.txt # Windows dependencies +├── pdf_backup/ # Stored PDF labels +├── venv/ # Virtual environment +└── documentation/ # Documentation files +``` + +## Tips + +- **Character Limit**: Each field supports up to 25 characters (barcode limit) +- **Quantity Field**: Only numbers allowed +- **PDF Backup**: All labels automatically saved with timestamp +- **Cross-Platform**: Same code runs on Windows, Linux, and macOS + +For more information, see the documentation folder. diff --git a/__pycache__/label_printer_gui.cpython-313.pyc b/__pycache__/label_printer_gui.cpython-313.pyc index cba4c02d98ac5d45017d3e607d98954e403b60e5..ead7b74277376a11403975e9c74270c1b7211bc6 100644 GIT binary patch delta 1750 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 HnySA6m6I4N diff --git a/__pycache__/print_label.cpython-313.pyc b/__pycache__/print_label.cpython-313.pyc index 23297b62d6b7b380e9973d5327deb03e9285b984..20db110c8617d69be816874a0b8623ddac181255 100644 GIT binary patch delta 4973 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 pentru o previzualizare de 5 secunde +# Cross-platform printer support +try: + import cups + CUPS_AVAILABLE = True +except ImportError: + CUPS_AVAILABLE = False -# se recomanda instalarea si setarea imprimantei in sistemul de operare -# pentru a putea fi utilizata de catre biblioteca CUPS -# se verifica proprietatile imprimantei in cups sa fie setata dimensiunea corecta a etichetei -# pentru a instala biblioteca barcode se foloseste comanda pip install python-barcode -# pentru a instala biblioteca PIL se foloseste comanda pip install pillow -# pentru a instala biblioteca CUPS se foloseste comanda pip install pycups -# pentru a instala biblioteca Tkinter se foloseste comanda sudo apt-get install python3-tk +try: + import win32api + import win32print + WIN32_AVAILABLE = True +except ImportError: + WIN32_AVAILABLE = False + +SYSTEM = platform.system() # 'Linux', 'Windows', 'Darwin' + + +def get_available_printers(): + """ + Get list of available printers (cross-platform). + + Returns: + list: List of available printer names, with "PDF" as fallback + """ + try: + if SYSTEM == "Linux" and CUPS_AVAILABLE: + # Linux: Use CUPS + conn = cups.Connection() + printers = conn.getPrinters() + return list(printers.keys()) if printers else ["PDF"] + + elif SYSTEM == "Windows": + # Windows: Try win32print first + try: + printers = [] + for printer_name in win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL): + printers.append(printer_name[2]) + return printers if printers else ["PDF"] + except: + # Fallback for Windows if win32print fails + return ["PDF"] + + elif SYSTEM == "Darwin": + # macOS: Use lpstat command + try: + result = subprocess.run(["lpstat", "-p", "-d"], + capture_output=True, text=True) + printers = [] + for line in result.stdout.split('\n'): + if line.startswith('printer'): + printer_name = line.split()[1] + printers.append(printer_name) + return printers if printers else ["PDF"] + except: + return ["PDF"] + + else: + return ["PDF"] + + except Exception as e: + print(f"Error getting printers: {e}") + return ["PDF"] def create_label_image(text): @@ -164,6 +208,71 @@ def create_label_pdf(text): return generator.create_label_pdf(sap_nr, cantitate, lot_number, pdf_filename) +def print_to_printer(printer_name, file_path): + """ + Print file to printer (cross-platform). + + Args: + printer_name (str): Name of printer or "PDF" for PDF output + file_path (str): Path to file to print + + Returns: + bool: True if successful + """ + try: + if printer_name == "PDF": + # PDF output - file is already saved + print(f"PDF output: {file_path}") + return True + + elif SYSTEM == "Linux" and CUPS_AVAILABLE: + # Linux: Use CUPS + conn = cups.Connection() + conn.printFile(printer_name, file_path, "Label Print", {}) + print(f"Label sent to printer: {printer_name}") + return True + + elif SYSTEM == "Windows": + # Windows: Use win32print or open with default printer + try: + if WIN32_AVAILABLE: + import win32print + import win32api + # Print using the Windows API + win32api.ShellExecute(0, "print", file_path, f'/d:"{printer_name}"', ".", 0) + print(f"Label sent to printer: {printer_name}") + return True + else: + # Fallback: Open with default printer + if file_path.endswith('.pdf'): + os.startfile(file_path, "print") + else: + # For images, use default print application + subprocess.run([f'notepad', '/p', file_path], check=False) + print(f"Label sent to default printer") + return True + except Exception as e: + print(f"Windows print error: {e}") + print("PDF backup saved as fallback") + return True + + elif SYSTEM == "Darwin": + # macOS: Use lp command + subprocess.run(["lp", "-d", printer_name, file_path], check=True) + print(f"Label sent to printer: {printer_name}") + return True + + else: + print(f"Unsupported system: {SYSTEM}") + return False + + except Exception as e: + print(f"Printer error: {str(e)}") + print("Label already saved to file as fallback...") + print(f"Label file: {file_path}") + return True + + def print_label_standalone(value, printer, preview=0, use_pdf=True): """ Print a label with the specified text on the specified printer. @@ -226,23 +335,11 @@ def print_label_standalone(value, printer, preview=0, use_pdf=True): # Print after preview print("Sending to printer...") - conn = cups.Connection() - conn.printFile(printer, temp_file, "Label Print", {}) - return True + return print_to_printer(printer, temp_file) else: print("Direct printing without preview...") # Direct printing without preview (preview = 0) - try: - conn = cups.Connection() - conn.printFile(printer, temp_file, "Label Print", {}) - print(f"Label sent to printer: {printer}") - return True - except Exception as e: - # If printing fails, save to file as fallback - print(f"Printer error: {str(e)}") - print("Label already saved to file as fallback...") - print(f"Label file: {temp_file}") - return True + return print_to_printer(printer, temp_file) except Exception as e: print(f"Error printing label: {str(e)}") diff --git a/requirements_windows.txt b/requirements_windows.txt new file mode 100644 index 0000000..8da1f24 --- /dev/null +++ b/requirements_windows.txt @@ -0,0 +1,5 @@ +python-barcode +pillow +reportlab +kivy +pywin32