3636#include " pcsx2/ImGui/FullscreenUI.h"
3737#include " pcsx2/MTGS.h"
3838#include " pcsx2/PerformanceMetrics.h"
39+ #include " pcsx2/VMManager.h"
40+ #include " pcsx2/ImGui/ImGuiOverlays.h"
41+ #include " pcsx2/SPU2/spu2.h"
3942#include " pcsx2/Recording/InputRecording.h"
4043#include " pcsx2/Recording/InputRecordingControls.h"
4144#include " pcsx2/SaveState.h"
5457#include < QtWidgets/QInputDialog>
5558#include < QtWidgets/QMessageBox>
5659#include < QtWidgets/QProgressBar>
60+ #include < QtWidgets/QSlider>
5761#include < QtWidgets/QStyle>
5862#include < QtWidgets/QStyleFactory>
63+ #include < QtWidgets/QWidgetAction>
64+ #include < QtWidgets/QHBoxLayout>
5965
6066#ifdef _WIN32
6167#include " common/RedtapeWindows.h"
@@ -185,6 +191,7 @@ void MainWindow::setupAdditionalUi()
185191{
186192 makeIconsMasks (menuBar ());
187193 updateAdvancedSettingsVisibility ();
194+ setupStatusBarWidgets ();
188195
189196 const bool toolbar_visible = Host::GetBaseBoolSettingValue (" UI" , " ShowToolbar" , false );
190197 m_ui.actionViewToolbar ->setChecked (toolbar_visible);
@@ -195,58 +202,6 @@ void MainWindow::setupAdditionalUi()
195202 m_ui.toolBar ->setMovable (!toolbars_locked);
196203 m_ui.toolBar ->setContextMenuPolicy (Qt::PreventContextMenu);
197204
198- const bool status_bar_visible = Host::GetBaseBoolSettingValue (" UI" , " ShowStatusBar" , true );
199- m_ui.actionViewStatusBar ->setChecked (status_bar_visible);
200- m_ui.statusBar ->setVisible (status_bar_visible);
201-
202- const bool show_game_grid = Host::GetBaseBoolSettingValue (" UI" , " GameListGridView" , false );
203- updateGameGridActions (show_game_grid);
204-
205- m_game_list_widget = new GameListWidget (getContentParent ());
206- m_game_list_widget->initialize ();
207- m_ui.actionGridViewShowTitles ->setChecked (m_game_list_widget->getShowGridCoverTitles ());
208- m_ui.mainContainer ->addWidget (m_game_list_widget);
209-
210- m_status_progress_widget = new QProgressBar (m_ui.statusBar );
211- m_status_progress_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
212- m_status_progress_widget->setFixedSize (140 , 16 );
213- m_status_progress_widget->setMinimum (0 );
214- m_status_progress_widget->setMaximum (100 );
215- m_status_progress_widget->hide ();
216-
217- m_status_verbose_widget = new QLabel (m_ui.statusBar );
218- m_status_verbose_widget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);
219- m_status_verbose_widget->setFixedHeight (16 );
220- m_status_verbose_widget->hide ();
221-
222- m_status_renderer_widget = new QLabel (m_ui.statusBar );
223- m_status_renderer_widget->setFixedHeight (16 );
224- m_status_renderer_widget->setFixedSize (65 , 16 );
225- m_status_renderer_widget->hide ();
226-
227- m_status_resolution_widget = new QLabel (m_ui.statusBar );
228- m_status_resolution_widget->setFixedHeight (16 );
229- m_status_resolution_widget->setFixedSize (75 , 16 );
230- m_status_resolution_widget->hide ();
231-
232- m_status_fps_widget = new QLabel (m_ui.statusBar );
233- m_status_fps_widget->setFixedHeight (16 );
234- m_status_fps_widget->setMinimumWidth (60 );
235- m_status_fps_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
236- m_status_fps_widget->hide ();
237-
238- m_status_vps_widget = new QLabel (m_ui.statusBar );
239- m_status_vps_widget->setFixedHeight (16 );
240- m_status_vps_widget->setMinimumWidth (60 );
241- m_status_vps_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
242- m_status_vps_widget->hide ();
243-
244- m_status_speed_widget = new QLabel (m_ui.statusBar );
245- m_status_speed_widget->setFixedHeight (16 );
246- m_status_speed_widget->setMinimumWidth (130 );
247- m_status_speed_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
248- m_status_speed_widget->hide ();
249-
250205 m_settings_toolbar_menu = new QMenu (m_ui.toolBar );
251206 m_settings_toolbar_menu->addAction (m_ui.actionSettings );
252207 m_settings_toolbar_menu->addAction (m_ui.actionViewGameProperties );
@@ -257,6 +212,14 @@ void MainWindow::setupAdditionalUi()
257212 connect (action, &QAction::triggered, [scale]() { g_emu_thread->requestDisplaySize (static_cast <float >(scale)); });
258213 }
259214
215+ const bool show_game_grid = Host::GetBaseBoolSettingValue (" UI" , " GameListGridView" , false );
216+ updateGameGridActions (show_game_grid);
217+
218+ m_game_list_widget = new GameListWidget (getContentParent ());
219+ m_game_list_widget->initialize ();
220+ m_ui.actionGridViewShowTitles ->setChecked (m_game_list_widget->getShowGridCoverTitles ());
221+ m_ui.mainContainer ->addWidget (m_game_list_widget);
222+
260223 updateEmulationActions (false , false , false );
261224 updateDisplayRelatedActions (false , false , false );
262225
@@ -292,6 +255,158 @@ void MainWindow::setupAdditionalUi()
292255#endif
293256}
294257
258+ void MainWindow::setupStatusBarWidgets ()
259+ {
260+ const bool status_bar_visible = Host::GetBaseBoolSettingValue (" UI" , " ShowStatusBar" , true );
261+ m_ui.actionViewStatusBar ->setChecked (status_bar_visible);
262+ m_ui.statusBar ->setVisible (status_bar_visible);
263+
264+ m_status_progress_widget = new QProgressBar (m_ui.statusBar );
265+ m_status_progress_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
266+ m_status_progress_widget->setFixedSize (140 , 16 );
267+ m_status_progress_widget->setMinimum (0 );
268+ m_status_progress_widget->setMaximum (100 );
269+ m_status_progress_widget->hide ();
270+
271+ m_status_verbose_widget = new QLabel (m_ui.statusBar );
272+ m_status_verbose_widget->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Fixed);
273+ m_status_verbose_widget->setFixedHeight (20 );
274+ m_status_verbose_widget->hide ();
275+
276+ m_status_renderer_widget = new QToolButton (m_ui.statusBar );
277+ m_status_renderer_widget->setAutoRaise (true );
278+ m_status_renderer_widget->setToolButtonStyle (Qt::ToolButtonTextOnly);
279+ m_status_renderer_widget->setPopupMode (QToolButton::InstantPopup);
280+ m_status_renderer_widget->setMinimumWidth (80 );
281+ m_status_renderer_widget->setFixedHeight (20 );
282+
283+ m_status_renderer_menu = new QMenu (m_status_renderer_widget);
284+ m_status_renderer_widget->setMenu (m_status_renderer_menu);
285+
286+ m_status_renderer_widget->hide ();
287+ m_ui.statusBar ->addPermanentWidget (m_status_renderer_widget);
288+
289+ m_status_resolution_widget = new QToolButton (m_ui.statusBar );
290+ m_status_resolution_widget->setAutoRaise (true );
291+ m_status_resolution_widget->setToolButtonStyle (Qt::ToolButtonTextOnly);
292+ m_status_resolution_widget->setPopupMode (QToolButton::InstantPopup);
293+ m_status_resolution_widget->setMinimumWidth (120 );
294+ m_status_resolution_widget->setFixedHeight (20 );
295+
296+ m_status_resolution_menu = new QMenu (m_status_resolution_widget);
297+ const float current_upscale = Host::GetBaseFloatSettingValue (" EmuCore/GS" , " upscale_multiplier" , 1 .0f );
298+ QActionGroup* resolution_group = new QActionGroup (m_status_resolution_menu);
299+ static constexpr const u32 max_upscale_multiplier = 12 ;
300+ for (u32 scale = 1 ; scale <= max_upscale_multiplier; scale++)
301+ {
302+ const float fscale = static_cast <float >(scale);
303+ QAction* action = m_status_resolution_menu->addAction (tr (" %1x Scale" ).arg (scale), [fscale]() {
304+ MTGS::RunOnGSThread ([fscale]() {
305+ EmuConfig.GS .UpscaleMultiplier = fscale;
306+ MTGS::ApplySettings ();
307+ });
308+ });
309+ action->setCheckable (true );
310+ action->setActionGroup (resolution_group);
311+ action->setChecked (std::abs (current_upscale - fscale) < 0 .01f );
312+ }
313+ m_status_resolution_widget->setMenu (m_status_resolution_menu);
314+ m_status_resolution_widget->hide ();
315+
316+ m_status_slot_widget = new QToolButton (m_ui.statusBar );
317+ m_status_slot_widget->setAutoRaise (true );
318+ m_status_slot_widget->setToolButtonStyle (Qt::ToolButtonTextOnly);
319+ m_status_slot_widget->setPopupMode (QToolButton::InstantPopup);
320+ m_status_slot_widget->setMinimumWidth (60 );
321+ m_status_slot_widget->setFixedHeight (20 );
322+
323+ m_status_slot_menu = new QMenu (m_status_slot_widget);
324+ for (s32 i = 1 ; i <= VMManager::NUM_SAVE_STATE_SLOTS; i++)
325+ m_status_slot_menu->addAction (tr (" Slot %1" ).arg (i), [i]() { Host::RunOnGSThread ([i] { SaveStateSelectorUI::SetCurrentSlot (i); }); });
326+
327+ m_status_slot_widget->setMenu (m_status_slot_menu);
328+ m_status_slot_widget->hide ();
329+
330+ m_status_volume_widget = new QToolButton (m_ui.statusBar );
331+ m_status_volume_widget->setAutoRaise (true );
332+ m_status_volume_widget->setToolButtonStyle (Qt::ToolButtonTextOnly);
333+ m_status_volume_widget->setPopupMode (QToolButton::InstantPopup);
334+ m_status_volume_widget->setMinimumWidth (100 );
335+ m_status_volume_widget->setFixedHeight (20 );
336+
337+ m_status_volume_menu = new QMenu (m_status_volume_widget);
338+ m_status_volume_menu->addAction (tr (" Mute Audio" ), []() {
339+ Host::RunOnCPUThread ([]() {
340+ if (VMManager::HasValidVM ())
341+ {
342+ const bool new_muted = !SPU2::IsOutputMuted ();
343+ if (SPU2::SetOutputMuted (new_muted))
344+ SPU2::SetOutputMuted (new_muted);
345+ }
346+ });
347+ });
348+ m_status_volume_menu->addSeparator ();
349+
350+ m_status_volume_slider = new QSlider (Qt::Horizontal, m_status_volume_menu);
351+ m_status_volume_slider->setRange (0 , 100 );
352+ m_status_volume_slider->setFixedWidth (120 );
353+ m_status_volume_slider->setValue (Host::GetBaseIntSettingValue (" SPU2/Output" , " StandardVolume" , 100 ));
354+ connect (m_status_volume_slider, &QSlider::valueChanged, [](int value) {
355+ Host::RunOnCPUThread ([value]() {
356+ if (VMManager::HasValidVM ())
357+ {
358+ SPU2::SetOutputMuted (false );
359+ SPU2::SetOutputVolume (static_cast <u32 >(value));
360+ }
361+ });
362+ });
363+
364+ QWidget* container = new QWidget (m_status_volume_menu);
365+ QHBoxLayout* layout = new QHBoxLayout (container);
366+ layout->setContentsMargins (8 , 4 , 8 , 4 );
367+ layout->addWidget (m_status_volume_slider);
368+
369+ QWidgetAction* slider_action = new QWidgetAction (m_status_volume_menu);
370+ slider_action->setDefaultWidget (container);
371+ m_status_volume_menu->addAction (slider_action);
372+ m_status_volume_widget->setMenu (m_status_volume_menu);
373+ m_status_volume_widget->hide ();
374+
375+ m_status_speed_widget = new QToolButton (m_ui.statusBar );
376+ m_status_speed_widget->setAutoRaise (true );
377+ m_status_speed_widget->setToolButtonStyle (Qt::ToolButtonTextOnly);
378+ m_status_speed_widget->setPopupMode (QToolButton::InstantPopup);
379+ m_status_speed_widget->setFixedHeight (20 );
380+ m_status_speed_widget->setMinimumWidth (60 );
381+ m_status_speed_widget->hide ();
382+
383+ m_status_speed_menu = new QMenu (m_status_speed_widget);
384+ m_status_speed_menu->addAction (tr (" Unlimited" ), []() { VMManager::SetLimiterMode (LimiterModeType::Unlimited); });
385+ m_status_speed_menu->addAction (tr (" Turbo" ), []() { VMManager::SetLimiterMode (LimiterModeType::Turbo); });
386+ m_status_speed_menu->addAction (tr (" Slow-Motion" ), []() { VMManager::SetLimiterMode (LimiterModeType::Slomo); });
387+ m_status_speed_menu->addAction (tr (" Normal" ), []() { VMManager::SetLimiterMode (LimiterModeType::Nominal); });
388+ m_status_speed_widget->setMenu (m_status_speed_menu);
389+ m_status_speed_widget->hide ();
390+
391+ m_status_gpu_widget = new QLabel (m_ui.statusBar );
392+ m_status_gpu_widget->setFixedHeight (20 );
393+ m_status_gpu_widget->setMinimumWidth (60 );
394+ m_status_gpu_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
395+ m_status_gpu_widget->hide ();
396+
397+ m_status_fps_widget = new QLabel (m_ui.statusBar );
398+ m_status_fps_widget->setFixedHeight (20 );
399+ m_status_fps_widget->setMinimumWidth (60 );
400+ m_status_fps_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
401+ m_status_fps_widget->hide ();
402+
403+ m_status_vps_widget = new QLabel (m_ui.statusBar );
404+ m_status_vps_widget->setFixedHeight (20 );
405+ m_status_vps_widget->setMinimumWidth (60 );
406+ m_status_vps_widget->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed);
407+ m_status_vps_widget->hide ();
408+ }
409+
295410void MainWindow::connectSignals ()
296411{
297412 connect (m_ui.actionStartFile , &QAction::triggered, this , &MainWindow::onStartFileActionTriggered);
@@ -432,7 +547,8 @@ void MainWindow::connectSignals()
432547 connect (m_game_list_widget, &GameListWidget::addGameDirectoryRequested, this ,
433548 [this ]() { getSettingsWindow ()->getGameListSettingsWidget ()->addSearchDirectory (this ); });
434549
435- createRendererSwitchMenu ();
550+ connect (m_ui.menuDebugSwitchRenderer , &QMenu::aboutToShow, [this ] { populateRendererMenu (m_ui.menuDebugSwitchRenderer ); });
551+ connect (m_status_renderer_menu, &QMenu::aboutToShow, [this ] { populateRendererMenu (m_status_renderer_menu); });
436552}
437553
438554void MainWindow::connectVMThreadSignals (EmuThread* thread)
@@ -468,7 +584,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
468584 connect (m_ui.actionReloadPatches , &QAction::triggered, thread, &EmuThread::reloadPatches);
469585}
470586
471- void MainWindow::createRendererSwitchMenu ( )
587+ void MainWindow::populateRendererMenu (QMenu* menu )
472588{
473589 static constexpr const GSRendererType renderers[] = {
474590 GSRendererType::Auto,
@@ -490,23 +606,22 @@ void MainWindow::createRendererSwitchMenu()
490606 const GSRendererType current_renderer = static_cast <GSRendererType>(
491607 Host::GetBaseIntSettingValue (" EmuCore/GS" , " Renderer" , static_cast <int >(GSRendererType::Auto)));
492608
493- QActionGroup* switch_renderer_group = new QActionGroup (m_ui.menuDebugSwitchRenderer );
609+ menu->clear ();
610+
611+ QActionGroup* switch_renderer_group = new QActionGroup (menu);
494612
495613 for (const GSRendererType renderer : renderers)
496614 {
497- QAction* action = new QAction (
498- QString::fromUtf8 (Pcsx2Config::GSOptions::GetRendererName (renderer)), switch_renderer_group);
499- action->setCheckable (true );
500- action->setChecked (current_renderer == renderer);
501- connect (action,
502- &QAction::triggered, [renderer] {
615+ QAction* action = menu->addAction (
616+ QString::fromUtf8 (Pcsx2Config::GSOptions::GetRendererName (renderer)), [renderer] {
503617 Host::SetBaseIntSettingValue (" EmuCore/GS" , " Renderer" , static_cast <int >(renderer));
504618 Host::CommitBaseSettingChanges ();
505619 g_emu_thread->applySettings ();
506620 });
621+ action->setCheckable (true );
622+ action->setChecked (current_renderer == renderer);
623+ action->setActionGroup (switch_renderer_group);
507624 }
508-
509- m_ui.menuDebugSwitchRenderer ->addActions (switch_renderer_group->actions ());
510625}
511626
512627void MainWindow::recreate ()
@@ -997,11 +1112,60 @@ void MainWindow::updateStatusBarWidgetVisibility()
9971112 };
9981113
9991114 Update (m_status_verbose_widget, s_vm_valid, 1 );
1115+ Update (m_status_slot_widget, s_vm_valid, 0 );
10001116 Update (m_status_renderer_widget, s_vm_valid, 0 );
10011117 Update (m_status_resolution_widget, s_vm_valid, 0 );
1118+ Update (m_status_volume_widget, s_vm_valid, 0 );
1119+ Update (m_status_speed_widget, s_vm_valid, 0 );
1120+ Update (m_status_gpu_widget, s_vm_valid, 0 );
10021121 Update (m_status_fps_widget, s_vm_valid, 0 );
10031122 Update (m_status_vps_widget, s_vm_valid, 0 );
1004- Update (m_status_speed_widget, s_vm_valid, 0 );
1123+ }
1124+
1125+ void MainWindow::setStatusRendererText (const QString& text)
1126+ {
1127+ m_status_renderer_widget->setText (text);
1128+ }
1129+
1130+ void MainWindow::setStatusResolutionText (const QString& text)
1131+ {
1132+ m_status_resolution_widget->setText (text);
1133+ }
1134+
1135+ void MainWindow::setStatusSlotText (const QString& text)
1136+ {
1137+ m_status_slot_widget->setText (text);
1138+ }
1139+
1140+ void MainWindow::setStatusVolumeText (const QString& text, int volume)
1141+ {
1142+ m_status_volume_widget->setText (text);
1143+
1144+ if (m_status_volume_slider && !m_status_volume_slider->isSliderDown ())
1145+ {
1146+ QSignalBlocker blocker (m_status_volume_slider);
1147+ m_status_volume_slider->setValue (volume);
1148+ }
1149+ }
1150+
1151+ void MainWindow::setStatusGPUText (const QString& text)
1152+ {
1153+ m_status_gpu_widget->setText (text);
1154+ }
1155+
1156+ void MainWindow::setStatusFPSText (const QString& text)
1157+ {
1158+ m_status_fps_widget->setText (text);
1159+ }
1160+
1161+ void MainWindow::setStatusVPSText (const QString& text)
1162+ {
1163+ m_status_vps_widget->setText (text);
1164+ }
1165+
1166+ void MainWindow::setStatusSpeedText (const QString& text)
1167+ {
1168+ m_status_speed_widget->setText (text);
10051169}
10061170
10071171void MainWindow::updateWindowTitle ()
@@ -2182,6 +2346,9 @@ void MainWindow::onVMStopped()
21822346 m_last_fps_status = empty_string;
21832347 m_status_renderer_widget->setText (empty_string);
21842348 m_status_resolution_widget->setText (empty_string);
2349+ m_status_slot_widget->setText (empty_string);
2350+ m_status_volume_widget->setText (empty_string);
2351+ m_status_gpu_widget->setText (empty_string);
21852352 m_status_fps_widget->setText (empty_string);
21862353 m_status_vps_widget->setText (empty_string);
21872354 m_status_speed_widget->setText (empty_string);
0 commit comments