@@ -31,41 +31,25 @@ class AdvancedSettingsWindow(ttk.Toplevel):
3131 Self-contained settings sub-window for the UI
3232 """
3333
34- _instance = None
3534 def __init__ (self , parent ):
36- if UI .AdvancedSettingsWindow ._instance :
37- return
3835 super ().__init__ (parent )
39- UI .AdvancedSettingsWindow ._instance = self
4036 self .title ('Advanced Settings' )
4137 self .minsize (300 , 300 )
4238 self .settings = Settings ()
4339 self .create_widgets ()
44- self .protocol ("WM_DELETE_WINDOW" , self .on_close )
4540
4641 # Populate UI
4742 settings_dict = self .settings .get_dict ()
4843
4944 if 'base_url' in settings_dict :
5045 self .base_url_entry .insert (0 , settings_dict ['base_url' ])
51- if 'selected_model_radio' in settings_dict :
52- self .model_var .set (settings_dict ['selected_model_radio' ])
53- elif 'model' in settings_dict :
54- loaded_model = settings_dict ['model' ]
55- if loaded_model in self .gemini_models :
56- self .model_var .set ('gemini' )
57- else :
58- self .model_var .set ('custom' )
59- self .model_entry .insert (0 , loaded_model )
46+ if 'model' in settings_dict :
47+ self .model_entry .insert (0 , settings_dict ['model' ])
48+ self .model_var .set (settings_dict .get ('model' , 'custom' ))
6049 else :
50+ self .model_entry .insert (0 , DEFAULT_MODEL_NAME )
6151 self .model_var .set (DEFAULT_MODEL_NAME )
6252
63- self .update_ui_visibility ()
64-
65- def on_close (self ):
66- UI .AdvancedSettingsWindow ._instance = None
67- self .destroy ()
68-
6953 def create_widgets (self ) -> None :
7054 # Radio buttons for model selection
7155 ttk .Label (self , text = 'Select Model:' , bootstyle = "primary" ).pack (pady = 10 , padx = 10 )
@@ -80,111 +64,67 @@ def create_widgets(self) -> None:
8064 ('GPT-4o-mini (Cheapest, Fastest)' , 'gpt-4o-mini' ),
8165 ('GPT-4v (Deprecated. Most-Accurate, Slowest)' , 'gpt-4-vision-preview' ),
8266 ('GPT-4-Turbo (Least Accurate, Fast)' , 'gpt-4-turbo' ),
83- ('Gemini (Free, Fast)' , 'gemini' ),
67+ ('' , '' ),
68+ ('Gemini gemini-2.0-flash (Free, Fast)' , 'gemini-2.0-flash' ),
69+ ('Gemini gemini-2.0-flash-lite' , 'gemini-2.0-flash-lite' ),
70+ ('Gemini gemini-2.0-flash-thinking-exp' , 'gemini-2.0-flash-thinking-exp' ),
71+ ('Gemini gemini-2.0-pro-exp-02-05' , 'gemini-2.0-pro-exp-02-05' ),
72+ ('' , '' ),
8473 ('Custom (Specify Settings Below)' , 'custom' )
8574 ]
8675 for text , value in models :
87- radio_button = ttk .Radiobutton (radio_frame , text = text , value = value , variable = self .model_var , bootstyle = "info" )
88- radio_button .pack (anchor = ttk .W , pady = 5 )
89- radio_button .config (command = self .update_ui_visibility )
90-
91- # Gemini Model Selection
92- self .gemini_model_label = ttk .Label (self , text = 'Select or Type Gemini Model:' , bootstyle = "primary" )
93- self .gemini_model_var = ttk .StringVar (value = 'gemini-2.0-flash' )
94-
95- self .gemini_model_frame = ttk .Frame (self )
96-
97- self .gemini_models = [
98- 'gemini-2.0-flash' ,
99- 'gemini-2.0-flash-lite' ,
100- 'gemini-2.0-flash-thinking-exp' ,
101- 'gemini-2.0-pro-exp-02-05'
102- ]
103- self .gemini_model_combobox = ttk .Combobox (self .gemini_model_frame , textvariable = self .gemini_model_var , values = self .gemini_models , width = 30 )
104- self .gemini_model_combobox .pack (pady = 5 )
105- self .gemini_model_combobox .set ('gemini-2.0-flash' )
76+ if text == '' and value == '' :
77+ ttk .Separator (radio_frame , orient = 'horizontal' ).pack (fill = 'x' , pady = 10 )
78+ else :
79+ ttk .Radiobutton (radio_frame , text = text , value = value , variable = self .model_var , bootstyle = "info" ).pack (
80+ anchor = ttk .W , pady = 5 )
10681
107- # Custom Base URL
108- self .custom_frame = ttk .Frame (self )
109-
110- self .label_base_url = ttk .Label (self .custom_frame , text = 'Custom OpenAI-Like API Model Base URL' , bootstyle = "secondary" )
111- self .label_base_url .pack (pady = 10 )
82+ label_base_url = ttk .Label (self , text = 'Custom OpenAI-Like API Model Base URL' , bootstyle = "secondary" )
83+ label_base_url .pack (pady = 10 )
11284
11385 # Entry for Base URL
114- self .base_url_entry = ttk .Entry (self . custom_frame , width = 30 )
86+ self .base_url_entry = ttk .Entry (self , width = 30 )
11587 self .base_url_entry .pack ()
11688
11789 # Model Label
118- self . label_model = ttk .Label (self . custom_frame , text = 'Custom Model Name:' , bootstyle = "secondary" )
119- self . label_model .pack (pady = 10 )
90+ label_model = ttk .Label (self , text = 'Custom Model Name:' , bootstyle = "secondary" )
91+ label_model .pack (pady = 10 )
12092
12193 # Entry for Model
122- self .model_entry = ttk .Entry (self . custom_frame , width = 30 )
94+ self .model_entry = ttk .Entry (self , width = 30 )
12395 self .model_entry .pack ()
12496
12597 # Save Button
12698 save_button = ttk .Button (self , text = 'Save Settings' , bootstyle = "success" , command = self .save_button )
12799 save_button .pack (pady = 20 )
128100
129- def update_ui_visibility (self ):
130- """Update the visibility of UI elements based on model selection"""
131- model_choice = self .model_var .get ()
132-
133- # First hide all optional frames
134- self .gemini_model_label .pack_forget ()
135- self .gemini_model_frame .pack_forget ()
136- self .custom_frame .pack_forget ()
137-
138- # Then show only the relevant ones
139- if model_choice == 'gemini' :
140- self .gemini_model_label .pack (pady = 10 , padx = 10 )
141- self .gemini_model_frame .pack (padx = 20 , pady = 10 )
142- if 'gemini_model' in self .settings .get_dict ():
143- self .gemini_model_combobox .set (self .settings .get_dict ()['gemini_model' ])
144-
145- if model_choice == 'custom' :
146- self .custom_frame .pack (padx = 20 , pady = 10 )
147- previous_model = self .settings .get_dict ().get ('model' , DEFAULT_MODEL_NAME )
148- if previous_model not in self .gemini_models :
149- self .model_entry .delete (0 , ttk .END )
150- self .model_entry .insert (0 , previous_model )
101+ # Restart App Label
102+ restart_app_label = ttk .Label (self , text = 'Restart the app after any change in settings' ,
103+ font = ('Helvetica' , 10 ))
104+ restart_app_label .pack (pady = (0 , 20 ))
151105
152106 def save_button (self ) -> None :
153107 base_url = self .base_url_entry .get ().strip ()
154- model = self .model_var .get ()
155-
156- if model == 'custom' :
157- model = self .model_entry .get ().strip ()
158- elif model == 'gemini' :
159- model = self .gemini_model_var .get ().strip ()
160-
108+ model = self .model_var .get () if self .model_var .get () != 'custom' else self .model_entry .get ().strip ()
161109 settings_dict = {
162110 'base_url' : base_url ,
163111 'model' : model ,
164- 'gemini_model' : self .gemini_model_var .get ().strip (),
165- 'selected_model_radio' : self .model_var .get ()
166112 }
167113
168114 self .settings .save_settings_to_file (settings_dict )
169115 self .destroy ()
170- UI .AdvancedSettingsWindow ._instance = None
171116
172117 class SettingsWindow (ttk .Toplevel ):
173118 """
174119 Self-contained settings sub-window for the UI
175120 """
176121
177- _instance = None
178122 def __init__ (self , parent ):
179- if UI .SettingsWindow ._instance :
180- return
181123 super ().__init__ (parent )
182- UI .SettingsWindow ._instance = self
183124 self .title ('Settings' )
184125 self .minsize (300 , 450 )
185126 self .available_themes = ['darkly' , 'cyborg' , 'journal' , 'solar' , 'superhero' ]
186127 self .create_widgets ()
187- self .protocol ("WM_DELETE_WINDOW" , self .on_close )
188128
189129 self .settings = Settings ()
190130
@@ -193,31 +133,20 @@ def __init__(self, parent):
193133
194134 if 'api_key' in settings_dict :
195135 self .api_key_entry .insert (0 , settings_dict ['api_key' ])
196- if 'gemini_api_key' in settings_dict :
197- self .gemini_api_key_entry .insert (0 , settings_dict ['gemini_api_key' ])
198136 if 'default_browser' in settings_dict :
199137 self .browser_combobox .set (settings_dict ['default_browser' ])
200138 if 'play_ding_on_completion' in settings_dict :
201139 self .play_ding .set (1 if settings_dict ['play_ding_on_completion' ] else 0 )
202- if 'custom_llm_instructions' in settings_dict :
140+ if 'custom_llm_instructions' :
203141 self .llm_instructions_text .insert ('1.0' , settings_dict ['custom_llm_instructions' ])
204142 self .theme_combobox .set (settings_dict .get ('theme' , 'superhero' ))
205-
206- def on_close (self ):
207- UI .SettingsWindow ._instance = None
208- self .destroy ()
209-
210- def create_label_and_entry (self , parent , label_text ):
211- ttk .Label (parent , text = label_text , bootstyle = "info" ).pack (pady = 10 )
212- entry = ttk .Entry (parent , width = 30 )
213- entry .pack ()
214- return entry
215143
216144 def create_widgets (self ) -> None :
217145 # API Key Widgets
218- self .api_key_entry = self .create_label_and_entry (self , 'OpenAI API Key:' )
219-
220- self .gemini_api_key_entry = self .create_label_and_entry (self , 'Gemini API Key:' )
146+ label_api = ttk .Label (self , text = 'OpenAI/Gemini/LLM Model API Key:' , bootstyle = "info" )
147+ label_api .pack (pady = 10 )
148+ self .api_key_entry = ttk .Entry (self , width = 30 )
149+ self .api_key_entry .pack ()
221150
222151 # Label for Browser Choice
223152 label_browser = ttk .Label (self , text = 'Choose Default Browser:' , bootstyle = "info" )
@@ -255,50 +184,59 @@ def create_widgets(self) -> None:
255184 # Add binding for immediate theme change
256185 self .theme_combobox .bind ('<<ComboboxSelected>>' , self .on_theme_change )
257186
258- # Save Button
259- save_button = ttk .Button (self , text = 'Save Settings' , bootstyle = "success" , command = self .save_button )
260- save_button .pack (pady = (10 , 5 ))
261-
262187 # Button to open Advanced Settings
263188 advanced_settings_button = ttk .Button (self , text = 'Advanced Settings' , bootstyle = "info" ,
264189 command = self .open_advanced_settings )
265- advanced_settings_button .pack (pady = (0 , 10 ))
190+ advanced_settings_button .pack (pady = (10 , 0 ))
266191
267- # Create clickable labels
268- self .create_link_label ('Setup Instructions' ,
269- 'https://github.com/AmberSahdev/Open-Interface?tab=readme-ov-file#setup-%EF%B8%8F' )
270- self .create_link_label ('Check for Updates' ,
271- 'https://github.com/AmberSahdev/Open-Interface/releases/latest' )
192+ # Save Button
193+ save_button = ttk .Button (self , text = 'Save Settings' , bootstyle = "success" , command = self .save_button )
194+ save_button .pack (pady = 5 )
195+
196+ # Restart App Label
197+ restart_app_label = ttk .Label (self , text = 'Restart the app after any change in settings' ,
198+ font = ('Helvetica' , 10 ))
199+ restart_app_label .pack (pady = (0 , 10 ))
200+
201+ # Hyperlink Label
202+ link_label = ttk .Label (self , text = 'Setup Instructions' , bootstyle = "primary" )
203+ link_label .pack ()
204+ link_label .bind ('<Button-1>' , lambda e : open_link (
205+ 'https://github.com/AmberSahdev/Open-Interface?tab=readme-ov-file#setup-%EF%B8%8F' ))
206+
207+ # Check for updates Label
208+ update_label = ttk .Label (self , text = 'Check for Updates' , bootstyle = "primary" )
209+ update_label .pack ()
210+ update_label .bind ('<Button-1>' , lambda e : open_link (
211+ 'https://github.com/AmberSahdev/Open-Interface/releases/latest' ))
272212
273213 # Version Label
274214 version_label = ttk .Label (self , text = f'Version: { str (version )} ' , font = ('Helvetica' , 10 ))
275215 version_label .pack (side = "bottom" , pady = 10 )
276216
277- def create_link_label (self , text , url ):
278- link_label = ttk .Label (self , text = text , bootstyle = "primary" )
279- link_label .pack ()
280- link_label .bind ('<Button-1>' , lambda e : open_link (url ))
281-
282217 def on_theme_change (self , event = None ) -> None :
283218 # Apply theme immediately when selected
284219 theme = self .theme_var .get ()
285220 self .master .change_theme (theme )
286221
287222 def save_button (self ) -> None :
223+ theme = self .theme_var .get ()
224+ api_key = self .api_key_entry .get ().strip ()
225+ default_browser = self .browser_var .get ()
288226 settings_dict = {
289- 'api_key' : self .api_key_entry .get ().strip (),
290- 'gemini_api_key' : self .gemini_api_key_entry .get ().strip (),
291- 'default_browser' : self .browser_var .get (),
227+ 'api_key' : api_key ,
228+ 'default_browser' : default_browser ,
292229 'play_ding_on_completion' : bool (self .play_ding .get ()),
293230 'custom_llm_instructions' : self .llm_instructions_text .get ("1.0" , "end-1c" ).strip (),
294- 'theme' : self . theme_var . get ()
231+ 'theme' : theme
295232 }
296233
234+ # Remove redundant theme change since it's already applied
297235 self .settings .save_settings_to_file (settings_dict )
298236 self .destroy ()
299- UI .SettingsWindow ._instance = None
300237
301238 def open_advanced_settings (self ):
239+ # Open the advanced settings window
302240 UI .AdvancedSettingsWindow (self )
303241
304242 class MainWindow (ttk .Window ):
@@ -313,7 +251,7 @@ def __init__(self):
313251 try :
314252 super ().__init__ (themename = theme )
315253 except :
316- super ().__init__ () # https://github.com/AmberSahdev/Open-Interface/issues/35
254+ super ().__init__ () # https://github.com/AmberSahdev/Open-Interface/issues/35
317255
318256 self .title ('Open Interface' )
319257 window_width = 450
@@ -454,7 +392,18 @@ def voice_input(self) -> None:
454392 def update_message (self , message : str ) -> None :
455393 # Update the message display with the provided text.
456394 # Ensure thread safety when updating the Tkinter GUI.
457- if threading .current_thread () is threading .main_thread ():
458- self .message_display ['text' ] = message
459- else :
460- self .message_display .after (0 , lambda : self .message_display .config (text = message ))
395+ try :
396+ if threading .current_thread () is threading .main_thread ():
397+ self .message_display ['text' ] = message
398+ else :
399+ print ("calling lambda 1" )
400+ self .message_display .after (0 , lambda : self ._update_message_on_main_thread (message ))
401+ print ("calling lambda 2" )
402+ except Exception as e :
403+ print (f"Error updating message: { e } " )
404+
405+ def _update_message_on_main_thread (self , message : str ) -> None :
406+ # TODO: This lambda is not being executed, investigate
407+ print (f"inside lambda to update message 1 = message: { message } " )
408+ self .message_display .config (text = message )
409+ print ("inside lambda to update message 2" )
0 commit comments