| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 | 
							- /******************************************************************************
 
-     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);
 
- 	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]);
 
- }
 
 
  |