From 25bb8a444fb3a7ca6c19a429f2d89e83a6ddb823 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Thu, 27 Jul 2017 02:40:41 -0700 Subject: [PATCH] UI: Add modular UI Changes the UI to an adjustable user interface, allowing the user to fully customize how the scenes list, sources list, the mixer, transitions, and the buttons are oriented on the main window window. --- UI/data/locale/en-US.ini | 4 + UI/forms/OBSBasic.ui | 1672 ++++++++++++++++++++------------------ UI/window-basic-main.cpp | 127 ++- UI/window-basic-main.hpp | 6 +- 4 files changed, 1010 insertions(+), 799 deletions(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index b7a01d854..78a0c0b23 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -429,6 +429,7 @@ Basic.Main.AddSourceHelp.Text="You need to have at least 1 scene to add a source # basic mode main window Basic.Main.Scenes="Scenes" Basic.Main.Sources="Sources" +Basic.Main.Controls="Controls" Basic.Main.Connecting="Connecting..." Basic.Main.StartRecording="Start Recording" Basic.Main.StartReplayBuffer="Start Replay Buffer" @@ -487,6 +488,9 @@ Basic.MainMenu.Edit.AdvAudio="&Advanced Audio Properties" # basic mode view menu Basic.MainMenu.View="&View" Basic.MainMenu.View.Toolbars="&Toolbars" +Basic.MainMenu.View.Docks="Docks" +Basic.MainMenu.View.Docks.ResetUI="Reset UI" +Basic.MainMenu.View.Docks.LockUI="Lock UI" Basic.MainMenu.View.Toolbars.Listboxes="&Listboxes" Basic.MainMenu.View.SceneTransitions="S&cene Transitions" Basic.MainMenu.View.StatusBar="&Status Bar" diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index 53998458a..cb11bb446 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -7,8 +7,8 @@ 0 0 - 1110 - 724 + 1079 + 730 @@ -34,238 +34,40 @@ - + - - - Qt::Vertical - - - false - - - + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + Basic.Main.PreviewDisabled + + + Qt::AlignCenter + + + + + + + 2 + - + - 2 + 4 - - - 4 - - - - - - 0 - 0 - - - - - 32 - 32 - - - - Qt::ClickFocus - - - Qt::CustomContextMenu - - - - - - - - - - - - 0 - 0 - - - - Qt::CustomContextMenu - - - Basic.Main.PreviewDisabled - - - Qt::AlignCenter - - - - - - - - - - - 2 - - - - - true - - - - 0 - 0 - - - - Basic.Main.StartStreaming - - - false - - - - - - - true - - - - 0 - 0 - - - - - 130 - 0 - - - - Basic.Main.StartRecording - - - - - - - Basic.TogglePreviewProgramMode - - - true - - - - - - - - 0 - 0 - - - - Settings - - - - - - - - 0 - 0 - - - - Exit - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - - - - 220 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - Qt::ScrollBarAlwaysOn - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 215 - 16 - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - - - + 0 @@ -274,537 +76,23 @@ - 160 - 0 + 32 + 32 - - - 260 - 16777215 - + + Qt::ClickFocus - - QFrame::StyledPanel + + Qt::CustomContextMenu - - QFrame::Sunken - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Qt::CustomContextMenu - - - QFrame::NoFrame - - - QFrame::Plain - - - true - - - true - - - QAbstractItemView::InternalMove - - - Qt::TargetMoveAction - - - - - - - - - 16 - 16 - - - - false - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 150 - 0 - - - - - - - - - Basic.Main.Sources - - - - - - - 2 - - - - - - 0 - 0 - - - - Mixer - - - - - - - - 0 - 0 - - - - - 22 - 22 - - - - Basic.AdvAudio - - - - - - - :/res/images/configuration21_16.png:/res/images/configuration21_16.png - - - true - - - configIconSmall - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - 160 - 0 - - - - - 260 - 16777215 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Qt::CustomContextMenu - - - QFrame::NoFrame - - - true - - - true - - - QAbstractItemView::InternalMove - - - Qt::TargetMoveAction - - - QAbstractItemView::ExtendedSelection - - - - - - - - - 16 - 16 - - - - false - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 150 - 0 - - - - - - - - - - - - - Basic.Main.Scenes - - - - - - - Basic.SceneTransitions - - - - - - - - 4 - - - 1 - - - 1 - - - 1 - - - 2 - - - - - - 120 - 0 - - - - Transition - - - - - - - 4 - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 22 - 22 - - - - Basic.AddTransition - - - Basic.AddTransition - - - - - - - :/res/images/add.png:/res/images/add.png - - - true - - - addIconSmall - - - - - - - - 0 - 0 - - - - - 22 - 22 - - - - Basic.RemoveTransition - - - Basic.RemoveTransition - - - - - - - :/res/images/list_remove.png:/res/images/list_remove.png - - - true - - - removeIconSmall - - - - - - - - 0 - 0 - - - - - 22 - 22 - - - - Basic.TransitionProperties - - - Basic.TransitionProperties - - - - - - - :/res/images/configuration21_16.png:/res/images/configuration21_16.png - - - true - - - configIconSmall - - - - - - - - - 4 - - - - - - 0 - 0 - - - - Basic.TransitionDuration - - - transitionDuration - - - - - - - Basic.TransitionDuration - - - ms - - - 2 - - - 10000 - - - 50 - - - 300 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - + + @@ -813,7 +101,7 @@ 0 0 - 1110 + 1079 21 @@ -978,18 +266,31 @@ - - - - F11 + + + Basic.MainMenu.View.Docks + + + + + + + + + + Basic.MainMenu.View.Fullscreen.Interface + + F11 + + + - @@ -1010,6 +311,773 @@ + + + QDockWidget::AllDockWidgetFeatures + + + Basic.Main.Scenes + + + 8 + + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + true + + + QAbstractItemView::InternalMove + + + Qt::TargetMoveAction + + + + + + + + 16 + 16 + + + + false + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 150 + 0 + + + + + + + + + + + + + QDockWidget::AllDockWidgetFeatures + + + Basic.Main.Sources + + + 8 + + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 160 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Qt::CustomContextMenu + + + QFrame::NoFrame + + + true + + + true + + + QAbstractItemView::InternalMove + + + Qt::TargetMoveAction + + + QAbstractItemView::ExtendedSelection + + + + + + + + 16 + 16 + + + + false + + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 150 + 0 + + + + + + + + + + + + + QDockWidget::AllDockWidgetFeatures + + + Mixer + + + 8 + + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 220 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 230 + 16 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 2 + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + Basic.AdvAudio + + + + + + + :/res/images/configuration21_16.png:/res/images/configuration21_16.png + + + true + + + configIconSmall + + + + + + + + + + + QDockWidget::AllDockWidgetFeatures + + + Basic.SceneTransitions + + + 8 + + + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 4 + + + 1 + + + 1 + + + 1 + + + 2 + + + + + + 120 + 0 + + + + Transition + + + + + + + 4 + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + Basic.AddTransition + + + Basic.AddTransition + + + + + + + :/res/images/add.png:/res/images/add.png + + + true + + + addIconSmall + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + Basic.RemoveTransition + + + Basic.RemoveTransition + + + + + + + :/res/images/list_remove.png:/res/images/list_remove.png + + + true + + + removeIconSmall + + + + + + + + 0 + 0 + + + + + 22 + 22 + + + + Basic.TransitionProperties + + + Basic.TransitionProperties + + + + + + + :/res/images/configuration21_16.png:/res/images/configuration21_16.png + + + true + + + configIconSmall + + + + + + + + + 4 + + + + + + 0 + 0 + + + + Basic.TransitionDuration + + + transitionDuration + + + + + + + Basic.TransitionDuration + + + ms + + + 2 + + + 10000 + + + 50 + + + 300 + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + QDockWidget::AllDockWidgetFeatures + + + Basic.Main.Controls + + + 8 + + + + + 2 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + true + + + + 0 + 0 + + + + Basic.Main.StartStreaming + + + false + + + + + + + true + + + + 0 + 0 + + + + + 130 + 0 + + + + Basic.Main.StartRecording + + + + + + + Basic.TogglePreviewProgramMode + + + true + + + + + + + + 0 + 0 + + + + Settings + + + + + + + + 0 + 0 + + + + Exit + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + @@ -1414,17 +1482,6 @@ Basic.MainMenu.View.Toolbars.Listboxes - - - true - - - true - - - Basic.MainMenu.View.SceneTransitions - - true @@ -1488,6 +1545,77 @@ Basic.Stats + + + Basic.MainMenu.View.Docks.ResetUI + + + + + true + + + true + + + Basic.MainMenu.View.Docks.LockUI + + + + + true + + + true + + + Basic.Main.Scenes + + + + + true + + + true + + + Basic.Main.Sources + + + + + true + + + true + + + Mixer + + + + + true + + + true + + + Basic.SceneTransitions + + + + + true + + + true + + + Basic.Main.Controls + + @@ -1540,12 +1668,12 @@ close() - 838 - 272 + 976 + 601 - 902 - -10 + 862 + -11 diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 055179cd0..65b680b77 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -145,6 +145,8 @@ OBSBasic::OBSBasic(QWidget *parent) ui->setupUi(this); ui->previewDisabledLabel->setVisible(false); + startingDockLayout = saveState(); + copyActionsDynamicProperties(); ui->sources->setItemDelegate(new VisibilityItemDelegate(ui->sources)); @@ -257,6 +259,33 @@ OBSBasic::OBSBasic(QWidget *parent) addNudge(Qt::Key_Down, SLOT(NudgeDown())); addNudge(Qt::Key_Left, SLOT(NudgeLeft())); addNudge(Qt::Key_Right, SLOT(NudgeRight())); + + auto assignDockToggle = [this](QDockWidget *dock, QAction *action) + { + auto handleWindowToggle = [action] (bool vis) + { + action->blockSignals(true); + action->setChecked(vis); + action->blockSignals(false); + }; + auto handleMenuToggle = [dock] (bool check) + { + dock->blockSignals(true); + dock->setVisible(check); + dock->blockSignals(false); + }; + + dock->connect(dock->toggleViewAction(), &QAction::toggled, + handleWindowToggle); + dock->connect(action, &QAction::toggled, + handleMenuToggle); + }; + + assignDockToggle(ui->scenesDock, ui->toggleScenes); + assignDockToggle(ui->sourcesDock, ui->toggleSources); + assignDockToggle(ui->mixerDock, ui->toggleMixer); + assignDockToggle(ui->transitionsDock, ui->toggleTransitions); + assignDockToggle(ui->controlsDock, ui->toggleControls); } static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent, @@ -1355,7 +1384,6 @@ void OBSBasic::OBSInit() } \ } while (false) - SET_VISIBILITY("ShowTransitions", toggleSceneTransitions); SET_VISIBILITY("ShowListboxToolbars", toggleListboxToolbars); SET_VISIBILITY("ShowStatusBar", toggleStatusBar); #undef SET_VISIBILITY @@ -1419,24 +1447,26 @@ void OBSBasic::OBSInit() show(); #endif - QList defSizes; - - int top = config_get_int(App()->GlobalConfig(), "BasicWindow", - "splitterTop"); - int bottom = config_get_int(App()->GlobalConfig(), "BasicWindow", - "splitterBottom"); - - if (!top || !bottom) { - defSizes = ui->mainSplitter->sizes(); - int total = defSizes[0] + defSizes[1]; - defSizes[0] = total * 75 / 100; - defSizes[1] = total - defSizes[0]; + const char *dockStateStr = config_get_string(App()->GlobalConfig(), + "BasicWindow", "DockState"); + if (!dockStateStr) { + on_resetUI_triggered(); } else { - defSizes.push_back(top); - defSizes.push_back(bottom); + QByteArray dockState = + QByteArray::fromBase64(QByteArray(dockStateStr)); + if (!restoreState(dockState)) + on_resetUI_triggered(); } - ui->mainSplitter->setSizes(defSizes); + config_set_default_bool(App()->GlobalConfig(), "BasicWindow", + "DocksLocked", true); + + bool docksLocked = config_get_bool(App()->GlobalConfig(), + "BasicWindow", "DocksLocked"); + on_lockUI_toggled(docksLocked); + ui->lockUI->blockSignals(true); + ui->lockUI->setChecked(docksLocked); + ui->lockUI->blockSignals(false); SystemTray(true); @@ -1758,13 +1788,8 @@ OBSBasic::~OBSBasic() config_set_int(App()->GlobalConfig(), "General", "LastVersion", LIBOBS_API_VER); - QList splitterSizes = ui->mainSplitter->sizes(); bool alwaysOnTop = IsAlwaysOnTop(this); - config_set_int(App()->GlobalConfig(), "BasicWindow", "splitterTop", - splitterSizes[0]); - config_set_int(App()->GlobalConfig(), "BasicWindow", "splitterBottom", - splitterSizes[1]); config_set_bool(App()->GlobalConfig(), "BasicWindow", "PreviewEnabled", previewEnabled); config_set_bool(App()->GlobalConfig(), "BasicWindow", "AlwaysOnTop", @@ -1777,6 +1802,8 @@ OBSBasic::~OBSBasic() "EditPropertiesMode", editPropertiesMode); config_set_bool(App()->GlobalConfig(), "BasicWindow", "PreviewProgramMode", IsPreviewProgramMode()); + config_set_bool(App()->GlobalConfig(), "BasicWindow", + "DocksLocked", ui->lockUI->isChecked()); config_save_safe(App()->GlobalConfig(), "tmp", nullptr); #ifdef _WIN32 @@ -2981,6 +3008,10 @@ void OBSBasic::closeEvent(QCloseEvent *event) "BasicWindow", "geometry", saveGeometry().toBase64().constData()); + config_set_string(App()->GlobalConfig(), + "BasicWindow", "DockState", + saveState().toBase64().constData()); + if (outputHandler && outputHandler->Active()) { SetShowing(true); @@ -5253,13 +5284,57 @@ int OBSBasic::GetProfilePath(char *path, size_t size, const char *file) const return snprintf(path, size, "%s/%s/%s", profiles_path, profile, file); } -void OBSBasic::on_toggleSceneTransitions_toggled(bool visible) +void OBSBasic::on_resetUI_triggered() { - ui->sceneTransitionsLabel->setVisible(visible); - ui->transitionsContainer->setVisible(visible); + restoreState(startingDockLayout); - config_set_bool(App()->GlobalConfig(), "BasicWindow", - "ShowTransitions", visible); + int cx = width(); + int cy = height(); + + int cx22_5 = cx * 225 / 1000; + int cx5 = cx * 5 / 100; + + cy = cy * 225 / 1000; + + int mixerSize = cx - (cx22_5 * 2 + cx5 * 2); + + QList docks { + ui->scenesDock, + ui->sourcesDock, + ui->mixerDock, + ui->transitionsDock, + ui->controlsDock + }; + + QList sizes { + cx22_5, + cx22_5, + mixerSize, + cx5, + cx5 + }; + + ui->scenesDock->setVisible(true); + ui->sourcesDock->setVisible(true); + ui->mixerDock->setVisible(true); + ui->transitionsDock->setVisible(true); + ui->controlsDock->setVisible(true); + + resizeDocks(docks, {cy, cy, cy, cy, cy}, Qt::Vertical); + resizeDocks(docks, sizes, Qt::Horizontal); +} + +void OBSBasic::on_lockUI_toggled(bool lock) +{ + QDockWidget::DockWidgetFeatures features = lock + ? QDockWidget::NoDockWidgetFeatures + : QDockWidget::AllDockWidgetFeatures; + + ui->scenesDock->setFeatures(features); + ui->sourcesDock->setFeatures(features); + ui->mixerDock->setFeatures(features); + ui->transitionsDock->setFeatures(features); + ui->controlsDock->setFeatures(features); } void OBSBasic::on_toggleListboxToolbars_toggled(bool visible) diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index d34b74d0f..85e804600 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -348,6 +348,8 @@ private: QList visDlgPositions; + QByteArray startingDockLayout; + obs_data_array_t *SaveProjectors(); void LoadSavedProjectors(obs_data_array_t *savedProjectors); @@ -615,7 +617,6 @@ private slots: void on_actionAlwaysOnTop_triggered(); - void on_toggleSceneTransitions_toggled(bool visible); void on_toggleListboxToolbars_toggled(bool visible); void on_toggleStatusBar_toggled(bool visible); @@ -629,6 +630,9 @@ private slots: void on_autoConfigure_triggered(); void on_stats_triggered(); + void on_resetUI_triggered(); + void on_lockUI_toggled(bool lock); + void logUploadFinished(const QString &text, const QString &error); void updateCheckFinished();