@@ -86,107 +86,109 @@ void MainWindow::initUI() {
8686 QWidget* central = new QWidget (this );
8787 setCentralWidget (central);
8888
89- // Root Layout (Vertical )
90- QVBoxLayout * rootLayout = new QVBoxLayout (central);
89+ // Root Layout (Horizontal: Sidebar | Content )
90+ QHBoxLayout * rootLayout = new QHBoxLayout (central);
9191 rootLayout->setContentsMargins (0 , 0 , 0 , 0 );
9292 rootLayout->setSpacing (0 );
9393
9494 // ---------------------------------------------------------
95- // 1. Global Header
95+ // 1. Sidebar (Left)
9696 // ---------------------------------------------------------
97- QWidget* headerWidget = new QWidget ();
98- headerWidget->setStyleSheet (" background-color: rgba(20, 20, 30, 0.95); border-bottom: 1px solid rgba(255, 255, 255, 0.1);" );
99- QHBoxLayout* headerLayout = new QHBoxLayout (headerWidget);
100- headerLayout->setContentsMargins (20 , 15 , 20 , 15 );
101- headerLayout->setSpacing (20 );
97+ QWidget* sidebarWidget = new QWidget ();
98+ sidebarWidget->setFixedWidth (200 );
99+ sidebarWidget->setStyleSheet (" background-color: rgba(20, 20, 30, 0.95); border-right: 1px solid rgba(255, 255, 255, 0.1);" );
102100
103- // Icon & Title
101+ QVBoxLayout* sidebarLayout = new QVBoxLayout (sidebarWidget);
102+ sidebarLayout->setContentsMargins (15 , 25 , 15 , 25 );
103+ sidebarLayout->setSpacing (15 );
104+
105+ // Header
106+ QHBoxLayout* headerLayout = new QHBoxLayout ();
104107 QLabel* icon = new QLabel (" ⚡" );
105- icon->setStyleSheet (QString (" font-size: 28px ; color: %1; font-weight: bold; background: transparent; border: none;" ).arg (Colors::ACCENT_BLUE));
108+ icon->setStyleSheet (QString (" font-size: 20px ; color: %1; font-weight: bold; background: transparent; border: none;" ).arg (Colors::ACCENT_BLUE));
106109
107110 QLabel* title = new QLabel (" Lua Patcher" );
108- title->setStyleSheet (" font-size: 20px ; font-weight: 800 ; color: #E2E8F0; background: transparent; border: none;" );
111+ title->setStyleSheet (" font-size: 16px ; font-weight: 700 ; color: #E2E8F0; background: transparent; border: none;" );
109112
110113 headerLayout->addWidget (icon);
111114 headerLayout->addWidget (title);
112- headerLayout->addSpacing (40 );
115+ headerLayout->addStretch ();
116+ sidebarLayout->addLayout (headerLayout);
117+
118+ sidebarLayout->addSpacing (20 );
113119
114- // Tabs (Navigation)
115- m_tabLua = new GlassButton (" ⬇" , " Lua Patcher" , " " , Colors::ACCENT_BLUE);
116- m_tabLua->setFixedSize (160 , 45 );
120+ // Nav Buttons
121+ m_tabLua = new GlassButton (" ⬇" , " Lua Patcher" , " " , Colors::ACCENT_BLUE);
122+ m_tabLua->setFixedHeight (40 );
123+ m_tabLua->setStyleSheet (" text-align: left; padding-left: 10px;" );
117124 connect (m_tabLua, &QPushButton::clicked, this , [this ](){ switchMode (AppMode::LuaPatcher); });
125+ sidebarLayout->addWidget (m_tabLua);
118126
119- m_tabFix = new GlassButton (" 🔧" , " Fix Manager" , " " , Colors::ACCENT_PURPLE);
120- m_tabFix->setFixedSize (160 , 45 );
127+ m_tabFix = new GlassButton (" 🔧" , " Fix Manager" , " " , Colors::ACCENT_PURPLE);
128+ m_tabFix->setFixedHeight (40 );
129+ m_tabFix->setStyleSheet (" text-align: left; padding-left: 10px;" );
121130 connect (m_tabFix, &QPushButton::clicked, this , [this ](){ switchMode (AppMode::FixManager); });
131+ sidebarLayout->addWidget (m_tabFix);
122132
123- headerLayout->addWidget (m_tabLua);
124- headerLayout->addWidget (m_tabFix);
125- headerLayout->addStretch ();
133+ sidebarLayout->addSpacing (10 );
126134
127- rootLayout->addWidget (headerWidget);
128-
129- // ---------------------------------------------------------
130- // 2. Content Area
131- // ---------------------------------------------------------
132- QWidget* contentWidget = new QWidget ();
133- QHBoxLayout* mainLayout = new QHBoxLayout (contentWidget);
134- mainLayout->setContentsMargins (40 , 30 , 40 , 30 );
135- mainLayout->setSpacing (40 );
135+ // Separator
136+ QFrame* line = new QFrame ();
137+ line->setFrameShape (QFrame::HLine);
138+ line->setStyleSheet (" background: rgba(255, 255, 255, 0.1);" );
139+ sidebarLayout->addWidget (line);
136140
137- // ─── LEFT COLUMN: ACTIONS ───
138- QVBoxLayout* leftCol = new QVBoxLayout ();
139- leftCol->setSpacing (16 );
141+ sidebarLayout->addSpacing (10 );
140142
141- // Status
143+ // Status (Moved to sidebar)
142144 m_statusLabel = new QLabel (" Initializing..." );
143- m_statusLabel->setStyleSheet (QString (" color: %1; font-size: 13px ;" ).arg (Colors::TEXT_SECONDARY));
145+ m_statusLabel->setStyleSheet (QString (" color: %1; font-size: 11px ;" ).arg (Colors::TEXT_SECONDARY));
144146 m_statusLabel->setWordWrap (true );
145- leftCol ->addWidget (m_statusLabel);
147+ sidebarLayout ->addWidget (m_statusLabel);
146148
147- leftCol ->addStretch ();
149+ sidebarLayout ->addStretch ();
148150
149- // Buttons
150- m_btnPatch = new GlassButton (" ⬇" , " Patch Game " , " Install Lua patch for selected game " , Colors::ACCENT_GREEN);
151+ // Actions (Contextual Buttons in Sidebar)
152+ m_btnPatch = new GlassButton (" ⬇" , " Patch" , " Install Patch " , Colors::ACCENT_GREEN);
151153 m_btnPatch->setEnabled (false );
152154 connect (m_btnPatch, &QPushButton::clicked, this , &MainWindow::doPatch);
153- leftCol ->addWidget (m_btnPatch);
155+ sidebarLayout ->addWidget (m_btnPatch);
154156
155- m_btnGenerate = new GlassButton (" ⚙" , " Generate Patch " , " Fetch data for unknown game " , Colors::ACCENT_BLUE);
157+ m_btnGenerate = new GlassButton (" ⚙" , " Generate" , " Fetch Data " , Colors::ACCENT_BLUE);
156158 m_btnGenerate->setEnabled (false );
157159 m_btnGenerate->hide ();
158160 connect (m_btnGenerate, &QPushButton::clicked, this , &MainWindow::doGenerate);
159- leftCol ->addWidget (m_btnGenerate);
161+ sidebarLayout ->addWidget (m_btnGenerate);
160162
161- m_btnApplyFix = new GlassButton (" 🔧" , " Apply Fix" , " Download and apply game fix files " , Colors::ACCENT_PURPLE);
163+ m_btnApplyFix = new GlassButton (" 🔧" , " Apply Fix" , " Apply Fix Files " , Colors::ACCENT_PURPLE);
162164 m_btnApplyFix->setEnabled (false );
163165 m_btnApplyFix->hide ();
164166 connect (m_btnApplyFix, &QPushButton::clicked, this , &MainWindow::doApplyFix);
165- leftCol ->addWidget (m_btnApplyFix);
167+ sidebarLayout ->addWidget (m_btnApplyFix);
166168
167- m_btnRestart = new GlassButton (" ↻" , " Restart Steam" , " Apply changes by restarting Steam" , Colors::ACCENT_PURPLE);
168- connect (m_btnRestart, &QPushButton::clicked, this , &MainWindow::doRestart);
169- leftCol->addWidget (m_btnRestart);
169+ sidebarLayout->addSpacing (10 );
170170
171- leftCol->addStretch ();
171+ m_btnRestart = new GlassButton (" ↻" , " Restart Steam" , " Apply Changes" , Colors::ACCENT_PURPLE);
172+ connect (m_btnRestart, &QPushButton::clicked, this , &MainWindow::doRestart);
173+ sidebarLayout->addWidget (m_btnRestart);
172174
175+ sidebarLayout->addSpacing (20 );
176+
173177 // Version & Creator
174- QLabel* versionLabel = new QLabel (QString (" v%1" ).arg (Config::APP_VERSION));
175- versionLabel ->setStyleSheet (QString (" color: %1; font-size: 12px ; font-weight: bold;" ).arg (Colors::TEXT_SECONDARY));
176- versionLabel ->setAlignment (Qt::AlignCenter);
177- leftCol ->addWidget (versionLabel );
178+ QLabel* infoLabel = new QLabel (QString (" v%1\n by leVI & raxnmint " ).arg (Config::APP_VERSION));
179+ infoLabel ->setStyleSheet (QString (" color: %1; font-size: 10px ; font-weight: bold;" ).arg (Colors::TEXT_SECONDARY));
180+ infoLabel ->setAlignment (Qt::AlignCenter);
181+ sidebarLayout ->addWidget (infoLabel );
178182
179- QLabel* creatorLabel = new QLabel (" created by <a href=\" https://github.com/sayedalimollah2602-prog\" style=\" color: #94A3B8; text-decoration: none;\" >leVI</a> & <a href=\" https://github.com/raxnmint\" style=\" color: #94A3B8; text-decoration: none;\" >raxnmint</a>" );
180- creatorLabel->setStyleSheet (" font-size: 11px;" );
181- creatorLabel->setAlignment (Qt::AlignCenter);
182- creatorLabel->setOpenExternalLinks (true );
183- leftCol->addWidget (creatorLabel);
184-
185- mainLayout->addLayout (leftCol, 35 );
186-
187- // ─── RIGHT COLUMN: SEARCH & LIST ───
188- QVBoxLayout* rightCol = new QVBoxLayout ();
189- rightCol->setSpacing (16 );
183+ rootLayout->addWidget (sidebarWidget);
184+
185+ // ---------------------------------------------------------
186+ // 2. Content Area (Right)
187+ // ---------------------------------------------------------
188+ QWidget* contentWidget = new QWidget ();
189+ QVBoxLayout* mainLayout = new QVBoxLayout (contentWidget);
190+ mainLayout->setContentsMargins (30 , 30 , 30 , 30 );
191+ mainLayout->setSpacing (20 );
190192
191193 // Search Bar
192194 QHBoxLayout* searchLayout = new QHBoxLayout ();
@@ -208,7 +210,7 @@ void MainWindow::initUI() {
208210 if (m_searchInput->text ().trimmed ().isEmpty ()) startSync (); else doSearch ();
209211 });
210212 searchLayout->addWidget (refreshBtn);
211- rightCol ->addLayout (searchLayout);
213+ mainLayout ->addLayout (searchLayout);
212214
213215 // Stack for Loading / List
214216 m_stack = new QStackedWidget ();
@@ -221,22 +223,21 @@ void MainWindow::initUI() {
221223 m_stack->addWidget (pageLoading);
222224
223225 m_resultsList = new QListWidget ();
224- m_resultsList->setIconSize (QSize (40 , 40 ));
226+ m_resultsList->setIconSize (QSize (36 , 36 ));
225227 m_resultsList->setWordWrap (true );
226228 m_resultsList->setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
227229 m_resultsList->setTextElideMode (Qt::ElideNone);
228230 connect (m_resultsList, &QListWidget::itemPressed, this , &MainWindow::onGameSelected);
229231 m_stack->addWidget (m_resultsList);
230- rightCol ->addWidget (m_stack);
232+ mainLayout ->addWidget (m_stack);
231233
232234 m_progress = new QProgressBar ();
233235 m_progress->setFixedHeight (4 );
234236 m_progress->setTextVisible (false );
235237 m_progress->setStyleSheet (QString (" QProgressBar { background: %1; border-radius: 2px; } QProgressBar::chunk { background: %2; border-radius: 2px; }" ).arg (Colors::GLASS_BG).arg (Colors::ACCENT_GREEN));
236238 m_progress->hide ();
237- rightCol ->addWidget (m_progress);
239+ mainLayout ->addWidget (m_progress);
238240
239- mainLayout->addLayout (rightCol, 65 );
240241 rootLayout->addWidget (contentWidget);
241242
242243 m_terminalDialog = new TerminalDialog (this );
@@ -979,27 +980,90 @@ void MainWindow::switchMode(AppMode mode) {
979980 // Clear selection and re-run search/filter
980981 m_resultsList->clearSelection ();
981982 onGameSelected (nullptr );
982- doSearch ();
983+
984+ if (m_currentMode == AppMode::FixManager) {
985+ populateFixList ();
986+ } else {
987+ doSearch ();
988+ }
989+ }
990+
991+ void MainWindow::populateFixList () {
992+ m_statusLabel->setText (" Listing available fixes..." );
993+ cancelNameFetches ();
994+
995+ QJsonArray fixGames;
996+ for (const auto & game : m_supportedGames) {
997+ if (game.hasFix ) {
998+ QJsonObject item;
999+ item[" id" ] = game.id ;
1000+ item[" name" ] = game.name ;
1001+ item[" supported_local" ] = true ;
1002+ fixGames.append (item);
1003+ }
1004+ }
1005+
1006+ displayResults (fixGames);
1007+
1008+ if (m_resultsList->count () > 0 ) {
1009+ m_statusLabel->setText (QString (" Found %1 available fixes" ).arg (m_resultsList->count ()));
1010+ } else {
1011+ m_statusLabel->setText (" No fixes available in current index." );
1012+ }
1013+
1014+ m_stack->setCurrentIndex (1 );
1015+ m_spinner->stop ();
9831016}
9841017
9851018void MainWindow::updateModeUI () {
986- // Update Tab Styles
987- QString activeStyle = QString (" background: %1; border: 1px solid %2; color: %3; border-radius: 6px; font-weight: bold;" )
988- .arg (Colors::GLASS_HOVER)
989- .arg (Colors::ACCENT_BLUE)
990- .arg (Colors::TEXT_PRIMARY);
991-
992- QString inactiveStyle = QString (" background: transparent; border: 1px solid transparent; color: %1; border-radius: 6px;" )
993- .arg (Colors::TEXT_SECONDARY);
1019+ // Update Tab Styles with Left Border Indicator
1020+
1021+ // Active: Semi-transparent background + Accent Color Text + Left Border
1022+ QString activeStyle = QString (
1023+ " background: rgba(59, 130, 246, 0.15);" // Slight blue tint
1024+ " border: none;"
1025+ " border-left: 3px solid %1;" // Accent color border
1026+ " color: %2;"
1027+ " text-align: left;"
1028+ " padding-left: 10px;"
1029+ " font-weight: bold;"
1030+ ).arg (Colors::ACCENT_BLUE).arg (Colors::ACCENT_BLUE);
1031+
1032+ // Inactive: Transparent + Gray Text
1033+ QString inactiveStyle = QString (
1034+ " background: transparent;"
1035+ " border: none;"
1036+ " border-left: 3px solid transparent;"
1037+ " color: %1;"
1038+ " text-align: left;"
1039+ " padding-left: 10px;"
1040+ ).arg (Colors::TEXT_SECONDARY);
9941041
9951042 if (m_currentMode == AppMode::LuaPatcher) {
9961043 m_tabLua->setStyleSheet (activeStyle);
997- m_tabFix->setStyleSheet (inactiveStyle);
998- m_stack->setCurrentIndex (1 ); // Show list
1044+ // Fix tab uses purple accent for active state if we want to differentiate,
1045+ // but for now let's keep it consistent or use its own accent
1046+
1047+ QString fixInactive = inactiveStyle; // Standard inactive
1048+ m_tabFix->setStyleSheet (fixInactive);
1049+
1050+ m_stack->setCurrentIndex (1 );
9991051 } else {
10001052 m_tabLua->setStyleSheet (inactiveStyle);
1001- m_tabFix->setStyleSheet (activeStyle);
1002- m_stack->setCurrentIndex (1 ); // Show list
1053+
1054+ // Active Style for Fix Manager (Purple Accent)
1055+ QString fixActive = QString (
1056+ " background: rgba(168, 85, 247, 0.15);" // Slight purple tint
1057+ " border: none;"
1058+ " border-left: 3px solid %1;"
1059+ " color: %2;"
1060+ " text-align: left;"
1061+ " padding-left: 10px;"
1062+ " font-weight: bold;"
1063+ ).arg (Colors::ACCENT_PURPLE).arg (Colors::ACCENT_PURPLE);
1064+
1065+ m_tabFix->setStyleSheet (fixActive);
1066+ m_stack->setCurrentIndex (1 );
10031067 }
10041068}
10051069
0 commit comments