1+ """
2+ GUI components for macOS_application_speedtest_for_python.
3+ """
4+ import tkinter as tk
5+ from tkinter import ttk , messagebox , Menu
6+ import logging
7+
8+ logger = logging .getLogger ("SpeedTest" )
9+
10+
11+ class ResultsFrame (tk .Frame ):
12+ """Frame for displaying speed test results."""
13+
14+ def __init__ (self , master , ** kwargs ):
15+ super ().__init__ (master , ** kwargs )
16+
17+ # Create labels for results
18+ self .result_title = tk .Label (self , text = "Test Results" , font = ("Helvetica" , 14 , "bold" ))
19+ self .result_title .pack (pady = (10 , 5 ))
20+
21+ # Download speed result
22+ self .download_frame = tk .Frame (self )
23+ self .download_frame .pack (fill = "x" , pady = 2 )
24+
25+ self .download_label = tk .Label (self .download_frame , text = "Download Speed:" , width = 15 ,
26+ anchor = "w" )
27+ self .download_label .pack (side = "left" , padx = 5 )
28+
29+ self .download_value = tk .Label (self .download_frame , text = "-- Mbps" , width = 15 , anchor = "e" )
30+ self .download_value .pack (side = "left" , padx = 5 )
31+
32+ # Upload speed result
33+ self .upload_frame = tk .Frame (self )
34+ self .upload_frame .pack (fill = "x" , pady = 2 )
35+
36+ self .upload_label = tk .Label (self .upload_frame , text = "Upload Speed:" , width = 15 , anchor = "w" )
37+ self .upload_label .pack (side = "left" , padx = 5 )
38+
39+ self .upload_value = tk .Label (self .upload_frame , text = "-- Mbps" , width = 15 , anchor = "e" )
40+ self .upload_value .pack (side = "left" , padx = 5 )
41+
42+ # Ping result
43+ self .ping_frame = tk .Frame (self )
44+ self .ping_frame .pack (fill = "x" , pady = 2 )
45+
46+ self .ping_label = tk .Label (self .ping_frame , text = "Ping:" , width = 15 , anchor = "w" )
47+ self .ping_label .pack (side = "left" , padx = 5 )
48+
49+ self .ping_value = tk .Label (self .ping_frame , text = "-- ms" , width = 15 , anchor = "e" )
50+ self .ping_value .pack (side = "left" , padx = 5 )
51+
52+ # Timestamp
53+ self .timestamp_frame = tk .Frame (self )
54+ self .timestamp_frame .pack (fill = "x" , pady = 2 )
55+
56+ self .timestamp_label = tk .Label (self .timestamp_frame , text = "Test Time:" , width = 15 ,
57+ anchor = "w" )
58+ self .timestamp_label .pack (side = "left" , padx = 5 )
59+
60+ self .timestamp_value = tk .Label (self .timestamp_frame , text = "--" , width = 25 , anchor = "e" )
61+ self .timestamp_value .pack (side = "left" , padx = 5 )
62+
63+ # Initially hide
64+ self .pack_forget ()
65+
66+ def update_results (self , download , upload , ping , timestamp ):
67+ """Updates the result values."""
68+ self .download_value .config (text = f"{ download } Mbps" )
69+ self .upload_value .config (text = f"{ upload } Mbps" )
70+ self .ping_value .config (text = f"{ ping } ms" )
71+ self .timestamp_value .config (text = timestamp )
72+ self .pack (fill = "both" , expand = True , pady = 10 )
73+
74+ def clear (self ):
75+ """Clears the result values."""
76+ self .download_value .config (text = "-- Mbps" )
77+ self .upload_value .config (text = "-- Mbps" )
78+ self .ping_value .config (text = "-- ms" )
79+ self .timestamp_value .config (text = "--" )
80+
81+
82+ class SettingsWindow :
83+ """Window for application settings."""
84+
85+ def __init__ (self , parent , settings , save_callback ):
86+ self .parent = parent
87+ self .settings = settings
88+ self .save_callback = save_callback
89+
90+ # Create a new window
91+ self .window = tk .Toplevel (parent )
92+ self .window .title ("Settings" )
93+ self .window .geometry ("400x300" )
94+ self .window .resizable (False , False )
95+ self .window .transient (parent )
96+ self .window .grab_set ()
97+
98+ # Center on parent
99+ x = parent .winfo_x () + (parent .winfo_width () // 2 ) - (400 // 2 )
100+ y = parent .winfo_y () + (parent .winfo_height () // 2 ) - (300 // 2 )
101+ self .window .geometry (f"+{ x } +{ y } " )
102+
103+ # Create a frame for settings
104+ self .frame = tk .Frame (self .window , padx = 20 , pady = 20 )
105+ self .frame .pack (fill = "both" , expand = True )
106+
107+ # Auto save results
108+ self .auto_save_var = tk .BooleanVar (value = settings .get ("auto_save_results" , True ))
109+ self .auto_save_check = ttk .Checkbutton (
110+ self .frame ,
111+ text = "Automatically save test results" ,
112+ variable = self .auto_save_var
113+ )
114+ self .auto_save_check .pack (anchor = "w" , pady = 5 )
115+
116+ # Show network info
117+ self .show_network_var = tk .BooleanVar (value = settings .get ("show_network_info" , True ))
118+ self .show_network_check = ttk .Checkbutton (
119+ self .frame ,
120+ text = "Show network adapter information" ,
121+ variable = self .show_network_var
122+ )
123+ self .show_network_check .pack (anchor = "w" , pady = 5 )
124+
125+ # Dark mode option
126+ self .dark_mode_var = tk .BooleanVar (value = settings .get ("dark_mode" , False ))
127+ self .dark_mode_check = ttk .Checkbutton (
128+ self .frame ,
129+ text = "Dark mode (requires restart)" ,
130+ variable = self .dark_mode_var
131+ )
132+ self .dark_mode_check .pack (anchor = "w" , pady = 5 )
133+
134+ # Create buttons
135+ self .button_frame = tk .Frame (self .window )
136+ self .button_frame .pack (fill = "x" , padx = 20 , pady = 20 )
137+
138+ self .save_button = ttk .Button (
139+ self .button_frame ,
140+ text = "Save" ,
141+ command = self .save_settings
142+ )
143+ self .save_button .pack (side = "right" , padx = 5 )
144+
145+ self .cancel_button = ttk .Button (
146+ self .button_frame ,
147+ text = "Cancel" ,
148+ command = self .window .destroy
149+ )
150+ self .cancel_button .pack (side = "right" , padx = 5 )
151+
152+ def save_settings (self ):
153+ """Saves the settings and closes the window."""
154+ self .settings ["auto_save_results" ] = self .auto_save_var .get ()
155+ self .settings ["show_network_info" ] = self .show_network_var .get ()
156+ self .settings ["dark_mode" ] = self .dark_mode_var .get ()
157+
158+ if self .save_callback :
159+ self .save_callback (self .settings )
160+
161+ self .window .destroy ()
162+
163+
164+ def create_menu (root , settings_callback , about_callback ):
165+ """Creates the application menu bar."""
166+ menubar = Menu (root )
167+
168+ # File menu
169+ file_menu = Menu (menubar , tearoff = 0 )
170+ file_menu .add_command (label = "Settings" , command = settings_callback )
171+ file_menu .add_separator ()
172+ file_menu .add_command (label = "Exit" , command = root .quit )
173+ menubar .add_cascade (label = "File" , menu = file_menu )
174+
175+ # Tools menu
176+ tools_menu = Menu (menubar , tearoff = 0 )
177+ tools_menu .add_command (label = "Export All History" , command = lambda : messagebox .showinfo (
178+ "Feature Coming Soon" , "This feature will be available in the next update."
179+ ))
180+ tools_menu .add_command (label = "Clear History" , command = lambda : messagebox .showinfo (
181+ "Feature Coming Soon" , "This feature will be available in the next update."
182+ ))
183+ menubar .add_cascade (label = "Tools" , menu = tools_menu )
184+
185+ # Help menu
186+ help_menu = Menu (menubar , tearoff = 0 )
187+ help_menu .add_command (label = "View Help" , command = lambda : messagebox .showinfo (
188+ "Help" ,
189+ "For help and documentation, please visit: https://github.com/AlexTkDev/"
190+ "macOS_application_speedtest_for_python"
191+ ))
192+ help_menu .add_separator ()
193+ help_menu .add_command (label = "About" , command = about_callback )
194+ menubar .add_cascade (label = "Help" , menu = help_menu )
195+
196+ root .config (menu = menubar )
197+
198+ return menubar
199+
200+
201+ def show_about_dialog (parent ):
202+ """Shows the About dialog."""
203+ from speedtest_app import __version__
204+
205+ about_window = tk .Toplevel (parent )
206+ about_window .title ("About Internet Speed Test" )
207+ about_window .geometry ("300x200" )
208+ about_window .resizable (False , False )
209+ about_window .transient (parent )
210+ about_window .grab_set ()
211+
212+ # Center on parent
213+ x = parent .winfo_x () + (parent .winfo_width () // 2 ) - (300 // 2 )
214+ y = parent .winfo_y () + (parent .winfo_height () // 2 ) - (200 // 2 )
215+ about_window .geometry (f"+{ x } +{ y } " )
216+
217+ # App name and version
218+ app_name = tk .Label (about_window , text = "Internet Speed Test" , font = ("Helvetica" , 16 , "bold" ))
219+ app_name .pack (pady = (20 , 5 ))
220+
221+ version = tk .Label (about_window , text = f"Version { __version__ } " )
222+ version .pack ()
223+
224+ # Separator
225+ separator = ttk .Separator (about_window , orient = "horizontal" )
226+ separator .pack (fill = "x" , padx = 20 , pady = 10 )
227+
228+ # Developer info
229+ dev_info = tk .Label (about_window , text = "Developed by Aleksandr" )
230+ dev_info .pack ()
231+
232+ # Copyright info
233+ copyright_info = tk .Label (about_window , text = "© 2024 Aleksandr. MIT License" )
234+ copyright_info .pack ()
235+
236+ # Close button
237+ close_button = ttk .Button (about_window , text = "Close" , command = about_window .destroy )
238+ close_button .pack (pady = 20 )
0 commit comments