4141from .launch_page import LaunchPage
4242from .settings_page import SettingsPage
4343from .background_widget import BackgroundWidget
44+ from .console_window import ConsoleWindow
45+ from .servers_page import ServersPage
46+ from .skin_manager import SkinManagerPage
4447
4548
4649class MainWindow (QMainWindow ):
@@ -61,6 +64,9 @@ def __init__(self):
6164
6265 self .image_files = []
6366 self .current_image_index = 0
67+
68+ # New console window
69+ self .console_window = ConsoleWindow ()
6470
6571 self .setWindowTitle (APP_NAME )
6672 self .setMinimumSize (900 , 500 )
@@ -121,9 +127,20 @@ def init_ui(self):
121127 main_layout .setContentsMargins (20 , 20 , 20 , 20 )
122128 main_layout .setSpacing (20 )
123129
124- # Left navigation
130+ # Left navigation Scroll Area
131+ left_scroll = QScrollArea ()
132+ left_scroll .setWidgetResizable (True )
133+ left_scroll .setHorizontalScrollBarPolicy (Qt .ScrollBarPolicy .ScrollBarAlwaysOff )
134+ left_scroll .setVerticalScrollBarPolicy (Qt .ScrollBarPolicy .ScrollBarAlwaysOff )
135+ left_scroll .setFrameShape (QFrame .Shape .NoFrame )
136+ left_scroll .setStyleSheet ("background: transparent;" ) # Transparent background
137+
138+ # Left navigation container
125139 left_widget = QWidget ()
126140 left_widget .setObjectName ("left_title_container" )
141+ # Ensure the widget itself has transparent bg if styled otherwise in stylesheet
142+ left_widget .setAttribute (Qt .WidgetAttribute .WA_TranslucentBackground )
143+
127144 left_layout = QVBoxLayout (left_widget )
128145 left_layout .setSpacing (5 )
129146 left_layout .setContentsMargins (10 , 10 , 10 , 10 )
@@ -150,6 +167,16 @@ def init_ui(self):
150167 self .nav_launch_button .setCursor (Qt .CursorShape .PointingHandCursor )
151168 left_layout .addWidget (self .nav_launch_button )
152169
170+ self .nav_servers_button = QPushButton ("Servers" )
171+ self .nav_servers_button .setObjectName ("nav_button" )
172+ self .nav_servers_button .setCursor (Qt .CursorShape .PointingHandCursor )
173+ left_layout .addWidget (self .nav_servers_button )
174+
175+ self .nav_skins_button = QPushButton ("Skins" )
176+ self .nav_skins_button .setObjectName ("nav_button" )
177+ self .nav_skins_button .setCursor (Qt .CursorShape .PointingHandCursor )
178+ left_layout .addWidget (self .nav_skins_button )
179+
153180 self .nav_mods_button = QPushButton ("Mods" )
154181 self .nav_mods_button .setObjectName ("nav_button" )
155182 self .nav_mods_button .setCursor (Qt .CursorShape .PointingHandCursor )
@@ -165,8 +192,16 @@ def init_ui(self):
165192 self .nav_settings_button .setCursor (Qt .CursorShape .PointingHandCursor )
166193 left_layout .addWidget (self .nav_settings_button )
167194
195+ self .nav_console_button = QPushButton ("Console" )
196+ self .nav_console_button .setObjectName ("nav_button" )
197+ self .nav_console_button .setCursor (Qt .CursorShape .PointingHandCursor )
198+ self .nav_console_button .clicked .connect (self .show_console )
199+ left_layout .addWidget (self .nav_console_button )
200+
168201 left_layout .addStretch (1 )
169- main_layout .addWidget (left_widget , 2 )
202+
203+ left_scroll .setWidget (left_widget )
204+ main_layout .addWidget (left_scroll , 2 )
170205
171206 # Right content
172207 content_frame = QFrame ()
@@ -184,16 +219,22 @@ def init_ui(self):
184219 self .settings_page .settings_saved .connect (self .reload_background_settings )
185220 self .mods_page = ModsPage ()
186221 self .mod_browser_page = ModBrowserPage ()
222+ self .servers_page = ServersPage ()
223+ self .skin_manager_page = SkinManagerPage ()
187224
188- self .stacked_widget .addWidget (self .launch_page )
189- self .stacked_widget .addWidget (self .mods_page )
190- self .stacked_widget .addWidget (self .mod_browser_page )
191- self .stacked_widget .addWidget (self .settings_page )
225+ self .stacked_widget .addWidget (self .launch_page ) # Index 0
226+ self .stacked_widget .addWidget (self .servers_page ) # Index 1
227+ self .stacked_widget .addWidget (self .skin_manager_page ) # Index 2
228+ self .stacked_widget .addWidget (self .mods_page ) # Index 3
229+ self .stacked_widget .addWidget (self .mod_browser_page ) # Index 4
230+ self .stacked_widget .addWidget (self .settings_page ) # Index 5
192231
193232 self .nav_launch_button .clicked .connect (lambda : self .switch_page (0 , self .nav_launch_button ))
194- self .nav_mods_button .clicked .connect (lambda : self .switch_page (1 , self .nav_mods_button ))
195- self .nav_browse_mods_button .clicked .connect (lambda : self .switch_page (2 , self .nav_browse_mods_button ))
196- self .nav_settings_button .clicked .connect (lambda : self .switch_page (3 , self .nav_settings_button ))
233+ self .nav_servers_button .clicked .connect (lambda : self .switch_page (1 , self .nav_servers_button ))
234+ self .nav_skins_button .clicked .connect (lambda : self .switch_page (2 , self .nav_skins_button ))
235+ self .nav_mods_button .clicked .connect (lambda : self .switch_page (3 , self .nav_mods_button ))
236+ self .nav_browse_mods_button .clicked .connect (lambda : self .switch_page (4 , self .nav_browse_mods_button ))
237+ self .nav_settings_button .clicked .connect (lambda : self .switch_page (5 , self .nav_settings_button ))
197238
198239 # Connect signals from launch page to main window slots
199240 self .launch_page .username_input .textChanged .connect (self .save_settings )
@@ -240,7 +281,7 @@ def switch_page(self, index, button):
240281 self .mod_browser_page .set_launch_filters (version , loader_param )
241282
242283 # Update nav button styles
243- for btn in [self .nav_launch_button , self .nav_mods_button , self .nav_browse_mods_button , self .nav_settings_button ]:
284+ for btn in [self .nav_launch_button , self .nav_mods_button , self .nav_browse_mods_button , self .nav_settings_button , self . nav_servers_button , self . nav_skins_button ]:
244285 btn .setObjectName ("nav_button" )
245286 button .setObjectName ("nav_button_active" )
246287 self .apply_styles ()
@@ -301,6 +342,7 @@ def on_login_success(self, info: MicrosoftInfo):
301342 self .minecraft_info = info
302343 self .update_status (f"Logged in as { info ['username' ]} " )
303344 self .launch_page .microsoft_login_button .setText (f"Logged in as { info ['username' ]} " )
345+ self .skin_manager_page .set_microsoft_info (info )
304346
305347 def load_microsoft_info (self ):
306348 info = self .microsoft_auth .load_microsoft_info ()
@@ -314,6 +356,7 @@ def load_microsoft_info(self):
314356 self .update_status (f"Logged in as { info ['username' ]} " )
315357 self .launch_page .microsoft_login_button .setText (f"Logged in as { info ['username' ]} " )
316358 self .launch_page .auth_method_combo .setCurrentText ("Microsoft" )
359+ self .skin_manager_page .set_microsoft_info (info )
317360 else :
318361 self .update_status ("Failed to refresh token. Please login again." )
319362
@@ -517,6 +560,12 @@ def save_settings(self):
517560 self .config_manager .set ("last_version" , self .launch_page .version_combo .currentText ())
518561 self .config_manager .save ()
519562
563+ @pyqtSlot ()
564+ def show_console (self ):
565+ self .console_window .show ()
566+ self .console_window .raise_ ()
567+ self .console_window .activateWindow ()
568+
520569 @pyqtSlot ()
521570 def start_launch (self ):
522571 modifiers = QApplication .keyboardModifiers ()
@@ -569,6 +618,10 @@ def start_launch(self):
569618 self .launch_page .status_label .setText ("Starting worker thread..." )
570619 self .launch_page .progress_bar .setRange (0 , 100 )
571620 self .launch_page .progress_bar .setValue (0 )
621+
622+ # Clear console and show it
623+ self .console_window .clear_logs ()
624+ self .console_window .show ()
572625
573626 self .worker_thread = QThread ()
574627 self .worker = Worker (version , options , mod_loader_type )
@@ -578,6 +631,7 @@ def start_launch(self):
578631
579632 self .worker .progress .connect (self .update_progress )
580633 self .worker .status .connect (self .update_status )
634+ self .worker .log_output .connect (self .console_window .append_log ) # Connect logs
581635 self .worker .finished .connect (self .on_launch_finished )
582636
583637 self .worker .finished .connect (self .worker_thread .quit )
0 commit comments