1
0

OBSBasic_Docks.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /******************************************************************************
  2. Copyright (C) 2023 by Lain Bailey <[email protected]>
  3. Zachary Lund <[email protected]>
  4. Philippe Groarke <[email protected]>
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ******************************************************************************/
  16. #include "OBSBasic.hpp"
  17. #include <qt-wrappers.hpp>
  18. void setupDockAction(QDockWidget *dock)
  19. {
  20. QAction *action = dock->toggleViewAction();
  21. auto neverDisable = [action]() {
  22. QSignalBlocker block(action);
  23. action->setEnabled(true);
  24. };
  25. auto newToggleView = [dock](bool check) {
  26. QSignalBlocker block(dock);
  27. dock->setVisible(check);
  28. };
  29. // Replace the slot connected by default
  30. QObject::disconnect(action, &QAction::triggered, nullptr, 0);
  31. QObject::connect(action, &QAction::triggered, dock, newToggleView);
  32. // Make the action unable to be disabled
  33. QObject::connect(action, &QAction::enabledChanged, action, neverDisable);
  34. }
  35. void OBSBasic::on_resetDocks_triggered(bool force)
  36. {
  37. #ifdef BROWSER_AVAILABLE
  38. if ((extraDocks.size() || extraCustomDocks.size() || extraBrowserDocks.size()) && !force)
  39. #else
  40. if ((extraDocks.size() || extraCustomDocks.size()) && !force)
  41. #endif
  42. {
  43. QMessageBox::StandardButton button =
  44. OBSMessageBox::question(this, QTStr("ResetUIWarning.Title"), QTStr("ResetUIWarning.Text"));
  45. if (button == QMessageBox::No)
  46. return;
  47. }
  48. #define RESET_DOCKLIST(dockList) \
  49. for (int i = dockList.size() - 1; i >= 0; i--) { \
  50. dockList[i]->setVisible(true); \
  51. dockList[i]->setFloating(true); \
  52. dockList[i]->move(frameGeometry().topLeft() + rect().center() - dockList[i]->rect().center()); \
  53. dockList[i]->setVisible(false); \
  54. }
  55. RESET_DOCKLIST(extraDocks)
  56. RESET_DOCKLIST(extraCustomDocks)
  57. #ifdef BROWSER_AVAILABLE
  58. RESET_DOCKLIST(extraBrowserDocks)
  59. #endif
  60. #undef RESET_DOCKLIST
  61. restoreState(startingDockLayout);
  62. ui->sideDocks->setChecked(true);
  63. int cx = width();
  64. int bottomDocksHeight = height();
  65. bottomDocksHeight = bottomDocksHeight * 225 / 1000;
  66. ui->scenesDock->setVisible(true);
  67. ui->sourcesDock->setVisible(true);
  68. ui->mixerDock->setVisible(true);
  69. ui->transitionsDock->setVisible(true);
  70. controlsDock->setVisible(true);
  71. statsDock->setVisible(false);
  72. statsDock->setFloating(true);
  73. QList<QDockWidget *> bottomDocks{ui->mixerDock, ui->transitionsDock, controlsDock};
  74. resizeDocks(bottomDocks, {bottomDocksHeight, bottomDocksHeight, bottomDocksHeight}, Qt::Vertical);
  75. resizeDocks(bottomDocks, {cx * 45 / 100, cx * 14 / 100, cx * 16 / 100}, Qt::Horizontal);
  76. int sideDockWidth = std::min(width() * 30 / 100, 280);
  77. resizeDocks({ui->scenesDock, ui->sourcesDock}, {sideDockWidth, sideDockWidth}, Qt::Horizontal);
  78. activateWindow();
  79. }
  80. void OBSBasic::on_lockDocks_toggled(bool lock)
  81. {
  82. QDockWidget::DockWidgetFeatures features =
  83. lock ? QDockWidget::NoDockWidgetFeatures
  84. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  85. QDockWidget::DockWidgetFloatable);
  86. QDockWidget::DockWidgetFeatures mainFeatures = features;
  87. mainFeatures &= ~QDockWidget::QDockWidget::DockWidgetClosable;
  88. ui->scenesDock->setFeatures(mainFeatures);
  89. ui->sourcesDock->setFeatures(mainFeatures);
  90. ui->mixerDock->setFeatures(mainFeatures);
  91. ui->transitionsDock->setFeatures(mainFeatures);
  92. controlsDock->setFeatures(mainFeatures);
  93. statsDock->setFeatures(features);
  94. for (int i = extraDocks.size() - 1; i >= 0; i--)
  95. extraDocks[i]->setFeatures(features);
  96. for (int i = extraCustomDocks.size() - 1; i >= 0; i--)
  97. extraCustomDocks[i]->setFeatures(features);
  98. #ifdef BROWSER_AVAILABLE
  99. for (int i = extraBrowserDocks.size() - 1; i >= 0; i--)
  100. extraBrowserDocks[i]->setFeatures(features);
  101. #endif
  102. }
  103. void OBSBasic::on_sideDocks_toggled(bool side)
  104. {
  105. config_set_bool(App()->GetUserConfig(), "BasicWindow", "SideDocks", side);
  106. setDockCornersVertical(side);
  107. }
  108. void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area, bool extraBrowser)
  109. {
  110. if (dock->objectName().isEmpty())
  111. return;
  112. bool lock = ui->lockDocks->isChecked();
  113. QDockWidget::DockWidgetFeatures features =
  114. lock ? QDockWidget::NoDockWidgetFeatures
  115. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  116. QDockWidget::DockWidgetFloatable);
  117. setupDockAction(dock);
  118. dock->setFeatures(features);
  119. addDockWidget(area, dock);
  120. #ifdef BROWSER_AVAILABLE
  121. if (extraBrowser && extraBrowserMenuDocksSeparator.isNull())
  122. extraBrowserMenuDocksSeparator = ui->menuDocks->addSeparator();
  123. if (!extraBrowser && !extraBrowserMenuDocksSeparator.isNull())
  124. ui->menuDocks->insertAction(extraBrowserMenuDocksSeparator, dock->toggleViewAction());
  125. else
  126. ui->menuDocks->addAction(dock->toggleViewAction());
  127. if (extraBrowser)
  128. return;
  129. #else
  130. UNUSED_PARAMETER(extraBrowser);
  131. ui->menuDocks->addAction(dock->toggleViewAction());
  132. #endif
  133. extraDockNames.push_back(dock->objectName());
  134. extraDocks.push_back(std::shared_ptr<QDockWidget>(dock));
  135. }
  136. void OBSBasic::RemoveDockWidget(const QString &name)
  137. {
  138. if (extraDockNames.contains(name)) {
  139. int idx = extraDockNames.indexOf(name);
  140. extraDockNames.removeAt(idx);
  141. extraDocks[idx].reset();
  142. extraDocks.removeAt(idx);
  143. } else if (extraCustomDockNames.contains(name)) {
  144. int idx = extraCustomDockNames.indexOf(name);
  145. extraCustomDockNames.removeAt(idx);
  146. removeDockWidget(extraCustomDocks[idx]);
  147. extraCustomDocks.removeAt(idx);
  148. }
  149. }
  150. bool OBSBasic::IsDockObjectNameUsed(const QString &name)
  151. {
  152. QStringList list;
  153. list << "scenesDock"
  154. << "sourcesDock"
  155. << "mixerDock"
  156. << "transitionsDock"
  157. << "controlsDock"
  158. << "statsDock";
  159. list << extraDockNames;
  160. list << extraCustomDockNames;
  161. return list.contains(name);
  162. }
  163. void OBSBasic::AddCustomDockWidget(QDockWidget *dock)
  164. {
  165. // Prevent the object name from being changed
  166. connect(dock, &QObject::objectNameChanged, this, &OBSBasic::RepairCustomExtraDockName);
  167. bool lock = ui->lockDocks->isChecked();
  168. QDockWidget::DockWidgetFeatures features =
  169. lock ? QDockWidget::NoDockWidgetFeatures
  170. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  171. QDockWidget::DockWidgetFloatable);
  172. dock->setFeatures(features);
  173. addDockWidget(Qt::RightDockWidgetArea, dock);
  174. extraCustomDockNames.push_back(dock->objectName());
  175. extraCustomDocks.push_back(dock);
  176. }
  177. void OBSBasic::setDockCornersVertical(bool vertical)
  178. {
  179. if (vertical) {
  180. setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
  181. setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
  182. setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  183. setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
  184. } else {
  185. setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
  186. setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
  187. setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
  188. setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
  189. }
  190. }
  191. void OBSBasic::RepairCustomExtraDockName()
  192. {
  193. QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
  194. int idx = extraCustomDocks.indexOf(dock);
  195. QSignalBlocker block(dock);
  196. if (idx == -1) {
  197. blog(LOG_WARNING, "A custom dock got its object name changed");
  198. return;
  199. }
  200. blog(LOG_WARNING, "The custom dock '%s' got its object name restored", QT_TO_UTF8(extraCustomDockNames[idx]));
  201. dock->setObjectName(extraCustomDockNames[idx]);
  202. }