From 450a58a7d88cec61eb52286baf5b6b0c5840c9df Mon Sep 17 00:00:00 2001 From: Andrew Ward Date: Fri, 21 Mar 2025 19:12:17 +0000 Subject: [PATCH] implement banner showing and hiding --- .../presets_manager.cpython-312.pyc | Bin 32551 -> 34097 bytes utils/__pycache__/text_to_mic.cpython-312.pyc | Bin 58642 -> 62971 bytes utils/presets_manager.py | 58 ++++++-- utils/text_to_mic.py | 135 ++++++++++++++++-- 4 files changed, 175 insertions(+), 18 deletions(-) diff --git a/utils/__pycache__/presets_manager.cpython-312.pyc b/utils/__pycache__/presets_manager.cpython-312.pyc index f61c29d2d327c1005325affbce6cd4e6adcad0f5..ef4d15fba45683caeb23155916aa6e72dd486d75 100644 GIT binary patch delta 4716 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 delta 3574 zcmaJ@3s6+o8Q!yZcUg9q=Psb~x+@?oWJH97_%=aQL(=?qS<|WSL(X`tCzdV$*(=)T* z`Okm;=RN=V&z{<+KYEqLzZMr~(cu_7`L4Ige=7cq7|U14*rR()7iO?7FGDFbS1~pd zScM%DVzXkHB%ClG7ho{f1I3mSxM;D0x77}fmYTRkvP7d_w@rlTZ2Od+MY&|z%9scP zd^)v?+6>Vy9ijn0$hnU4m)|`6L-$vA=5MWf(Q=cQ{!YJnJYoSK-p7 z=d0mk$1SW($w_fBwjXLz4;C4Mp5``{RjRC3W$V@0u&2r0!aaUjWevO()l^e^M@L&{ zkk^Af?Ic?ducm#&vf(!~c8iI+*tijMdeodgViu!j@krBA?|^skwqM?M&MXd_mn!ni z#m4j=GGgwxZ&ZU-DJvcj3dbY-aM@A?dq=1&u>Kp5SL;4-R0pwrLS!_ZujJpg~3yPdtG)EB?N zoX50n{w&G25&VSUB*7rTDY&U5$UcNaC7;e+j||n^1^Ec6?ms?SI&(>ze1t^ZE_V1-JDZO?zxkIY)&58&xt`fXyG?5Up^lGJ;=GI2nI`w z*jq})EsCDK4A;tLLgIprrUu%Z3yljipnpNK{;CcREvRPgFuEW=aSNIA5Nsyc3gW`F z-20GJg=SBfpVp|Ra3Ewvs!_x-?r$e-Ug%_BDBTNtSq_~Uk09Vj)9Q-U#y`}A_z;MT zb6AYBV)09?q!)Kf&iuCozayAQu$v%>;C_PF2>M{&(yU|(YMRXmG%hV-ams^B zRWoMmUA1c_`Q?8?sC6;!z!|%Oe(pSe7QR`vfz5$+t1ITOME2-|B&gLJNsXFm*-N0^ zmJ+0n=~d$npA>H8tKj#mi&6l2XtWfkdY6IUO2SoOsw!iT!J?{})(ga-UH&wZ_vs;Avwg)lEgm%Oy}$j=efm}U=` z+&*c%g?&W)OT@SB;GSSmmfT@^XPAFX{7*Fb7SG*opWn+rCDvyMp)`a>xLoUqpDgOv zk#i3|YSki3SLWaGN5cy8#s5q|dU*cDG#SR@zn&ds;xcMUaDibM1`1D$lpCRVM_Yy_@ubhFK{wc&QQ5e6Dc*{( zPG(?6aqZ%&@sixs(TT5<MMNm@Ca@qslsIJxe-*3OBwCCGfoLWMeQQudteMPr%=m)A(d{&(iaU z!I_x~hqq_I)z)J8X^WF}!R6Q#{k8aOib6M+m=G4f$0K2 zBX#|@G+JvGk}P&u?n`i_qZ4g}GbSm`FtoHf;B||mR1%J3@-!x25nbO{G_hlFm!w7>>8#KP09vq3PV!WV7vhKSK+g7)@hb!_Ko0xH+Kl6eZw zd=mj(F5XC>-3$szYlW)WD|h&@Cq&dlNpA6Uwujx59Ikb;2)O;Je!=evYEPk>+!+XW zc)jg-np1)qbk+}{&B;R5I@T&=s0kivTW2VY(yiJ*3pHtqF{!Tge`@~|72t;A!0eQ- zs50yby}FCmgb}OrFIMLTXbH?KzhFyzsJg#;#3n{<;$g?p^nvsd=aQ&%$*^tdMO)&C zEjMb*9k$KU=z^%N;JmF6X=v;y?lJ2!#UsMu`lFi%Hjm_0MDr>}@~WbFRe#8NBd_+2 zj63>k_EsLay-C`&og{19_25ko^c2Fg=N*iWsk%Y zAvYqjl~5UJ!4_~LvYcfrpG02K*R3Vv>j<>Q&QufrbCCmKx~+EdPPX_)GH8%G{lUpQ z+DL3S!t^^@4%fOwwp5qv=KA%PZX z38m_$*HNhw@kLk4P;V^W+z3>n+`gE7|g3&x?$u=$&|3>wf^>a>ykB diff --git a/utils/__pycache__/text_to_mic.cpython-312.pyc b/utils/__pycache__/text_to_mic.cpython-312.pyc index 306f4a5e7bc873577669bd46b691bd6c422206e7..b7717250a44f4254e33ea3faeebcca19c1740783 100644 GIT binary patch delta 11245 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 delta 8181 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 UNo5UeyWxKGz2?i3=!mucA4yg;_5c6? diff --git a/utils/presets_manager.py b/utils/presets_manager.py index f60f373..c206520 100644 --- a/utils/presets_manager.py +++ b/utils/presets_manager.py @@ -63,7 +63,8 @@ class PresetsManager: command=self.toggle_presets, style="Flat.TButton" ) - self.presets_button.pack(side=tk.LEFT, padx=0, pady=2) + # Use grid instead of pack for the button to avoid mixing layout managers + self.presets_button.grid(column=0, row=0, sticky=tk.W, padx=0, pady=2) # Make presets frame expandable self.presets_frame.grid(column=0, row=7, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S)) @@ -159,7 +160,7 @@ class PresetsManager: """Adjust row weights to prioritize presets area expansion.""" # Store current weights if we haven't already if not self.original_row_weights: - for i in range(7): # Store weights for rows 0-6 (main content area) + for i in range(8): # Store weights for all relevant rows (0-7) self.original_row_weights[i] = self.parent.grid_rowconfigure(i, "weight") # Set all main content rows to have weight 0 (fixed height) @@ -177,6 +178,9 @@ class PresetsManager: # Reset presets row weight self.parent.grid_rowconfigure(7, weight=0) + + # Ensure toggle button row is properly weighted + self.parent.grid_rowconfigure(6, weight=0) def setup_preset_card_styles(self, bg_color, accent_color): """Set up common styles for preset cards once to avoid recreating them repeatedly.""" @@ -504,30 +508,64 @@ class PresetsManager: def toggle_presets(self): """Toggle the visibility of the presets panel.""" if self.presets_collapsed: + # EXPANDING presets self.presets_frame.grid() # Update button icon to down chevron while preserving text self.presets_button.configure(image=self.chevron_down, text=" Presets") - self.parent.geometry(self.parent.default_geometry) + + # Use parent's class constants for geometry instead of old properties + banner_hidden = self.parent.banner_var.get() if hasattr(self.parent, 'banner_var') else False + + # Calculate a width that preserves the current width if it's larger than default + current_width = self.parent.winfo_width() + width_to_use = max(current_width, self.parent.BASE_WIDTH) + + if banner_hidden: + self.parent.geometry(f"{width_to_use}x{self.parent.BASE_HEIGHT_NO_BANNER}") + else: + self.parent.geometry(f"{width_to_use}x{self.parent.BASE_HEIGHT_WITH_BANNER}") + # Adjust row weights to give all expansion space to presets self._adjust_row_weights() + # Refresh the presets display to adjust for the new window size self.refresh_presets_display() else: + # COLLAPSING presets self.presets_frame.grid_remove() # Update button icon to right chevron while preserving text self.presets_button.configure(image=self.chevron_right, text=" Presets") - # Add extra padding to the untoggled geometry to prevent button from being cut off - # Parse the current untoggled geometry - width, height = map(int, self.parent.untoggled_geometry.split('x')) - # Add 15 pixels to the height to prevent button cutoff - adjusted_height = height + 15 - adjusted_geometry = f"{width}x{adjusted_height}" + # Use parent's class constants for geometry + banner_hidden = self.parent.banner_var.get() if hasattr(self.parent, 'banner_var') else False + + # Calculate a width that preserves the current width if it's larger than default + current_width = self.parent.winfo_width() + width_to_use = max(current_width, self.parent.BASE_WIDTH) + + # Always ensure minimum height based on constants regardless of previous manual resizing + if banner_hidden: + # Ensure the minimum height without banner + minimum_height = self.parent.COLLAPSED_HEIGHT_NO_BANNER + self.parent.geometry(f"{width_to_use}x{minimum_height}") + else: + # Ensure the minimum height with banner + minimum_height = self.parent.COLLAPSED_HEIGHT_WITH_BANNER + self.parent.geometry(f"{width_to_use}x{minimum_height}") - self.parent.geometry(adjusted_geometry) # Restore original row weights self._restore_row_weights() + + # Force re-grid of toggle button to ensure it's properly positioned + if hasattr(self, 'presets_button') and self.presets_button.winfo_exists(): + self.presets_button.grid_configure(column=0, row=0, sticky=tk.W, padx=0, pady=2) + + # Update tracking of collapsed state self.presets_collapsed = not self.presets_collapsed + + # Update parent's tracking variable + if hasattr(self.parent, 'presets_collapsed'): + self.parent.presets_collapsed = self.presets_collapsed def save_current_text_as_preset(self): """Save current text to the selected category as a preset.""" diff --git a/utils/text_to_mic.py b/utils/text_to_mic.py index 5b47954..d429c08 100644 --- a/utils/text_to_mic.py +++ b/utils/text_to_mic.py @@ -35,9 +35,17 @@ class TextToMic(tk.Tk): super().__init__() self.title("Scorchsoft Text to Mic") - self.default_geometry = "590x890" - self.untoggled_geometry ="590x610" - self.geometry(self.default_geometry) + + # Fixed window dimensions for all states - DEFINED ONCE as class constants + # These are the ONLY values that should be used throughout the application + 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 + + # Initial window geometry + self.geometry(f"{self.BASE_WIDTH}x{self.BASE_HEIGHT_WITH_BANNER}") self.available_models = ["gpt-4o-mini", "gpt-4o", "gpt-4-turbo"] self.default_model = "gpt-4o-mini" @@ -103,8 +111,16 @@ class TextToMic(tk.Tk): # Create the category variable for the dropdown self.category_var = tk.StringVar(value="Select Category") + # Add toggle for banner visibility before presets manager initialization + self.banner_var = tk.BooleanVar() + settings = self.load_settings() + self.banner_var.set(settings.get("hide_banner", False)) + # Create the presets manager before initializing the GUI self.presets_manager = PresetsManager(self) + + # Store reference to presets state + self.presets_collapsed = self.presets_manager.presets_collapsed # Create menu and initialize GUI after presets manager is created self.create_menu() @@ -112,6 +128,10 @@ class TextToMic(tk.Tk): # Initialize our HotkeyManager self.hotkey_manager = HotkeyManager(self) + + # If banner should be hidden based on settings, hide it now + if self.banner_var.get(): + self.toggle_banner() def ensure_config_directory(self): """Ensure the config directory exists.""" @@ -160,6 +180,9 @@ class TextToMic(tk.Tk): help_menu.add_command(label="Terms of Use and Licence", command=self.show_terms_of_use) help_menu.add_command(label="Version", command=self.show_version) help_menu.add_command(label="Hotkey Instructions", command=self.show_hotkey_instructions) + + # Add toggle for banner visibility - use the existing banner_var from __init__ + help_menu.add_checkbutton(label="Hide Banner", variable=self.banner_var, command=self.toggle_banner) def show_hotkey_settings(self): """Show the hotkey settings dialog.""" @@ -372,20 +395,27 @@ class TextToMic(tk.Tk): #Credits # Banner image that links to Scorchsoft + self.banner_frame = ttk.Frame(main_frame) + self.banner_frame.grid(column=0, row=7, columnspan=2, pady=(10, 10)) + banner_path = self.resource_path("assets/ss-banner-550.png") try: banner_img = tk.PhotoImage(file=banner_path) - banner_label = tk.Label(main_frame, image=banner_img, cursor="hand2") + banner_label = tk.Label(self.banner_frame, image=banner_img, cursor="hand2") banner_label.image = banner_img # Keep a reference to prevent garbage collection - banner_label.grid(column=0, row=7, columnspan=2, pady=(10, 10)) + banner_label.pack() banner_label.bind("", lambda e: self.open_scorchsoft()) except Exception as e: print(f"Error loading banner image: {e}") # Fallback to text if image fails to load - info_label = tk.Label(main_frame, text="Visit Scorchsoft.com for custom app development", - fg="blue", cursor="hand2") - info_label.grid(column=0, row=7, columnspan=2, pady=(10, 10)) + info_label = tk.Label(self.banner_frame, text="Visit Scorchsoft.com for custom app development", + fg="blue", cursor="hand2") + info_label.pack() info_label.bind("", lambda e: self.open_scorchsoft()) + + # If the banner should be hidden based on settings, hide it now + if self.banner_var.get(): + self.toggle_banner() def open_scorchsoft(self, event=None): webbrowser.open('https://www.scorchsoft.com') @@ -1023,6 +1053,7 @@ Please also make sure you read the Terms of use and licence statement before usi "prompt": "", "auto_apply_ai_to_recording": False, "current_tone": "None", + "hide_banner": False, "hotkeys": { "record_start_stop": ["ctrl", "shift", "0"], "stop_recording": ["ctrl", "shift", "9"], @@ -1084,4 +1115,92 @@ Please also make sure you read the Terms of use and licence statement before usi """Save tone presets using the TonePresetsManager.""" return TonePresetsManager.save_tone_presets(self, tone_presets) + # Add a new method to toggle banner visibility + def toggle_banner(self): + """Toggle the visibility of the banner image.""" + settings = self.load_settings() + hide_banner = self.banner_var.get() + + # Get current presets state + presets_visible = hasattr(self, 'presets_manager') and not self.presets_manager.presets_collapsed + + # Calculate width that preserves current width if manually resized + current_width = self.winfo_width() + width_to_use = max(current_width, self.BASE_WIDTH) + + if hide_banner: + # Hide the banner + self.banner_frame.grid_remove() + + # Set window geometry based on presets state + if presets_visible: + # Presets visible, banner hidden + self.geometry(f"{width_to_use}x{self.BASE_HEIGHT_NO_BANNER}") + else: + # Presets collapsed, banner hidden + self.geometry(f"{width_to_use}x{self.COLLAPSED_HEIGHT_NO_BANNER}") + else: + # Show the banner + self.banner_frame.grid() + + # Set window geometry based on presets state + if presets_visible: + # Presets visible, banner visible + self.geometry(f"{width_to_use}x{self.BASE_HEIGHT_WITH_BANNER}") + else: + # Presets collapsed, banner visible + self.geometry(f"{width_to_use}x{self.COLLAPSED_HEIGHT_WITH_BANNER}") + + # Update the settings + settings["hide_banner"] = hide_banner + self.save_settings_to_JSON(settings) + + # Make sure presets are laid out correctly if visible + if presets_visible and hasattr(self, 'presets_manager'): + self.presets_manager.refresh_presets_display() + + # Ensure the presets button is correctly positioned using grid + if hasattr(self, 'presets_manager') and hasattr(self.presets_manager, 'presets_button'): + if self.presets_manager.presets_button.winfo_exists(): + # Use grid (not pack) to ensure proper positioning + self.presets_manager.presets_button.grid_configure(column=0, row=0, sticky=tk.W, padx=0, pady=2) + + def toggle_presets(self): + """Toggle the visibility of the presets panel.""" + if hasattr(self, 'presets_manager'): + # Toggle presets via presets manager + self.presets_manager.toggle_presets() + + # Update our local tracking of presets state + self.presets_collapsed = self.presets_manager.presets_collapsed + + # Get banner visibility state + banner_hidden = self.banner_var.get() + + # Calculate a width that preserves the current width if it's larger than default + current_width = self.winfo_width() + width_to_use = max(current_width, self.BASE_WIDTH) + + # Set window geometry based on both states + if self.presets_collapsed: + # Presets collapsed - ensure minimum height with current width + if banner_hidden: + # Banner hidden, presets collapsed + self.geometry(f"{width_to_use}x{self.COLLAPSED_HEIGHT_NO_BANNER}") + else: + # Banner visible, presets collapsed + self.geometry(f"{width_to_use}x{self.COLLAPSED_HEIGHT_WITH_BANNER}") + else: + # Presets expanded - use full height with current width + if banner_hidden: + # Banner hidden, presets expanded + self.geometry(f"{width_to_use}x{self.BASE_HEIGHT_NO_BANNER}") + else: + # Banner visible, presets expanded + self.geometry(f"{width_to_use}x{self.BASE_HEIGHT_WITH_BANNER}") + + # Refresh presets display if they're visible + if not self.presets_collapsed: + self.presets_manager.refresh_presets_display() +