11"""
22Sandbox Dashboard - GUI for creating, managing, and monitoring sandboxes
3+ Enhanced with modern UI elements and better user experience
34"""
45
56import tkinter as tk
910
1011
1112class SandboxDashboard :
12- """Dashboard for managing sandboxes"""
13+ """Dashboard for managing sandboxes with modern UI """
1314
1415 def __init__ (self , root , os_instance ):
1516 self .root = root
1617 self .os = os_instance
1718 self .manager = SandboxManager ()
1819 self .refresh_interval = 2000 # ms
1920 self .auto_refresh = True
21+ self .first_time_user = len (self .manager .list_sandboxes ()) == 0
2022
2123 def show (self ):
2224 """Show sandbox dashboard"""
@@ -299,6 +301,10 @@ def open_terminal():
299301 # Initial load
300302 self .refresh_sandbox_list (sandbox_list )
301303
304+ # Show quick start guide for first-time users
305+ if self .first_time_user :
306+ self .show_quick_start_guide (dashboard )
307+
302308 # Auto-refresh
303309 def auto_refresh_loop ():
304310 if self .auto_refresh and dashboard .winfo_exists ():
@@ -320,24 +326,46 @@ def refresh_sandbox_list(self, treeview):
320326 for item in treeview .get_children ():
321327 treeview .delete (item )
322328
323- # Add sandboxes
324- for sb in self .manager .list_sandboxes ():
325- sb .update_stats ()
326-
327- status_icon = {
328- 'running' : '🟢' ,
329- 'paused' : '🟡' ,
330- 'stopped' : '🔴'
331- }.get (sb .status , '⚪' )
332-
329+ # Get all sandboxes
330+ sandboxes = self .manager .list_sandboxes ()
331+
332+ # If no sandboxes, show empty state message
333+ if not sandboxes :
334+ # Insert a placeholder item
333335 treeview .insert ('' , tk .END , values = (
334- sb .name ,
335- sb .type .title (),
336- f"{ status_icon } { sb .status .title ()} " ,
337- f"{ sb .stats ['cpu_usage' ]:.1f} " ,
338- f"{ sb .stats ['memory_usage' ]:.0f} MB" ,
339- f"{ sb .stats ['disk_usage' ]:.0f} MB"
340- ))
336+ "No virtual machines created yet" ,
337+ "—" ,
338+ "Click 'Create New Sandbox' to get started" ,
339+ "—" ,
340+ "—" ,
341+ "—"
342+ ), tags = ('empty' ,))
343+
344+ # Configure tag to center and style the empty state
345+ treeview .tag_configure ('empty' , foreground = '#888888' , font = ('Arial' , 10 , 'italic' ))
346+ return
347+
348+ # Add sandboxes
349+ for sb in sandboxes :
350+ try :
351+ sb .update_stats ()
352+
353+ status_icon = {
354+ 'running' : '🟢' ,
355+ 'paused' : '🟡' ,
356+ 'stopped' : '🔴'
357+ }.get (sb .status , '⚪' )
358+
359+ treeview .insert ('' , tk .END , values = (
360+ sb .name ,
361+ sb .type .title (),
362+ f"{ status_icon } { sb .status .title ()} " ,
363+ f"{ sb .stats ['cpu_usage' ]:.1f} " ,
364+ f"{ sb .stats ['memory_usage' ]:.0f} MB" ,
365+ f"{ sb .stats ['disk_usage' ]:.0f} MB"
366+ ))
367+ except Exception as e :
368+ print (f"Error adding sandbox { sb .name } to list: { e } " )
341369
342370 def create_sandbox_dialog (self , parent ):
343371 """Show dialog to create new sandbox"""
@@ -865,3 +893,93 @@ def execute_command(event=None):
865893 command_var .set ("" )
866894
867895 command_entry .bind ('<Return>' , execute_command )
896+
897+ def show_quick_start_guide (self , parent ):
898+ """Show quick start guide for first-time users"""
899+ guide = tk .Toplevel (parent )
900+ guide .title ("Welcome to Sandbox Manager" )
901+ guide .geometry ("600x500" )
902+ guide .configure (bg = '#1a1a1a' if self .os .theme_mode == 'dark' else '#f5f5f5' )
903+ guide .transient (parent )
904+
905+ # Header
906+ header = tk .Frame (guide , bg = '#2d2d30' if self .os .theme_mode == 'dark' else '#ffffff' , height = 80 )
907+ header .pack (fill = tk .X )
908+ header .pack_propagate (False )
909+
910+ tk .Label (header , text = "🚀 Welcome to Sandbox Manager!" ,
911+ bg = '#2d2d30' if self .os .theme_mode == 'dark' else '#ffffff' ,
912+ fg = '#ffffff' if self .os .theme_mode == 'dark' else '#1a1a1a' ,
913+ font = ('Arial' , 18 , 'bold' )).pack (pady = (20 , 5 ))
914+
915+ tk .Label (header , text = "Create isolated virtual environments for your applications" ,
916+ bg = '#2d2d30' if self .os .theme_mode == 'dark' else '#ffffff' ,
917+ fg = '#888888' ,
918+ font = ('Arial' , 10 )).pack ()
919+
920+ # Content
921+ content = tk .Frame (guide , bg = '#1a1a1a' if self .os .theme_mode == 'dark' else '#f5f5f5' )
922+ content .pack (fill = tk .BOTH , expand = True , padx = 30 , pady = 20 )
923+
924+ guide_text = """
925+ 🔒 What are Sandboxes?
926+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
927+ Sandboxes are isolated virtual machines that provide:
928+
929+ ✅ Security - Run untrusted applications safely
930+ ✅ Isolation - Each sandbox has its own file system
931+ ✅ Resource Control - Set CPU, memory, and disk limits
932+ ✅ Easy Management - Create, start, stop, and delete with ease
933+
934+
935+ 📋 Getting Started
936+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
937+ 1. Click "Create New Sandbox" button
938+ 2. Choose a name for your virtual machine
939+ 3. Select a template (or customize resources)
940+ 4. Click "Create Virtual Machine"
941+ 5. Use the control panel to manage your sandbox
942+
943+
944+ 🎯 Available Templates
945+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
946+ 🔧 General Purpose - For everyday tasks
947+ 💻 Development - Enhanced resources for coding
948+ 🧪 Testing - Isolated environment for safe testing
949+ ⚡ Lightweight - Minimal resources for simple tasks
950+ 🚀 Heavy Workload - Maximum resources for demanding apps
951+
952+
953+ 💡 Tips
954+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
955+ • Use the Terminal feature to execute commands in a sandbox
956+ • Monitor resource usage in real-time
957+ • Pause sandboxes when not in use to save resources
958+ • Delete sandboxes you no longer need to free up space
959+ """
960+
961+ text_widget = scrolledtext .ScrolledText (content ,
962+ bg = '#2d2d30' if self .os .theme_mode == 'dark' else '#ffffff' ,
963+ fg = '#ffffff' if self .os .theme_mode == 'dark' else '#1a1a1a' ,
964+ font = ('Arial' , 10 ), relief = tk .FLAT , wrap = tk .WORD )
965+ text_widget .pack (fill = tk .BOTH , expand = True )
966+ text_widget .insert ('1.0' , guide_text )
967+ text_widget .config (state = 'disabled' )
968+
969+ # Buttons
970+ btn_frame = tk .Frame (guide , bg = '#1a1a1a' if self .os .theme_mode == 'dark' else '#f5f5f5' )
971+ btn_frame .pack (pady = (0 , 20 ))
972+
973+ tk .Button (btn_frame , text = "Create My First Sandbox" ,
974+ command = lambda : (guide .destroy (), self .create_sandbox_dialog (parent )),
975+ bg = '#007acc' , fg = 'white' , relief = tk .FLAT ,
976+ font = ('Arial' , 11 , 'bold' ), padx = 25 , pady = 10 ,
977+ cursor = 'hand2' ).pack (side = tk .LEFT , padx = 5 )
978+
979+ tk .Button (btn_frame , text = "Close" ,
980+ command = guide .destroy ,
981+ bg = '#3c3c3c' if self .os .theme_mode == 'dark' else '#d0d0d0' ,
982+ fg = '#ffffff' if self .os .theme_mode == 'dark' else '#1a1a1a' ,
983+ relief = tk .FLAT ,
984+ font = ('Arial' , 11 ), padx = 25 , pady = 10 ,
985+ cursor = 'hand2' ).pack (side = tk .LEFT , padx = 5 )
0 commit comments