Add scan-tag.png between drawing and QR code on ribbon prints
Inserts the scan-tag image centered horizontally between the user drawing and QR code in ribbon print output. Total height increases by scan-tag height. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
480
kiosk.py
480
kiosk.py
@ -24,6 +24,25 @@ import glob
|
||||
import traceback
|
||||
|
||||
|
||||
# Load configuration
|
||||
def load_config():
|
||||
config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.json')
|
||||
try:
|
||||
with open(config_path) as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
print("Warning: config.json not found. Copy config.example.json to config.json and customize it.")
|
||||
return {
|
||||
"printers": {"sticker": "sticker_printer", "ribbon": "tag-printer"},
|
||||
"camera": {"preferred_name": "NexiGo"},
|
||||
"ribbon": {"width": 450, "margin": 50},
|
||||
"background_color": "#bcfef9"
|
||||
}
|
||||
|
||||
CONFIG = load_config()
|
||||
BG_COLOR = CONFIG.get("background_color", "#bcfef9")
|
||||
|
||||
|
||||
def get_preferred_camera_index(preferred_name_fragment=None):
|
||||
"""
|
||||
Try to find a stable camera index for an external webcam.
|
||||
@ -95,15 +114,12 @@ def get_preferred_camera_index(preferred_name_fragment=None):
|
||||
|
||||
|
||||
|
||||
# Configuration
|
||||
MIGRATION_ITEMS_DIR = "/home/trav/Documents/migration_items"
|
||||
|
||||
# Global variables
|
||||
class GlobalVars:
|
||||
qr_code_value = None
|
||||
print_type = "neither"
|
||||
migration_ticket = ""
|
||||
selected_user = None
|
||||
ribbon_size = None # 'small', 'medium', or 'large'
|
||||
BUTTON_FONT = None
|
||||
TEXT_FONT = None
|
||||
|
||||
@ -147,28 +163,11 @@ class Kiosk(tk.Tk):
|
||||
self.start_over()
|
||||
|
||||
def start_over(self):
|
||||
global migration_ticket
|
||||
global MIGRATION_ITEMS_DIR
|
||||
|
||||
# Check if migration_ticket is defined
|
||||
#if 'migration_ticket' in globals():
|
||||
# Delete any existing migration files
|
||||
# if migration_ticket:
|
||||
# text_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# image_file = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
|
||||
# if os.path.exists(text_file):
|
||||
# os.remove(text_file)
|
||||
# if os.path.exists(image_file):
|
||||
# os.remove(image_file)
|
||||
|
||||
# Reset migration_ticket
|
||||
# migration_ticket = ""
|
||||
|
||||
# Reset other global variables
|
||||
# Reset global variables
|
||||
GlobalVars.qr_code_value = None
|
||||
GlobalVars.print_type = "neither"
|
||||
GlobalVars.selected_user = None
|
||||
GlobalVars.ribbon_size = None
|
||||
|
||||
# Switch to the home screen
|
||||
self.switch_frame(Screen0)
|
||||
@ -176,12 +175,12 @@ class Kiosk(tk.Tk):
|
||||
# home screen
|
||||
class Screen0(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
title_font = tkfont.Font(size=42, family='Helvetica') # 30% bigger
|
||||
|
||||
# Split the screen into two frames
|
||||
left_frame = tk.Frame(self, bg='#bcfef9')
|
||||
right_frame = tk.Frame(self, bg='#bcfef9', padx=40) # 40px padding on the right side
|
||||
left_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
right_frame = tk.Frame(self, bg=BG_COLOR, padx=40) # 40px padding on the right side
|
||||
left_frame.grid(row=0, column=0, sticky='nsew')
|
||||
right_frame.grid(row=0, column=1, sticky='nsew')
|
||||
|
||||
@ -189,21 +188,18 @@ class Screen0(tk.Frame):
|
||||
self.grid_columnconfigure(1, weight=1) # For right frame
|
||||
|
||||
# Title and buttons on the left side
|
||||
title_label = tk.Label(left_frame, text="Custodisco", bg='#bcfef9', fg='#800080', font=('Helvetica', 64)) # dark purple color
|
||||
title_label = tk.Label(left_frame, text="Custodisco", bg=BG_COLOR, fg='#800080', font=('Helvetica', 64)) # dark purple color
|
||||
title_label.pack(side='top', pady=200) # adjust to your needs
|
||||
|
||||
# Welcome message on the left side
|
||||
# welcome_text = """"""
|
||||
# welcome_label = tk.Label(left_frame, text=welcome_text, bg='#bcfef9', font=GlobalVars.TEXT_FONT, justify='left', wraplength=650)
|
||||
# welcome_label = tk.Label(left_frame, text=welcome_text, bg=BG_COLOR, font=GlobalVars.TEXT_FONT, justify='left', wraplength=650)
|
||||
# welcome_label.pack(side='top', padx=20, pady=20)
|
||||
|
||||
|
||||
|
||||
tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen1), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
# Button for Migration mode
|
||||
#tk.Button(right_frame, text="Create Item", command=lambda: master.switch_frame(Screen15), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
tk.Button(right_frame, text="Lookup Item", command=lambda: master.switch_frame(Screen14), height=4, width=75, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
# Create the quit button
|
||||
@ -217,7 +213,7 @@ class Screen0(tk.Frame):
|
||||
class Screen1(tk.Frame):
|
||||
def __init__(self, master):
|
||||
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
|
||||
# Create the label widget with the text
|
||||
@ -238,7 +234,7 @@ class VirtualScrolledFrame(ttk.Frame):
|
||||
|
||||
# Create a canvas object and a vertical scrollbar for scrolling it
|
||||
self.vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL)
|
||||
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, bg='#bcfef9')
|
||||
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, bg=BG_COLOR)
|
||||
self.vscrollbar.config(command=self.canvas.yview)
|
||||
|
||||
# Reset the view
|
||||
@ -246,7 +242,7 @@ class VirtualScrolledFrame(ttk.Frame):
|
||||
self.canvas.yview_moveto(0)
|
||||
|
||||
# Create a frame inside the canvas which will be scrolled with it
|
||||
self.interior = tk.Frame(self.canvas, bg='#bcfef9')
|
||||
self.interior = tk.Frame(self.canvas, bg=BG_COLOR)
|
||||
self.interior_id = self.canvas.create_window(0, 0, window=self.interior, anchor=tk.NW)
|
||||
|
||||
# Pack the widgets
|
||||
@ -275,12 +271,12 @@ class VirtualScrolledFrame(ttk.Frame):
|
||||
# find yourself in list of ssb users
|
||||
class Screen2(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
self.selected_label = None
|
||||
self.filtered_users = []
|
||||
|
||||
# Create a new frame at the top for the label and text box
|
||||
self.top_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.top_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.top_frame.pack(side="top", fill="x", pady=(60, 10))
|
||||
|
||||
# Add a label with text wrapping
|
||||
@ -288,7 +284,7 @@ class Screen2(tk.Frame):
|
||||
text="Start typing your public key or alias to find yourself in the list then click on your key to select it.",
|
||||
font=GlobalVars.TEXT_FONT,
|
||||
wraplength=800,
|
||||
bg='#bcfef9')
|
||||
bg=BG_COLOR)
|
||||
self.label.pack(side="top", pady=(0, 10))
|
||||
|
||||
# Add text box to the top frame
|
||||
@ -300,13 +296,13 @@ class Screen2(tk.Frame):
|
||||
self.entry.focus_set()
|
||||
|
||||
# Create container for user list
|
||||
self.container = tk.Frame(self, bg='#bcfef9')
|
||||
self.container = tk.Frame(self, bg=BG_COLOR)
|
||||
self.container.pack(fill='both', expand=True, padx=20, pady=10)
|
||||
|
||||
# Create a canvas for the user list
|
||||
self.canvas = tk.Canvas(self.container, bg='#bcfef9')
|
||||
self.canvas = tk.Canvas(self.container, bg=BG_COLOR)
|
||||
self.scrollbar = ttk.Scrollbar(self.container, orient="vertical", command=self.canvas.yview)
|
||||
self.scrollable_frame = tk.Frame(self.canvas, bg='#bcfef9')
|
||||
self.scrollable_frame = tk.Frame(self.canvas, bg=BG_COLOR)
|
||||
|
||||
self.scrollable_frame.bind(
|
||||
"<Configure>",
|
||||
@ -324,7 +320,7 @@ class Screen2(tk.Frame):
|
||||
style.configure("Vertical.TScrollbar", arrowsize=48, width=48)
|
||||
|
||||
# Create a frame for action buttons at the bottom
|
||||
self.button_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.button_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.button_frame.pack(side="bottom", fill="x", pady=10)
|
||||
|
||||
# The 'Refresh List' button
|
||||
@ -354,16 +350,16 @@ class Screen2(tk.Frame):
|
||||
|
||||
for index, user in enumerate(self.filtered_users):
|
||||
try:
|
||||
frame = tk.Frame(self.scrollable_frame, bg='#bcfef9')
|
||||
frame = tk.Frame(self.scrollable_frame, bg=BG_COLOR)
|
||||
frame.pack(fill='x', expand=True, pady=2)
|
||||
|
||||
alias = self.unescape_unicode(user.get('alias', ''))
|
||||
id = user.get('id', '')
|
||||
|
||||
alias_label = tk.Label(frame, text=alias, font=('Helvetica', 14, 'bold'), width=20, anchor='w', bg='#bcfef9')
|
||||
alias_label = tk.Label(frame, text=alias, font=('Helvetica', 14, 'bold'), width=20, anchor='w', bg=BG_COLOR)
|
||||
alias_label.pack(side='left', padx=(0, 10))
|
||||
|
||||
id_label = tk.Label(frame, text=id, font=('Helvetica', 14), anchor='w', bg='#bcfef9')
|
||||
id_label = tk.Label(frame, text=id, font=('Helvetica', 14), anchor='w', bg=BG_COLOR)
|
||||
id_label.pack(side='left', expand=True, fill='x')
|
||||
|
||||
frame.bind('<Button-1>', lambda e, u=user, f=frame: self.on_user_clicked(f, u))
|
||||
@ -407,9 +403,9 @@ class Screen2(tk.Frame):
|
||||
print(f"Highlighted frame: {frame}")
|
||||
|
||||
def unhighlight_frame(self, frame):
|
||||
frame.configure(bg="#bcfef9")
|
||||
frame.configure(bg=BG_COLOR)
|
||||
for child in frame.winfo_children():
|
||||
child.configure(bg="#bcfef9")
|
||||
child.configure(bg=BG_COLOR)
|
||||
print(f"Unhighlighted frame: {frame}")
|
||||
|
||||
def update_users_list(self):
|
||||
@ -493,14 +489,14 @@ class Screen2(tk.Frame):
|
||||
#take photo of item
|
||||
class Screen3(tk.Frame):
|
||||
def __init__(self, master=None):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
# Create the "Start Over" button
|
||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
home_button.place(x=0, y=0) # top-left corner
|
||||
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index(CONFIG["camera"]["preferred_name"]))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
|
||||
@ -509,9 +505,9 @@ class Screen3(tk.Frame):
|
||||
self.canvas.pack(side="left")
|
||||
|
||||
# Info and button on the right
|
||||
self.text_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.text_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.text_frame.pack(side="right", fill="both", expand=True)
|
||||
tk.Label(self.text_frame, text="Now we will take a picture of your item to show up on Scuttlebutt.\n\nIf you tap Take Photo a second time it will re-take the photo\nbut wont show you a preview during the countdown (this is a bug)", font=("Helvetica", 16), bg='#bcfef9').pack(pady=10)
|
||||
tk.Label(self.text_frame, text="Now we will take a picture of your item to show up on Scuttlebutt.\n\nIf you tap Take Photo a second time it will re-take the photo\nbut wont show you a preview during the countdown (this is a bug)", font=("Helvetica", 16), bg=BG_COLOR).pack(pady=10)
|
||||
self.button = tk.Button(self.text_frame, text="Take Photo", command=self.take_photo, height=3, width=37, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
self.button.pack(pady=10)
|
||||
|
||||
@ -530,7 +526,7 @@ class Screen3(tk.Frame):
|
||||
self.master.switch_frame(Screen0)
|
||||
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index(CONFIG["camera"]["preferred_name"]))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
|
||||
@ -539,9 +535,9 @@ class Screen3(tk.Frame):
|
||||
self.canvas.pack(side="left")
|
||||
|
||||
# Info and button on the right
|
||||
self.text_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.text_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.text_frame.pack(side="right", fill="both", expand=True)
|
||||
tk.Label(self.text_frame, text="Now we will take a picture of your item to show up on Scuttlebutt.\n\nIf you tap Take Photo a second time it will re-take the photo\nbut wont show you a preview during the countdown (this is a bug)", font=("Helvetica", 16), bg='#bcfef9').pack(pady=10)
|
||||
tk.Label(self.text_frame, text="Now we will take a picture of your item to show up on Scuttlebutt.\n\nIf you tap Take Photo a second time it will re-take the photo\nbut wont show you a preview during the countdown (this is a bug)", font=("Helvetica", 16), bg=BG_COLOR).pack(pady=10)
|
||||
self.button = tk.Button(self.text_frame, text="Take Photo", command=self.take_photo, height=3, width=37, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
self.button.pack(pady=10)
|
||||
|
||||
@ -557,14 +553,14 @@ class Screen3(tk.Frame):
|
||||
#take photo of item
|
||||
class Screen3(tk.Frame):
|
||||
def __init__(self, master=None):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
# Create the "Start Over" button
|
||||
home_button = tk.Button(text="Start Over", command=self.show_warning_dialog, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
home_button.place(x=0, y=0) # top-left corner
|
||||
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.vid = cv2.VideoCapture(get_preferred_camera_index(CONFIG["camera"]["preferred_name"]))
|
||||
self.is_capturing = True
|
||||
self.freeze_frame = None
|
||||
self.countdown_text = None
|
||||
@ -575,9 +571,9 @@ class Screen3(tk.Frame):
|
||||
self.canvas.pack(side="left")
|
||||
|
||||
# Info and button on the right
|
||||
self.text_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.text_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.text_frame.pack(side="right", fill="both", expand=True)
|
||||
# tk.Label(self.text_frame, text="Take a photo of your item", font=("Helvetica", 16), bg='#bcfef9').pack(pady=10)
|
||||
# tk.Label(self.text_frame, text="Take a photo of your item", font=("Helvetica", 16), bg=BG_COLOR).pack(pady=10)
|
||||
self.button = tk.Button(self.text_frame, text="Take Photo", command=self.take_photo, height=3, width=37, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
self.button.pack(pady=10)
|
||||
|
||||
@ -647,19 +643,6 @@ class Screen3(tk.Frame):
|
||||
self.canvas.create_image(0, 0, image=self.last_photo, anchor='nw')
|
||||
|
||||
def done(self):
|
||||
global migration_ticket
|
||||
global MIGRATION_ITEMS_DIR
|
||||
|
||||
# If migration_ticket is set, copy the photo to MIGRATION_ITEMS_DIR
|
||||
#if migration_ticket:
|
||||
# source_path = 'freeze_frame.jpg'
|
||||
# destination_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
# try:
|
||||
# shutil.copy2(source_path, destination_path)
|
||||
# print(f"Photo saved as {destination_path}")
|
||||
#except Exception as e:
|
||||
# print(f"Error saving photo: {e}")
|
||||
|
||||
self.release_resources()
|
||||
self.master.switch_frame(Screen5)
|
||||
|
||||
@ -679,7 +662,7 @@ class Screen3(tk.Frame):
|
||||
# draw a sticker
|
||||
class Screen4(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
# Configure column minsizes
|
||||
self.grid_columnconfigure(0, minsize=675)
|
||||
@ -687,11 +670,11 @@ class Screen4(tk.Frame):
|
||||
self.grid_columnconfigure(2, minsize=100)
|
||||
|
||||
# Creating a frame for the left side of the screen for drawing and instructions
|
||||
self.left_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.left_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.left_frame.grid(row=0, column=0, padx=2)
|
||||
|
||||
# Frame for the tools
|
||||
self.right_frame = tk.Frame(self, bg='#bcfef9')
|
||||
self.right_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
self.right_frame.grid(row=0, column=2, padx=70)
|
||||
|
||||
# Add Import Image Button
|
||||
@ -719,13 +702,13 @@ class Screen4(tk.Frame):
|
||||
self.add_qr_box()
|
||||
|
||||
# Create frames for pen size and color tools
|
||||
self.pen_size_frame = tk.Frame(self.right_frame, bg='#bcfef9')
|
||||
self.pen_size_frame = tk.Frame(self.right_frame, bg=BG_COLOR)
|
||||
self.pen_size_frame.pack(pady=(0, 20))
|
||||
self.pen_color_frame = tk.Frame(self.right_frame, bg='#bcfef9')
|
||||
self.pen_color_frame = tk.Frame(self.right_frame, bg=BG_COLOR)
|
||||
self.pen_color_frame.pack(pady=(0, 20))
|
||||
|
||||
# Pen size label
|
||||
tk.Label(self.pen_size_frame, text="Pen Size", font=GlobalVars.TEXT_FONT, bg='#bcfef9').pack()
|
||||
tk.Label(self.pen_size_frame, text="Pen Size", font=GlobalVars.TEXT_FONT, bg=BG_COLOR).pack()
|
||||
|
||||
# Add Draw Size buttons
|
||||
pen_sizes = [(".", 1), ("*", 2), ("⚬", 3), ("⬤", 4), ("⬛", 5)]
|
||||
@ -734,7 +717,7 @@ class Screen4(tk.Frame):
|
||||
height=2, width=5, bg='peach puff').pack(pady=2)
|
||||
|
||||
# Pen color label
|
||||
tk.Label(self.pen_color_frame, text="Pen Color", font=GlobalVars.TEXT_FONT, bg='#bcfef9').pack()
|
||||
tk.Label(self.pen_color_frame, text="Pen Color", font=GlobalVars.TEXT_FONT, bg=BG_COLOR).pack()
|
||||
|
||||
# Creating color buttons
|
||||
colors = ['black', 'gray', 'white']
|
||||
@ -754,7 +737,7 @@ class Screen4(tk.Frame):
|
||||
master.add_home_button(self)
|
||||
|
||||
# Define the info_label to display QRX, QRY, and QRscale values
|
||||
self.info_label = tk.Label(self.right_frame, text="", bg='#bcfef9', font=GlobalVars.TEXT_FONT)
|
||||
self.info_label = tk.Label(self.right_frame, text="", bg=BG_COLOR, font=GlobalVars.TEXT_FONT)
|
||||
self.info_label.pack(pady=5)
|
||||
|
||||
def draw_line(self, event):
|
||||
@ -879,7 +862,7 @@ class Screen4(tk.Frame):
|
||||
# typed description
|
||||
class Screen5(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
|
||||
|
||||
@ -900,38 +883,16 @@ class Screen5(tk.Frame):
|
||||
|
||||
def save_info_and_switch(self):
|
||||
global info_text
|
||||
global migration_ticket
|
||||
global MIGRATION_ITEMS_DIR
|
||||
|
||||
info_text = self.info_entry.get("1.0", "end-1c")
|
||||
info_text = info_text.replace('\n', '\\n')
|
||||
|
||||
# If migration_ticket is set (not empty), save the text and image to MIGRATION_ITEMS_DIR
|
||||
#if migration_ticket:
|
||||
# Save text
|
||||
# text_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# try:
|
||||
# with open(text_file_path, 'w') as f:
|
||||
# f.write(info_text)
|
||||
# print(f"Text saved as {text_file_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error saving text: {e}")
|
||||
|
||||
# Save image
|
||||
# source_image_path = 'freeze_frame.jpg'
|
||||
# destination_image_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.jpg")
|
||||
# try:
|
||||
# shutil.copy2(source_image_path, destination_image_path)
|
||||
# print(f"Photo saved as {destination_image_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error saving photo: {e}")
|
||||
|
||||
self.master.switch_frame(Screen11)
|
||||
|
||||
# I understand
|
||||
class Screen6(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
master.add_home_button(self)
|
||||
tk.Button(self, text="I Understand", command=lambda: master.switch_frame(Screen3), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=10)
|
||||
@ -941,7 +902,7 @@ class Screen6(tk.Frame):
|
||||
# create user not implemented lol
|
||||
class Screen7(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
master.add_home_button(self)
|
||||
# Assume there's a method to manage the text entry
|
||||
@ -958,39 +919,46 @@ class Screen7(tk.Frame):
|
||||
# draw a ribbon tag
|
||||
class Screen8(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
# Original dimensions
|
||||
self.original_width = 325
|
||||
self.original_height = 179
|
||||
# Get ribbon width from config and calculate dimensions based on selected size
|
||||
self.ribbon_width = CONFIG.get("ribbon", {}).get("width", 450)
|
||||
self.printable_width = self.ribbon_width - 50 # 25px margin each side
|
||||
multiplier = {'small': 0.5, 'medium': 1.0, 'large': 1.5}.get(GlobalVars.ribbon_size, 1.0)
|
||||
self.original_width = self.printable_width
|
||||
self.original_height = int(self.printable_width * multiplier)
|
||||
|
||||
# Doubled dimensions for display
|
||||
self.display_width = self.original_width * 2
|
||||
self.display_height = self.original_height * 2
|
||||
# Adaptive display scaling based on size
|
||||
# Target max display height ~700px to fit comfortably on screen
|
||||
max_display_height = 700
|
||||
ideal_scale = max_display_height / self.original_height
|
||||
self.scale_factor = min(2, max(1, int(ideal_scale))) # Clamp between 1x and 2x
|
||||
self.grid_size = self.scale_factor
|
||||
|
||||
# Grid size (2x2 pixels)
|
||||
self.grid_size = 2
|
||||
# Display dimensions
|
||||
self.display_width = self.original_width * self.scale_factor
|
||||
self.display_height = self.original_height * self.scale_factor
|
||||
|
||||
# Add the home button
|
||||
master.add_home_button(self)
|
||||
|
||||
# Main container to hold all elements
|
||||
main_container = tk.Frame(self, bg='#bcfef9')
|
||||
main_container = tk.Frame(self, bg=BG_COLOR)
|
||||
main_container.place(relx=0.5, rely=0.5, anchor='center')
|
||||
|
||||
# Left frame for drawing area and import button
|
||||
left_frame = tk.Frame(main_container, bg='#bcfef9')
|
||||
left_frame = tk.Frame(main_container, bg=BG_COLOR)
|
||||
left_frame.pack(side='left', padx=(0, 20))
|
||||
|
||||
# Right frame for tools and buttons
|
||||
right_frame = tk.Frame(main_container, bg='#bcfef9')
|
||||
right_frame = tk.Frame(main_container, bg=BG_COLOR)
|
||||
right_frame.pack(side='right')
|
||||
|
||||
# Import Image Button
|
||||
tk.Button(left_frame, text="Import Image", command=self.import_image, height=2, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=10)
|
||||
|
||||
# Simplified instructions
|
||||
self.label = tk.Label(left_frame, text="You may now draw your ribbon :)", wraplength=300, font=GlobalVars.TEXT_FONT, bg='#bcfef9')
|
||||
self.label = tk.Label(left_frame, text="You may now draw your ribbon :)", wraplength=300, font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
self.label.pack(pady=10)
|
||||
|
||||
# Drawing area (doubled size for display)
|
||||
@ -1009,10 +977,10 @@ class Screen8(tk.Frame):
|
||||
self.canvas.pack(pady=10)
|
||||
|
||||
# Pen size frame
|
||||
pen_size_frame = tk.Frame(right_frame, bg='#bcfef9')
|
||||
pen_size_frame = tk.Frame(right_frame, bg=BG_COLOR)
|
||||
pen_size_frame.pack(pady=10)
|
||||
|
||||
tk.Label(pen_size_frame, text="Pen Size", font=GlobalVars.TEXT_FONT, bg='#bcfef9').pack()
|
||||
tk.Label(pen_size_frame, text="Pen Size", font=GlobalVars.TEXT_FONT, bg=BG_COLOR).pack()
|
||||
|
||||
# Pen size buttons
|
||||
pen_sizes = [(".", 1), ("*", 2), ("⚬", 3), ("⬤", 4), ("⬛", 5)]
|
||||
@ -1021,10 +989,10 @@ class Screen8(tk.Frame):
|
||||
height=2, width=5, bg='peach puff').pack(pady=2)
|
||||
|
||||
# Pen color frame
|
||||
pen_color_frame = tk.Frame(right_frame, bg='#bcfef9')
|
||||
pen_color_frame = tk.Frame(right_frame, bg=BG_COLOR)
|
||||
pen_color_frame.pack(pady=10)
|
||||
|
||||
tk.Label(pen_color_frame, text="Pen Color", font=GlobalVars.TEXT_FONT, bg='#bcfef9').pack()
|
||||
tk.Label(pen_color_frame, text="Pen Color", font=GlobalVars.TEXT_FONT, bg=BG_COLOR).pack()
|
||||
|
||||
# Color buttons
|
||||
colors = ['black', 'gray', 'white']
|
||||
@ -1152,7 +1120,7 @@ class Screen8(tk.Frame):
|
||||
# txt update
|
||||
class Screen9(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
# Assume there's a method to manage the text entry
|
||||
tk.Button(self, text="Done", command=lambda: master.switch_frame(Screen10), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=10)
|
||||
@ -1162,15 +1130,15 @@ class Screen10(tk.Frame):
|
||||
def __init__(self, master):
|
||||
|
||||
GlobalVars.selected_user = None # Reset the selected user
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Label(self, text="Thank you!", bg='#bcfef9', font=('Helvetica', 48)).pack()
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
tk.Label(self, text="Thank you!", bg=BG_COLOR, font=('Helvetica', 48)).pack()
|
||||
tk.Button(self, text="Done", command=lambda: master.switch_frame(Screen0), height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=10)
|
||||
|
||||
# Sticker or tag?
|
||||
class Screen11(tk.Frame):
|
||||
def __init__(self, master):
|
||||
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
# Instructions
|
||||
self.label = tk.Label(self, text="Which type of tag would you like to design?",
|
||||
@ -1180,9 +1148,9 @@ class Screen11(tk.Frame):
|
||||
|
||||
# Button functions
|
||||
def select_ribbon():
|
||||
global print_type
|
||||
global print_type
|
||||
print_type = 'ribbon'
|
||||
master.switch_frame(Screen8)
|
||||
master.switch_frame(ScreenRibbonSize)
|
||||
|
||||
def select_sticker():
|
||||
global print_type
|
||||
@ -1195,10 +1163,106 @@ class Screen11(tk.Frame):
|
||||
tk.Button(self, text="Ribbon tag", command=select_ribbon, height=4, width=39, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(side='top', pady=30)
|
||||
|
||||
|
||||
# Select ribbon size
|
||||
class ScreenRibbonSize(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
|
||||
# Get ribbon config
|
||||
self.ribbon_width = CONFIG.get("ribbon", {}).get("width", 450)
|
||||
self.margin = CONFIG.get("ribbon", {}).get("margin", 50)
|
||||
self.printable_width = self.ribbon_width - 50 # 25px margin each side
|
||||
|
||||
# Title
|
||||
title_label = tk.Label(self, text="Select your ribbon size:",
|
||||
font=GlobalVars.TEXT_FONT, bg=BG_COLOR)
|
||||
title_label.pack(pady=30)
|
||||
|
||||
# Container for the three size options
|
||||
options_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
options_frame.pack(pady=20)
|
||||
|
||||
# Size options with multipliers
|
||||
sizes = [
|
||||
('Small', 0.5, 'Half-height drawing'),
|
||||
('Medium', 1.0, 'Square drawing'),
|
||||
('Large', 1.5, 'Tall drawing')
|
||||
]
|
||||
|
||||
for size_name, multiplier, description in sizes:
|
||||
self.create_size_option(options_frame, size_name, multiplier, description, master)
|
||||
|
||||
def create_size_option(self, parent, size_name, multiplier, description, master):
|
||||
# Frame for each option
|
||||
option_frame = tk.Frame(parent, bg=BG_COLOR, padx=20)
|
||||
option_frame.pack(side='left', padx=20)
|
||||
|
||||
# Calculate dimensions for this size (based on printable width)
|
||||
drawing_height = int(self.printable_width * multiplier)
|
||||
qr_scale = self.printable_width // 21
|
||||
qr_size = 21 * qr_scale
|
||||
# Total height includes top/bottom margins
|
||||
total_height = self.margin + drawing_height + qr_size + self.margin
|
||||
|
||||
# Create preview canvas (scaled down for display)
|
||||
preview_scale = 0.3
|
||||
preview_width = int(self.ribbon_width * preview_scale)
|
||||
preview_height = int(total_height * preview_scale)
|
||||
margin_preview = int(self.margin * preview_scale)
|
||||
drawing_preview_height = int(drawing_height * preview_scale)
|
||||
qr_preview_size = int(qr_size * preview_scale)
|
||||
side_margin_preview = int(25 * preview_scale) # 25px side margins
|
||||
|
||||
canvas = tk.Canvas(option_frame, width=preview_width, height=preview_height,
|
||||
bg='white', highlightthickness=2, highlightbackground='gray')
|
||||
canvas.pack(pady=10)
|
||||
|
||||
# Draw top margin area
|
||||
canvas.create_rectangle(0, 0, preview_width, margin_preview,
|
||||
fill='#f5f5f5', outline='')
|
||||
|
||||
# Draw drawing area (with side margins indicated)
|
||||
canvas.create_rectangle(side_margin_preview, margin_preview,
|
||||
preview_width - side_margin_preview, margin_preview + drawing_preview_height,
|
||||
fill='#e0e0e0', outline='black')
|
||||
canvas.create_text(preview_width // 2, margin_preview + drawing_preview_height // 2,
|
||||
text="Drawing", font=('Helvetica', 10))
|
||||
|
||||
# Draw QR indicator (centered)
|
||||
qr_x = (preview_width - qr_preview_size) // 2
|
||||
qr_y = margin_preview + drawing_preview_height
|
||||
canvas.create_rectangle(qr_x, qr_y,
|
||||
qr_x + qr_preview_size, qr_y + qr_preview_size,
|
||||
fill='#808080', outline='black')
|
||||
canvas.create_text(preview_width // 2, qr_y + qr_preview_size // 2,
|
||||
text="QR", font=('Helvetica', 8), fill='white')
|
||||
|
||||
# Draw bottom margin area
|
||||
canvas.create_rectangle(0, qr_y + qr_preview_size, preview_width, preview_height,
|
||||
fill='#f5f5f5', outline='')
|
||||
|
||||
# Size name and dimensions button (show printable dimensions)
|
||||
button_text = f"{size_name}\n{self.printable_width}×{drawing_height}px"
|
||||
btn = tk.Button(option_frame, text=button_text,
|
||||
command=lambda s=size_name.lower(): self.select_size(s, master),
|
||||
height=3, width=15, bg='peach puff', font=GlobalVars.BUTTON_FONT)
|
||||
btn.pack(pady=10)
|
||||
|
||||
# Description label
|
||||
desc_label = tk.Label(option_frame, text=description,
|
||||
font=('Helvetica', 12), bg=BG_COLOR)
|
||||
desc_label.pack()
|
||||
|
||||
def select_size(self, size, master):
|
||||
GlobalVars.ribbon_size = size
|
||||
master.switch_frame(Screen8)
|
||||
|
||||
|
||||
# after QR scanned for lookup
|
||||
class Screen12(tk.Frame):
|
||||
def __init__(self, master):
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
|
||||
print(f"Initializing Screen12 with QR code value: {GlobalVars.qr_code_value}")
|
||||
|
||||
@ -1223,10 +1287,10 @@ class Screen12(tk.Frame):
|
||||
|
||||
def display_error(self, message):
|
||||
print(f"Displaying error: {message}")
|
||||
error_frame = tk.Frame(self, bg='#bcfef9')
|
||||
error_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
error_frame.pack(expand=True, fill='both', padx=20, pady=20)
|
||||
|
||||
tk.Label(error_frame, text=message, bg='#bcfef9', font=GlobalVars.TEXT_FONT, wraplength=500).pack(pady=50)
|
||||
tk.Label(error_frame, text=message, bg=BG_COLOR, font=GlobalVars.TEXT_FONT, wraplength=500).pack(pady=50)
|
||||
|
||||
# Add "Go Back" button for error cases
|
||||
tk.Button(error_frame, text="Go Back", command=lambda: self.master.switch_frame(Screen0),
|
||||
@ -1245,11 +1309,11 @@ class Screen12(tk.Frame):
|
||||
|
||||
def display_content(self, message_content, image_path, replies):
|
||||
# Main content frame
|
||||
content_frame = tk.Frame(self, bg='#bcfef9')
|
||||
content_frame = tk.Frame(self, bg=BG_COLOR)
|
||||
content_frame.pack(expand=True, fill='both', padx=20, pady=10)
|
||||
|
||||
# Left column: Image
|
||||
left_column = tk.Frame(content_frame, bg='#bcfef9')
|
||||
left_column = tk.Frame(content_frame, bg=BG_COLOR)
|
||||
left_column.pack(side='left', fill='both', expand=False)
|
||||
|
||||
if image_path and os.path.exists(image_path):
|
||||
@ -1257,7 +1321,7 @@ class Screen12(tk.Frame):
|
||||
img = Image.open(image_path)
|
||||
img.thumbnail((550, 550)) # Slightly smaller than before
|
||||
photo = ImageTk.PhotoImage(img)
|
||||
img_label = tk.Label(left_column, image=photo, bg='#bcfef9')
|
||||
img_label = tk.Label(left_column, image=photo, bg=BG_COLOR)
|
||||
img_label.image = photo # Keep a reference
|
||||
img_label.pack(expand=True, fill='both')
|
||||
print(f"Displayed image: {image_path}")
|
||||
@ -1269,12 +1333,12 @@ class Screen12(tk.Frame):
|
||||
print("No image path provided")
|
||||
|
||||
# Right column: Scrollable text
|
||||
right_column = tk.Frame(content_frame, bg='#bcfef9')
|
||||
right_column = tk.Frame(content_frame, bg=BG_COLOR)
|
||||
right_column.pack(side='right', fill='both', padx=10, expand=True)
|
||||
|
||||
canvas = tk.Canvas(right_column, bg='#bcfef9')
|
||||
canvas = tk.Canvas(right_column, bg=BG_COLOR)
|
||||
scrollbar = ttk.Scrollbar(right_column, orient="vertical", command=canvas.yview)
|
||||
scrollable_frame = tk.Frame(canvas, bg='#bcfef9')
|
||||
scrollable_frame = tk.Frame(canvas, bg=BG_COLOR)
|
||||
|
||||
scrollable_frame.bind(
|
||||
"<Configure>",
|
||||
@ -1288,18 +1352,18 @@ class Screen12(tk.Frame):
|
||||
text_content = message_content.get('content', {}).get('text', '')
|
||||
# Remove markdown image syntax
|
||||
text_content = re.sub(r'!\[.*?\]\(.*?\)', '', text_content).strip()
|
||||
tk.Label(scrollable_frame, text=text_content, wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 28)).pack(pady=5, padx=(5, 0))
|
||||
tk.Label(scrollable_frame, text=text_content, wraplength=650, justify='left', bg=BG_COLOR, font=("Helvetica", 28)).pack(pady=5, padx=(5, 0))
|
||||
|
||||
# Display replies
|
||||
if replies:
|
||||
tk.Label(scrollable_frame, text="Replies:", wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 24, "bold")).pack(pady=(20, 5), padx=(5, 0))
|
||||
tk.Label(scrollable_frame, text="Replies:", wraplength=650, justify='left', bg=BG_COLOR, font=("Helvetica", 24, "bold")).pack(pady=(20, 5), padx=(5, 0))
|
||||
for reply in replies:
|
||||
author_id = reply.get('value', {}).get('author', 'Unknown')
|
||||
author_alias = self.get_alias(author_id)
|
||||
author_display = f"{author_alias} ({author_id})" if author_alias else author_id
|
||||
reply_text = reply.get('value', {}).get('content', {}).get('text', '')
|
||||
tk.Label(scrollable_frame, text=f"{author_display}:", wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 20, "bold")).pack(pady=(10, 0), padx=(5, 0))
|
||||
tk.Label(scrollable_frame, text=reply_text, wraplength=650, justify='left', bg='#bcfef9', font=("Helvetica", 18)).pack(pady=(0, 10), padx=(5, 0))
|
||||
tk.Label(scrollable_frame, text=f"{author_display}:", wraplength=650, justify='left', bg=BG_COLOR, font=("Helvetica", 20, "bold")).pack(pady=(10, 0), padx=(5, 0))
|
||||
tk.Label(scrollable_frame, text=reply_text, wraplength=650, justify='left', bg=BG_COLOR, font=("Helvetica", 18)).pack(pady=(0, 10), padx=(5, 0))
|
||||
|
||||
canvas.pack(side="left", fill="both", expand=True)
|
||||
scrollbar.pack(side="right", fill="y")
|
||||
@ -1316,7 +1380,7 @@ class Screen12(tk.Frame):
|
||||
class Screen13(tk.Frame):
|
||||
def __init__(self, master):
|
||||
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
tk.Frame.__init__(self, master, bg=BG_COLOR)
|
||||
master.add_home_button(self)
|
||||
|
||||
# Create a container to hold the widgets
|
||||
@ -1333,7 +1397,7 @@ class Screen13(tk.Frame):
|
||||
|
||||
# go ahead and print the thing
|
||||
def printy(self):
|
||||
global print_type, migration_ticket, MIGRATION_ITEMS_DIR
|
||||
global print_type
|
||||
|
||||
# Specify the path to your image file
|
||||
path_to_image = "/home/trav/Documents/custodiosk/freeze_frame.jpg"
|
||||
@ -1346,23 +1410,17 @@ class Screen13(tk.Frame):
|
||||
# make ssb post
|
||||
key = addtoDB.addToSSB(path_to_image, info_text, 1)
|
||||
|
||||
# If we have a migration ticket, append the message ID to the description file
|
||||
#if migration_ticket:
|
||||
# description_file_path = os.path.join(MIGRATION_ITEMS_DIR, f"{migration_ticket}.txt")
|
||||
# try:
|
||||
# with open(description_file_path, 'a') as f:
|
||||
# f.write(f"\n\n\n{key}")
|
||||
# print(f"Appended message ID to description file: {description_file_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error appending message ID to description file: {e}")
|
||||
|
||||
# ssb give! (make sure we have a UID to give to first)
|
||||
if GlobalVars.selected_user and GlobalVars.selected_user.strip() != "":
|
||||
nothing = addtoDB.addToSSB(GlobalVars.selected_user, key, 2)
|
||||
|
||||
# gonna need to revise this later but for now the textile tags are always full-size QR:
|
||||
# Calculate QR scale based on print type
|
||||
if print_type == "ribbon":
|
||||
QRscale = 7
|
||||
# Pixel-perfect QR: ribbon_width // 21 for version 1 QR
|
||||
ribbon_width = CONFIG.get("ribbon", {}).get("width", 450)
|
||||
printable_width = ribbon_width - 50 # 25px margin each side
|
||||
QRscale = printable_width // 21
|
||||
# else QRscale stays as set from imported image or master.QRscale
|
||||
|
||||
# Create qr code
|
||||
#from https://ourcodeworld.com/articles/read/554/how-to-create-a-qr-code-image-or-svg-in-python
|
||||
@ -1378,15 +1436,21 @@ class Screen13(tk.Frame):
|
||||
|
||||
# Create an image from the QR Code instance
|
||||
img = qr.make_image()
|
||||
|
||||
# Resize QR to fit layout (handles version auto-upgrade from fit=True)
|
||||
if print_type == "ribbon":
|
||||
target_qr_size = 21 * QRscale # Integer math: 21 * 19 = 399
|
||||
img = img.resize((target_qr_size, target_qr_size), Image.NEAREST)
|
||||
|
||||
whereToSaveQR = 'qr.jpg'
|
||||
img.save(whereToSaveQR)
|
||||
|
||||
# compose image for tag
|
||||
drawing = Image.open("drawing.png") # drawing
|
||||
qr = Image.open("qr.jpg") # qr
|
||||
qr_img = Image.open("qr.jpg") # qr
|
||||
|
||||
#### merge em
|
||||
|
||||
#### merge em
|
||||
|
||||
## if sticker
|
||||
if print_type == "sticker":
|
||||
## if we didn't custom set X/Y, set to defaults
|
||||
@ -1395,21 +1459,49 @@ class Screen13(tk.Frame):
|
||||
QRY=217
|
||||
merged_image = Image.new('L', (675, 375), "white")
|
||||
merged_image.paste(drawing, (0, 8))
|
||||
merged_image.paste(qr, (QRX, QRY+8)) # we add 8 because this is slightly off from when we drew it
|
||||
merged_image.paste(qr_img, (QRX, QRY+8)) # we add 8 because this is slightly off from when we drew it
|
||||
merged_image.save("merged_image.png")
|
||||
|
||||
# if ribbon
|
||||
if print_type == "ribbon":
|
||||
merged_image = Image.new('L', (375, 675), "white")
|
||||
merged_image.paste(drawing, (25, 100)) # set it 25 in because that's the border
|
||||
merged_image.paste(qr, (42, 279)) # paste without mask
|
||||
# Get config values
|
||||
ribbon_width = CONFIG.get("ribbon", {}).get("width", 450)
|
||||
margin = CONFIG.get("ribbon", {}).get("margin", 50)
|
||||
printable_width = ribbon_width - 50 # 25px side margins
|
||||
|
||||
multiplier = {'small': 0.5, 'medium': 1.0, 'large': 1.5}.get(GlobalVars.ribbon_size, 1.0)
|
||||
drawing_height = int(printable_width * multiplier)
|
||||
|
||||
# Load scan-tag image
|
||||
scan_tag = Image.open("scan-tag.png").convert("L")
|
||||
scan_tag_height = scan_tag.height
|
||||
|
||||
# Pixel-perfect QR (sized to printable width)
|
||||
qr_scale = printable_width // 21
|
||||
qr_size = 21 * qr_scale
|
||||
|
||||
# Total label height includes top/bottom margins and scan-tag
|
||||
total_height = margin + drawing_height + scan_tag_height + qr_size + margin
|
||||
|
||||
# Create full-width image with margins
|
||||
merged_image = Image.new('L', (ribbon_width, total_height), "white")
|
||||
# Paste drawing 25px in from left, margin down from top
|
||||
merged_image.paste(drawing, (25, margin))
|
||||
# Paste scan-tag centered below drawing
|
||||
scan_tag_x = (ribbon_width - scan_tag.width) // 2
|
||||
merged_image.paste(scan_tag, (scan_tag_x, margin + drawing_height))
|
||||
# Center QR horizontally within the full ribbon width, below scan-tag
|
||||
qr_x = (ribbon_width - qr_size) // 2
|
||||
merged_image.paste(qr_img, (qr_x, margin + drawing_height + scan_tag_height))
|
||||
merged_image.save("merged_image.png")
|
||||
image = Image.open("merged_image.png")
|
||||
# rotated_image = image.transpose(Image.ROTATE_270) # Transpose and rotate 90 degrees, old version when we weren't doing ribbon vertical
|
||||
# rotated_image.save("merged_image.png")
|
||||
|
||||
# Get the ZPL code for the image
|
||||
zpl_code = tozpl.print_to_zpl("merged_image.png")
|
||||
if print_type == "ribbon":
|
||||
zpl_code = tozpl.print_to_zpl("merged_image.png",
|
||||
print_width=ribbon_width,
|
||||
label_length=total_height)
|
||||
else:
|
||||
zpl_code = tozpl.print_to_zpl("merged_image.png")
|
||||
|
||||
#save the zpl
|
||||
# Open the file in write mode
|
||||
@ -1424,15 +1516,14 @@ class Screen13(tk.Frame):
|
||||
# print to sticker printer
|
||||
if print_type == "sticker":
|
||||
try:
|
||||
result = subprocess.Popen('lpr -P sticker_printer -o raw to_print.zpl', shell=True, stdout=subprocess.PIPE, )
|
||||
# print('no print')
|
||||
result = subprocess.Popen(f'lp -d {CONFIG["printers"]["sticker"]} -o raw to_print.zpl', shell=True, stdout=subprocess.PIPE, )
|
||||
except:
|
||||
print('traceback.format_exc():\n%s' % traceback.format_exc())
|
||||
exit()
|
||||
# or print to tag printer:
|
||||
if print_type == "ribbon":
|
||||
try:
|
||||
result = subprocess.Popen('lpr -P tag-printer -o raw to_print.zpl', shell=True, stdout=subprocess.PIPE, )
|
||||
result = subprocess.Popen(f'lp -d {CONFIG["printers"]["ribbon"]} -o raw to_print.zpl', shell=True, stdout=subprocess.PIPE, )
|
||||
except:
|
||||
print('traceback.format_exc():\n%s' % traceback.format_exc())
|
||||
exit()
|
||||
@ -1481,7 +1572,7 @@ class Screen14(tk.Frame):
|
||||
|
||||
self.qreader = QReader()
|
||||
# Prefer the external NexiGo USB webcam when available
|
||||
self.cap = cv2.VideoCapture(get_preferred_camera_index("NexiGo"))
|
||||
self.cap = cv2.VideoCapture(get_preferred_camera_index(CONFIG["camera"]["preferred_name"]))
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
|
||||
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
|
||||
|
||||
@ -1524,59 +1615,6 @@ class Screen14(tk.Frame):
|
||||
super().destroy()
|
||||
|
||||
|
||||
|
||||
|
||||
# New screen for Create Migration Item
|
||||
class Screen15(tk.Frame):
|
||||
def __init__(self, master):
|
||||
|
||||
tk.Frame.__init__(self, master, bg='#bcfef9')
|
||||
|
||||
# Create a main container frame
|
||||
main_frame = tk.Frame(self, bg='#bcfef9')
|
||||
main_frame.place(relx=0.5, rely=0.5, anchor='center')
|
||||
|
||||
# Add the home button to the main frame (this will be at the top)
|
||||
master.add_home_button(self)
|
||||
|
||||
# Instructions (now in the centered main frame)
|
||||
tk.Label(main_frame, text="If you're archiving an Item of Migration, please enter the last 3 digits of your ticket number. Otherwise, you can leave this blank.", font=GlobalVars.TEXT_FONT, bg='#bcfef9', wraplength=500).pack(pady=20)
|
||||
|
||||
# Text box for entering ticket number (now in the centered main frame)
|
||||
self.ticket_entry = tk.Entry(main_frame, font=GlobalVars.TEXT_FONT)
|
||||
self.ticket_entry.pack(pady=20)
|
||||
|
||||
# Done button (now in the centered main frame)
|
||||
tk.Button(main_frame, text="Done", command=self.process_ticket, height=3, width=30, bg='peach puff', font=GlobalVars.BUTTON_FONT).pack(pady=20)
|
||||
|
||||
# Set focus to the ticket entry field
|
||||
self.ticket_entry.focus_set()
|
||||
|
||||
def process_ticket(self):
|
||||
global migration_ticket
|
||||
ticket = self.ticket_entry.get().strip()
|
||||
|
||||
if ticket == "":
|
||||
# If the field is blank, proceed without setting migration_ticket
|
||||
migration_ticket = ""
|
||||
self.master.switch_frame(Screen1) # Go to the Scuttlebutt username selection screen
|
||||
elif re.match(r'^\d{1,4}$', ticket):
|
||||
if self.is_ticket_available(ticket):
|
||||
migration_ticket = ticket
|
||||
self.master.switch_frame(Screen1) # Go to the Scuttlebutt username selection screen
|
||||
else:
|
||||
messagebox.showerror("Invalid Input", "This migration number is already in use. Please try a different number.")
|
||||
else:
|
||||
messagebox.showerror("Invalid Input", "Please check your number and try again. It should be a 1-4 digit number or left blank.")
|
||||
|
||||
def is_ticket_available(self, ticket):
|
||||
# Get all files in the migration items directory
|
||||
files = os.listdir(MIGRATION_ITEMS_DIR)
|
||||
|
||||
# Strip file extensions and check if the ticket number exists
|
||||
existing_numbers = [os.path.splitext(f)[0] for f in files]
|
||||
return ticket not in existing_numbers
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = Kiosk()
|
||||
app.mainloop()
|
||||
|
||||
Reference in New Issue
Block a user