123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /******************************************************************************
- Copyright (C) 2023 by Lain Bailey <[email protected]>
- Zachary Lund <[email protected]>
- Philippe Groarke <[email protected]>
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- ******************************************************************************/
- #include "OBSBasic.hpp"
- #include <qt-wrappers.hpp>
- void assignDockToggle(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);
- }
- void setupDockAction(QDockWidget *dock)
- {
- QAction *action = dock->toggleViewAction();
- auto neverDisable = [action]() {
- QSignalBlocker block(action);
- action->setEnabled(true);
- };
- auto newToggleView = [dock](bool check) {
- QSignalBlocker block(dock);
- dock->setVisible(check);
- };
- // Replace the slot connected by default
- QObject::disconnect(action, &QAction::triggered, nullptr, 0);
- dock->connect(action, &QAction::triggered, newToggleView);
- // Make the action unable to be disabled
- action->connect(action, &QAction::enabledChanged, neverDisable);
- }
- void OBSBasic::on_resetDocks_triggered(bool force)
- {
- /* prune deleted extra docks */
- for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
- if (!oldExtraDocks[i]) {
- oldExtraDocks.removeAt(i);
- oldExtraDockNames.removeAt(i);
- }
- }
- #ifdef BROWSER_AVAILABLE
- if ((oldExtraDocks.size() || extraDocks.size() || extraCustomDocks.size() || extraBrowserDocks.size()) &&
- !force)
- #else
- if ((oldExtraDocks.size() || extraDocks.size() || extraCustomDocks.size()) && !force)
- #endif
- {
- QMessageBox::StandardButton button =
- OBSMessageBox::question(this, QTStr("ResetUIWarning.Title"), QTStr("ResetUIWarning.Text"));
- if (button == QMessageBox::No)
- return;
- }
- /* undock/hide/center extra docks */
- for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
- if (oldExtraDocks[i]) {
- oldExtraDocks[i]->setVisible(true);
- oldExtraDocks[i]->setFloating(true);
- oldExtraDocks[i]->move(frameGeometry().topLeft() + rect().center() -
- oldExtraDocks[i]->rect().center());
- oldExtraDocks[i]->setVisible(false);
- }
- }
- #define RESET_DOCKLIST(dockList) \
- for (int i = dockList.size() - 1; i >= 0; i--) { \
- dockList[i]->setVisible(true); \
- dockList[i]->setFloating(true); \
- dockList[i]->move(frameGeometry().topLeft() + rect().center() - dockList[i]->rect().center()); \
- dockList[i]->setVisible(false); \
- }
- RESET_DOCKLIST(extraDocks)
- RESET_DOCKLIST(extraCustomDocks)
- #ifdef BROWSER_AVAILABLE
- RESET_DOCKLIST(extraBrowserDocks)
- #endif
- #undef RESET_DOCKLIST
- restoreState(startingDockLayout);
- int cx = width();
- int cy = height();
- int cx22_5 = cx * 225 / 1000;
- int cx5 = cx * 5 / 100;
- int cx21 = cx * 21 / 100;
- cy = cy * 225 / 1000;
- int mixerSize = cx - (cx22_5 * 2 + cx5 + cx21);
- QList<QDockWidget *> docks{ui->scenesDock, ui->sourcesDock, ui->mixerDock, ui->transitionsDock, controlsDock};
- QList<int> sizes{cx22_5, cx22_5, mixerSize, cx5, cx21};
- ui->scenesDock->setVisible(true);
- ui->sourcesDock->setVisible(true);
- ui->mixerDock->setVisible(true);
- ui->transitionsDock->setVisible(true);
- controlsDock->setVisible(true);
- statsDock->setVisible(false);
- statsDock->setFloating(true);
- resizeDocks(docks, {cy, cy, cy, cy, cy}, Qt::Vertical);
- resizeDocks(docks, sizes, Qt::Horizontal);
- activateWindow();
- }
- void OBSBasic::on_lockDocks_toggled(bool lock)
- {
- QDockWidget::DockWidgetFeatures features =
- lock ? QDockWidget::NoDockWidgetFeatures
- : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
- QDockWidget::DockWidgetFloatable);
- QDockWidget::DockWidgetFeatures mainFeatures = features;
- mainFeatures &= ~QDockWidget::QDockWidget::DockWidgetClosable;
- ui->scenesDock->setFeatures(mainFeatures);
- ui->sourcesDock->setFeatures(mainFeatures);
- ui->mixerDock->setFeatures(mainFeatures);
- ui->transitionsDock->setFeatures(mainFeatures);
- controlsDock->setFeatures(mainFeatures);
- statsDock->setFeatures(features);
- for (int i = extraDocks.size() - 1; i >= 0; i--)
- extraDocks[i]->setFeatures(features);
- for (int i = extraCustomDocks.size() - 1; i >= 0; i--)
- extraCustomDocks[i]->setFeatures(features);
- #ifdef BROWSER_AVAILABLE
- for (int i = extraBrowserDocks.size() - 1; i >= 0; i--)
- extraBrowserDocks[i]->setFeatures(features);
- #endif
- for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
- if (!oldExtraDocks[i]) {
- oldExtraDocks.removeAt(i);
- oldExtraDockNames.removeAt(i);
- } else {
- oldExtraDocks[i]->setFeatures(features);
- }
- }
- }
- void OBSBasic::on_sideDocks_toggled(bool side)
- {
- if (side) {
- setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
- setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
- setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
- setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
- } else {
- setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
- setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
- setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
- setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
- }
- }
- QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
- {
- // Prevent the object name from being changed
- connect(dock, &QObject::objectNameChanged, this, &OBSBasic::RepairOldExtraDockName);
- #ifdef BROWSER_AVAILABLE
- QAction *action = new QAction(dock->windowTitle(), ui->menuDocks);
- if (!extraBrowserMenuDocksSeparator.isNull())
- ui->menuDocks->insertAction(extraBrowserMenuDocksSeparator, action);
- else
- ui->menuDocks->addAction(action);
- #else
- QAction *action = ui->menuDocks->addAction(dock->windowTitle());
- #endif
- action->setCheckable(true);
- action->setMenuRole(QAction::NoRole);
- assignDockToggle(dock, action);
- oldExtraDocks.push_back(dock);
- oldExtraDockNames.push_back(dock->objectName());
- bool lock = ui->lockDocks->isChecked();
- QDockWidget::DockWidgetFeatures features =
- lock ? QDockWidget::NoDockWidgetFeatures
- : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
- QDockWidget::DockWidgetFloatable);
- dock->setFeatures(features);
- /* prune deleted docks */
- for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
- if (!oldExtraDocks[i]) {
- oldExtraDocks.removeAt(i);
- oldExtraDockNames.removeAt(i);
- }
- }
- return action;
- }
- void OBSBasic::RepairOldExtraDockName()
- {
- QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
- int idx = oldExtraDocks.indexOf(dock);
- QSignalBlocker block(dock);
- if (idx == -1) {
- blog(LOG_WARNING, "A dock got its object name changed");
- return;
- }
- blog(LOG_WARNING, "The dock '%s' got its object name restored", QT_TO_UTF8(oldExtraDockNames[idx]));
- dock->setObjectName(oldExtraDockNames[idx]);
- }
- void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area, bool extraBrowser)
- {
- if (dock->objectName().isEmpty())
- return;
- bool lock = ui->lockDocks->isChecked();
- QDockWidget::DockWidgetFeatures features =
- lock ? QDockWidget::NoDockWidgetFeatures
- : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
- QDockWidget::DockWidgetFloatable);
- setupDockAction(dock);
- dock->setFeatures(features);
- addDockWidget(area, dock);
- #ifdef BROWSER_AVAILABLE
- if (extraBrowser && extraBrowserMenuDocksSeparator.isNull())
- extraBrowserMenuDocksSeparator = ui->menuDocks->addSeparator();
- if (!extraBrowser && !extraBrowserMenuDocksSeparator.isNull())
- ui->menuDocks->insertAction(extraBrowserMenuDocksSeparator, dock->toggleViewAction());
- else
- ui->menuDocks->addAction(dock->toggleViewAction());
- if (extraBrowser)
- return;
- #else
- UNUSED_PARAMETER(extraBrowser);
- ui->menuDocks->addAction(dock->toggleViewAction());
- #endif
- extraDockNames.push_back(dock->objectName());
- extraDocks.push_back(std::shared_ptr<QDockWidget>(dock));
- }
- void OBSBasic::RemoveDockWidget(const QString &name)
- {
- if (extraDockNames.contains(name)) {
- int idx = extraDockNames.indexOf(name);
- extraDockNames.removeAt(idx);
- extraDocks[idx].reset();
- extraDocks.removeAt(idx);
- } else if (extraCustomDockNames.contains(name)) {
- int idx = extraCustomDockNames.indexOf(name);
- extraCustomDockNames.removeAt(idx);
- removeDockWidget(extraCustomDocks[idx]);
- extraCustomDocks.removeAt(idx);
- }
- }
- bool OBSBasic::IsDockObjectNameUsed(const QString &name)
- {
- QStringList list;
- list << "scenesDock"
- << "sourcesDock"
- << "mixerDock"
- << "transitionsDock"
- << "controlsDock"
- << "statsDock";
- list << oldExtraDockNames;
- list << extraDockNames;
- list << extraCustomDockNames;
- return list.contains(name);
- }
- void OBSBasic::AddCustomDockWidget(QDockWidget *dock)
- {
- // Prevent the object name from being changed
- connect(dock, &QObject::objectNameChanged, this, &OBSBasic::RepairCustomExtraDockName);
- bool lock = ui->lockDocks->isChecked();
- QDockWidget::DockWidgetFeatures features =
- lock ? QDockWidget::NoDockWidgetFeatures
- : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
- QDockWidget::DockWidgetFloatable);
- dock->setFeatures(features);
- addDockWidget(Qt::RightDockWidgetArea, dock);
- extraCustomDockNames.push_back(dock->objectName());
- extraCustomDocks.push_back(dock);
- }
- void OBSBasic::RepairCustomExtraDockName()
- {
- QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
- int idx = extraCustomDocks.indexOf(dock);
- QSignalBlocker block(dock);
- if (idx == -1) {
- blog(LOG_WARNING, "A custom dock got its object name changed");
- return;
- }
- blog(LOG_WARNING, "The custom dock '%s' got its object name restored", QT_TO_UTF8(extraCustomDockNames[idx]));
- dock->setObjectName(extraCustomDockNames[idx]);
- }
|