Untitled

Anonymous
plain_text
01/26/2026 5:23 AM
14.6 KB
15
Indexable
#!/usr/bin/env python3
import tkinter as tk
from tkinter import ttk, messagebox
import subprocess
import os
import sys
import threading
import psutil

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
os.chdir(BASE_DIR)


# ================== HIDE TERMINAL ==================
def hide_terminal():
    """Hide terminal window"""
    if sys.platform.startswith('linux'):
        try:
            # Try to hide terminal
            subprocess.run(['xdotool', 'search', '--pid', str(os.getpid()), 
                          'windowminimize'], capture_output=True)
        except:
            pass

# Call hide terminal function
if __name__ == "__main__":
    # Wait a moment then hide terminal
    import time
    time.sleep(1)
    hide_terminal()
    
class ProgramLauncher:
    def __init__(self, root):
        self.root = root
        self.root.title("UCC Scale Program Launcher")
        self.root.geometry("400x300")
        self.root.configure(bg='#f0f0f0')
        
        self.launcher_hidden = False
        self.monitoring_process = None
        
        # Setup keyboard bindings
        self.setup_keyboard_bindings()
        
        self.center_window_on_primary_monitor()
        self.root.resizable(False, False)
        
        self.setup_ui()
        
        # Handle window close - HIDE not quit
        self.root.protocol("WM_DELETE_WINDOW", self.hide_to_tray)
        
        # Auto-focus
        self.root.after(100, self.root.lift)
        self.root.after(100, self.root.focus_force())
        
    def setup_keyboard_bindings(self):
        self.root.bind_all('<F12>', self.show_from_tray)
        self.root.bind_all('<h>', self.hide_to_tray)
        self.root.bind_all('<H>', self.hide_to_tray)
        # Tambah binding untuk Ctrl+H
        self.root.bind_all('<Control-h>', self.hide_to_tray)
        self.root.bind_all('<Control-H>', self.hide_to_tray)
        
    def center_window_on_primary_monitor(self):
        """Center window on primary monitor (not all monitors combined)"""
        self.root.update_idletasks()
        
        # Get window dimensions
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        
        # Get screen dimensions of primary monitor
        # Method 1: Use screen width/height (should give primary monitor)
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        
        # Method 2: Alternative approach - place window at position relative to mouse
        # This tends to place it on the monitor where mouse currently is
        pointer_x = self.root.winfo_pointerx()
        pointer_y = self.root.winfo_pointery()
        
        # Calculate position to center on screen where mouse is
        # If mouse is on primary monitor (usually x < screen_width), use primary monitor
        # Otherwise adjust for secondary monitor
        if pointer_x < screen_width:  # Primary monitor
            x = (screen_width - width) // 2
            y = (screen_height - height) // 2
        else:  # Secondary monitor (assuming horizontal setup)
            # Calculate position for secondary monitor
            x = pointer_x - (width // 2)
            y = (screen_height - height) // 2
            
            # Ensure window doesn't go off screen
            if x + width > screen_width * 2:  # Assuming two monitors of same width
                x = screen_width + (screen_width - width) // 2
            if y + height > screen_height:
                y = (screen_height - height) // 2
        
        # OR simpler: Always place on primary monitor
        # Uncomment the following lines for simpler approach
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
        
        self.root.geometry(f'{width}x{height}+{x}+{y}')
        
    def setup_ui(self):
        # Title
        title_label = tk.Label(
            self.root,
            text="PROGRAM LAUNCHER",
            font=("Arial", 18, "bold"),
            bg='#f0f0f0',
            fg='#2c3e50'
        )
        title_label.pack(pady=20)
        
        # Subtitle
        subtitle_label = tk.Label(
            self.root,
            text="Select UCC type to Scan:",
            font=("Arial", 11),
            bg='#f0f0f0',
            fg='#34495e'
        )
        subtitle_label.pack(pady=5)
        
        # Frame for buttons
        button_frame = tk.Frame(self.root, bg='#f0f0f0')
        button_frame.pack(pady=30)
        
        # Button Program 1
        self.btn_program1 = tk.Button(
            button_frame,
            text="UCC Shipping",
            command=self.run_program1,
            bg='#3498db',
            fg='white',
            font=("Arial", 12, "bold"),
            width=15,
            height=2,
            relief=tk.RAISED,
            cursor="hand2"
        )
        self.btn_program1.grid(row=0, column=0, padx=20, pady=10)
        
        # Button Program 2
        self.btn_program2 = tk.Button(
            button_frame,
            text="UCC Non Shipping",
            command=self.run_program2,
            bg='#2ecc71',
            fg='white',
            font=("Arial", 12, "bold"),
            width=15,
            height=2,
            relief=tk.RAISED,
            cursor="hand2"
        )
        self.btn_program2.grid(row=0, column=1, padx=20, pady=10)
        
        # Hide/Show Button
        self.btn_toggle = tk.Button(
            self.root,
            text="⇲ Hide to Tray",
            command=self.toggle_window,
            bg='#f39c12',
            fg='white',
            font=("Arial", 10, "bold"),
            width=15,
            height=1
        )
        self.btn_toggle.pack(pady=10)
        
        # Hotkey info
        hotkey_label = tk.Label(
            self.root,
            text="F12 = Show Window | Ctrl+H = Hide",
            font=("Arial", 9),
            bg='#f0f0f0',
            fg='#7f8c8d'
        )
        hotkey_label.pack()
        
        # Quit Button
        self.btn_quit = tk.Button(
            self.root,
            text="QUIT",
            command=self.quit_program,
            bg='#e74c3c',
            fg='white',
            font=("Arial", 12, "bold"),
            width=15,
            height=2,
            relief=tk.RAISED,
            cursor="hand2"
        )
        self.btn_quit.pack(pady=20)
        
        # Status bar
        self.status_label = tk.Label(
            self.root,
            text="Status: Ready (Press F12 if window hidden)",
            font=("Arial", 9),
            bg='#f0f0f0',
            fg='#7f8c8d',
            bd=1,
            relief=tk.SUNKEN,
            anchor=tk.W
        )
        self.status_label.pack(side=tk.BOTTOM, fill=tk.X, padx=5, pady=5)
        
    def hide_to_tray(self, event=None):
        if not self.launcher_hidden:
            self.launcher_hidden = True

            # Move window off-screen (NOT minimize)
            self.root.geometry("1x1+-1000+-1000")  # Changed to -1000 to ensure off-screen

            self.btn_toggle.config(text="⇱ Show Window (F12)")
            self.status_label.config(text="Status: Hidden - Press F12")

            
    def show_from_tray(self, event=None):
        if self.launcher_hidden:
            self.launcher_hidden = False

            # Reset to normal size and position on primary monitor
            self.root.geometry("400x300")
            self.center_window_on_primary_monitor()
            self.root.lift()
            self.root.focus_force()

            self.btn_toggle.config(text="⇲ Hide to Tray")
            self.status_label.config(text="Status: Ready")
            
    def toggle_window(self):
        """Toggle hide/show window"""
        if self.launcher_hidden:
            self.show_from_tray()
        else:
            self.hide_to_tray()
            
    def hide_launcher(self):
        """Hide launcher (when another program is running)"""
        if not self.launcher_hidden:
            self.hide_to_tray()
            
    def show_launcher(self):
        """Show launcher again"""
        if self.launcher_hidden:
            self.show_from_tray()
            
    def monitor_program(self, pid, program_name):
        """Monitor if program is still running"""
        try:
            process = psutil.Process(pid)
            process.wait()  # Wait until process finishes
            
            # Program has been closed, show launcher again
            self.root.after(100, self.show_launcher)
            self.status_label.config(text="Status: Program finished")
            
        except psutil.NoSuchProcess:
            self.root.after(100, self.show_launcher)
            self.status_label.config(text="Status: Program finished")
        except Exception as e:
            self.root.after(100, self.show_launcher)
            
    def run_program(self, filename, program_name):
        try:
            if not os.path.exists(filename):
                messagebox.showerror("Error", f"File {filename} not found!")
                self.status_label.config(text=f"Status: File {filename} not found")
                return
            
            self.status_label.config(text=f"Status: Running {program_name}...")
            self.root.update()
            
            process = subprocess.Popen(
                [sys.executable, filename],
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
                start_new_session=True
            )
            
            self.hide_launcher()
            self.status_label.config(text=f"Status: {program_name} is running...")
            
            monitor_thread = threading.Thread(
                target=self.monitor_program,
                args=(process.pid, program_name),
                daemon=True
            )
            monitor_thread.start()
            
        except Exception as e:
            messagebox.showerror("Error", f"Failed to run {program_name}: {str(e)}")
            self.status_label.config(text=f"Status: Error - {str(e)}")
            
    def run_program1(self):
        self.run_program("shipping.py", "UCC Shipping")
        
    def run_program2(self):
        self.run_program("non_shipping.py", "UCC Non Shipping")
        
    def quit_program(self):
        if messagebox.askyesno("Confirmation", "Are you sure you want to quit?"):
            self.status_label.config(text="Status: Exiting...")
            self.root.quit()
            self.root.destroy()
            sys.exit()

def main():
    # Check if psutil is installed
    try:
        import psutil
    except ImportError:
        print("psutil not found. Installing...")
        subprocess.run([sys.executable, "-m", "pip", "install", "psutil", "--break-system-packages"])
        import psutil
    
    root = tk.Tk()
    app = ProgramLauncher(root)
    root.mainloop()

if __name__ == "__main__":
    main()
Editor is loading...
Leave a Comment