From 039b9ee90db7f7df85e635b6f4534552bad1692a Mon Sep 17 00:00:00 2001 From: Andrew Ward Date: Sat, 22 Mar 2025 10:50:16 +0000 Subject: [PATCH] improvements to AI copyediting ux --- utils/__pycache__/text_to_mic.cpython-312.pyc | Bin 74030 -> 77389 bytes utils/text_to_mic.py | 99 +++++++++++++----- 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/utils/__pycache__/text_to_mic.cpython-312.pyc b/utils/__pycache__/text_to_mic.cpython-312.pyc index 77126aad0f849fe9c4fd38f678d5b61160403aa6..2bfee428e31c17dd55e7005f8f5e24b8b42e0015 100644 GIT binary patch delta 12551 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 delta 10040 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 diff --git a/utils/text_to_mic.py b/utils/text_to_mic.py index 1cc6b02..f7a6d15 100644 --- a/utils/text_to_mic.py +++ b/utils/text_to_mic.py @@ -55,8 +55,8 @@ class TextToMic(tk.Tk): self.BASE_WIDTH = 590 self.BASE_HEIGHT_WITH_BANNER = 860 self.BASE_HEIGHT_NO_BANNER = 700 - self.COLLAPSED_HEIGHT_WITH_BANNER = 622 - self.COLLAPSED_HEIGHT_NO_BANNER = 510 + self.COLLAPSED_HEIGHT_WITH_BANNER = 630 + self.COLLAPSED_HEIGHT_NO_BANNER = 512 # Initial window geometry self.geometry(f"{self.BASE_WIDTH}x{self.BASE_HEIGHT_WITH_BANNER}") @@ -172,7 +172,7 @@ class TextToMic(tk.Tk): settings_menu = Menu(self.menubar, tearoff=0) self.menubar.add_cascade(label="Settings", menu=settings_menu) settings_menu.add_command(label="Change API Key", command=self.change_api_key) - settings_menu.add_command(label="ChatGPT Manipulation", command=self.chat_gpt_settings) + settings_menu.add_command(label="AI Copy Editing", command=self.chat_gpt_settings) settings_menu.add_command(label="Hotkey Settings", command=self.show_hotkey_settings) settings_menu.add_command(label="Manage Tone Presets", command=self.show_tone_presets_manager) @@ -356,12 +356,12 @@ class TextToMic(tk.Tk): # Text to Read section with proper layout text_read_frame = ttk.Frame(main_frame) - text_read_frame.grid(column=0, row=4, columnspan=2, sticky="ew", pady=(0, 10)) + text_read_frame.grid(column=0, row=4, columnspan=2, sticky="ew", pady=(10, 0)) text_read_frame.columnconfigure(0, weight=1) # Left side expands text_read_frame.columnconfigure(1, weight=0) # Right side fixed width - # Text to Read label - ttk.Label(text_read_frame, text="Text to Read:").grid(column=0, row=0, sticky=tk.W) + # Text to Read label - Updated to match other section titles + ttk.Label(text_read_frame, text="Text to Read", font=("Arial", 10, "bold")).grid(column=0, row=0, sticky=tk.W, pady=(0, 10)) # Create a frame to contain the dropdown and save button save_frame = ttk.Frame(text_read_frame) @@ -387,6 +387,24 @@ class TextToMic(tk.Tk): self.text_input.configure(bg="white", fg=text_color, insertbackground=text_color, wrap=tk.WORD) self.text_input.grid(column=0, row=5, columnspan=2, pady=(0, 20), sticky="nsew") # Proper spacing + # Add a status frame at the bottom of the text input with white background + status_frame = ttk.Frame(main_frame, style='White.TFrame') + status_frame.grid(column=0, row=5, columnspan=2, sticky=(tk.S, tk.E), pady=(0, 25)) + + # Create a custom style for the white frame + self.style.configure('White.TFrame', background='white') + + # Status indicator showing if editing is enabled + status_text = "AI Copyediting Disabled" + if settings.get("chat_gpt_completion", False): + if settings.get("auto_apply_ai_to_recording", False): + status_text = f"AI Copyediting Enabled (Auto) - {settings.get('model', self.default_model)}" + else: + status_text = f"AI Copyediting Enabled (Manual) - {settings.get('model', self.default_model)}" + + self.editing_status = ttk.Label(status_frame, text=status_text, foreground="#888888", font=("Arial", 8, "italic"), background="white") + self.editing_status.pack(side=tk.RIGHT, padx=5) + # Create a frame for the buttons to allow for better styling button_frame = ttk.Frame(main_frame) button_frame.grid(column=0, row=6, columnspan=2, sticky="ew", pady=(0, 20)) @@ -976,42 +994,62 @@ Please also make sure you read the Terms of use and licence statement before usi def chat_gpt_settings(self): settings = self.load_settings() settings_window = tk.Toplevel(self) - settings_window.title("ChatGPT Manipulation Settings") + settings_window.title("AI Copy Editing Settings") settings_window.grab_set() # Grab the focus on this toplevel window + settings_window.geometry("600x420") # Slightly larger to accommodate explanation text main_frame = ttk.Frame(settings_window, padding="10") main_frame.grid(column=0, row=0, sticky=(tk.W, tk.E, tk.N, tk.S)) + settings_window.columnconfigure(0, weight=1) + settings_window.rowconfigure(0, weight=1) + main_frame.columnconfigure(1, weight=1) # Make the second column expandable # Use the ttk style for uniformity style = ttk.Style() style.theme_use('clam') + # Add explanation text at the top + explanation_text = "This feature allows automatic editing of text using AI. When enabled, text will be refined according to your rules below. Please be aware that enabling this setting will increase the latency of the application." + + explanation_label = ttk.Label(main_frame, text=explanation_text, wraplength=550) + explanation_label.grid(row=0, column=0, columnspan=2, sticky=tk.W, pady=(0, 10)) + + # Move the checkbox to the second column to align with other input fields enable_completion = tk.BooleanVar(value=settings.get("chat_gpt_completion", False)) - ttk.Checkbutton(main_frame, text="Enable ChatGPT Completion", variable=enable_completion).grid(row=0, column=1, sticky=tk.W, pady=2) - - # Model selection# - + ttk.Label(main_frame, text="Enable AI Copy Editing:").grid(row=1, column=0, sticky=tk.W, pady=2) + ttk.Checkbutton(main_frame, text="", variable=enable_completion).grid(row=1, column=1, sticky=tk.W, pady=2) + # Model selection model_var = tk.StringVar(value=settings.get("model", self.default_model)) - ttk.Label(main_frame, text="Model:").grid(row=1, column=0, sticky=tk.W, pady=2) + ttk.Label(main_frame, text="Model:").grid(row=2, column=0, sticky=tk.W, pady=2) model_menu = ttk.OptionMenu(main_frame, model_var, model_var.get(), *self.available_models) - model_menu.grid(row=1, column=1, sticky=tk.W, pady=2) + model_menu.grid(row=2, column=1, sticky=(tk.W, tk.E), pady=2) - # Max Tokens selection + # Max Tokens selection - expanded options max_tokens_var = tk.IntVar(value=settings.get("max_tokens", 750)) - ttk.Label(main_frame, text="Max Tokens:").grid(row=2, column=0, sticky=tk.W, pady=2) - max_tokens_menu = ttk.OptionMenu(main_frame, max_tokens_var, 750, 100, 250, 500, 750, 1000, 1250, 1500) - max_tokens_menu.grid(row=2, column=1, sticky=tk.W, pady=2) + ttk.Label(main_frame, text="Max Tokens:").grid(row=3, column=0, sticky=tk.W, pady=2) + max_tokens_menu = ttk.OptionMenu(main_frame, max_tokens_var, max_tokens_var.get(), + 100, 250, 500, 750, 1000, 1250, 1500, 2000, 3000, 4000, 5000) + max_tokens_menu.grid(row=3, column=1, sticky=(tk.W, tk.E), pady=2) - # Prompt entry as a Text area - ttk.Label(main_frame, text="Prompt:").grid(row=3, column=0, sticky=tk.NW, pady=2) - prompt_entry = tk.Text(main_frame, height=4, width=40) - prompt_entry.insert('1.0', settings.get("prompt", "")) - prompt_entry.grid(row=3, column=1, sticky=tk.W, pady=2) + # Prompt entry renamed to "Copy Editing Rules" with a Text area + ttk.Label(main_frame, text="Copy Editing Rules:").grid(row=4, column=0, sticky=tk.NW, pady=2) + prompt_entry = tk.Text(main_frame, height=8, width=50) + + # Default prompt example if none exists + default_prompt = "Edit the text provided to ensure it has a clear, professional tone. Fix any grammatical errors, improve sentence structure, and maintain consistent formatting. Make the language concise and impactful while preserving the original meaning. Make sure to edit text only and do not reply to it." + + prompt_entry.insert('1.0', settings.get("prompt", default_prompt)) + prompt_entry.grid(row=4, column=1, sticky=(tk.W, tk.E), pady=2) - # Auto-apply checkbox + # Auto-apply checkbox - moved to second column with clear label auto_apply = tk.BooleanVar(value=settings.get("auto_apply_ai_to_recording", False)) - ttk.Checkbutton(main_frame, text="Auto Apply to Recorded Transcript", variable=auto_apply).grid(row=4, column=1, sticky=tk.W, pady=2) + ttk.Label(main_frame, text="Auto Apply to Recordings:").grid(row=5, column=0, sticky=tk.W, pady=2) + ttk.Checkbutton(main_frame, text="", variable=auto_apply).grid(row=5, column=1, sticky=tk.W, pady=2) + + # Add a label explaining the auto-apply setting + auto_apply_explanation = "When checked, recordings will be automatically copy edited according to your rules above" + ttk.Label(main_frame, text=auto_apply_explanation, foreground="#666666", wraplength=450).grid(row=6, column=1, sticky=tk.W, pady=(0, 10)) # Save Button save_btn = ttk.Button(main_frame, text="Save", command=lambda: self.save_chat_gpt_settings({ @@ -1021,12 +1059,23 @@ Please also make sure you read the Terms of use and licence statement before usi "auto_apply_ai_to_recording": auto_apply.get(), "max_tokens": max_tokens_var.get() })) - save_btn.grid(row=5, column=1, sticky=tk.W + tk.E, pady=10) + save_btn.grid(row=7, column=0, columnspan=2, sticky=tk.E, pady=10) def save_chat_gpt_settings(self, settings): self.save_settings_to_JSON(settings) messagebox.showinfo("Settings Updated", "Your settings have been saved successfully.") self.load_settings() # Refresh settings if needed elsewhere + + # Update the status indicator on the main screen with more specific information + status_text = "AI Copyediting Disabled" + if settings.get("chat_gpt_completion", False): + if settings.get("auto_apply_ai_to_recording", False): + status_text = f"AI Copyediting Enabled (Auto) - {settings.get('model', self.default_model)}" + else: + status_text = f"AI Copyediting Enabled (Manual) - {settings.get('model', self.default_model)}" + + if hasattr(self, 'editing_status'): + self.editing_status.config(text=status_text) def apply_ai(self, input_text=None):