1
0

OBSBasic_Docks.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. dock->connect(action, &QAction::triggered, newToggleView);
  32. // Make the action unable to be disabled
  33. action->connect(action, &QAction::enabledChanged, 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. int cx = width();
  63. int cy = height();
  64. int cx22_5 = cx * 225 / 1000;
  65. int cx5 = cx * 5 / 100;
  66. int cx21 = cx * 21 / 100;
  67. cy = cy * 225 / 1000;
  68. int mixerSize = cx - (cx22_5 * 2 + cx5 + cx21);
  69. QList<QDockWidget *> docks{ui->scenesDock, ui->sourcesDock, ui->mixerDock, ui->transitionsDock, controlsDock};
  70. QList<int> sizes{cx22_5, cx22_5, mixerSize, cx5, cx21};
  71. ui->scenesDock->setVisible(true);
  72. ui->sourcesDock->setVisible(true);
  73. ui->mixerDock->setVisible(true);
  74. ui->transitionsDock->setVisible(true);
  75. controlsDock->setVisible(true);
  76. statsDock->setVisible(false);
  77. statsDock->setFloating(true);
  78. resizeDocks(docks, {cy, cy, cy, cy, cy}, Qt::Vertical);
  79. resizeDocks(docks, sizes, Qt::Horizontal);
  80. activateWindow();
  81. }
  82. void OBSBasic::on_lockDocks_toggled(bool lock)
  83. {
  84. QDockWidget::DockWidgetFeatures features =
  85. lock ? QDockWidget::NoDockWidgetFeatures
  86. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  87. QDockWidget::DockWidgetFloatable);
  88. QDockWidget::DockWidgetFeatures mainFeatures = features;
  89. mainFeatures &= ~QDockWidget::QDockWidget::DockWidgetClosable;
  90. ui->scenesDock->setFeatures(mainFeatures);
  91. ui->sourcesDock->setFeatures(mainFeatures);
  92. ui->mixerDock->setFeatures(mainFeatures);
  93. ui->transitionsDock->setFeatures(mainFeatures);
  94. controlsDock->setFeatures(mainFeatures);
  95. statsDock->setFeatures(features);
  96. for (int i = extraDocks.size() - 1; i >= 0; i--)
  97. extraDocks[i]->setFeatures(features);
  98. for (int i = extraCustomDocks.size() - 1; i >= 0; i--)
  99. extraCustomDocks[i]->setFeatures(features);
  100. #ifdef BROWSER_AVAILABLE
  101. for (int i = extraBrowserDocks.size() - 1; i >= 0; i--)
  102. extraBrowserDocks[i]->setFeatures(features);
  103. #endif
  104. }
  105. void OBSBasic::on_sideDocks_toggled(bool side)
  106. {
  107. if (side) {
  108. setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
  109. setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
  110. setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
  111. setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
  112. } else {
  113. setCorner(Qt::TopLeftCorner, Qt::TopDockWidgetArea);
  114. setCorner(Qt::TopRightCorner, Qt::TopDockWidgetArea);
  115. setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
  116. setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
  117. }
  118. }
  119. void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area, bool extraBrowser)
  120. {
  121. if (dock->objectName().isEmpty())
  122. return;
  123. bool lock = ui->lockDocks->isChecked();
  124. QDockWidget::DockWidgetFeatures features =
  125. lock ? QDockWidget::NoDockWidgetFeatures
  126. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  127. QDockWidget::DockWidgetFloatable);
  128. setupDockAction(dock);
  129. dock->setFeatures(features);
  130. addDockWidget(area, dock);
  131. #ifdef BROWSER_AVAILABLE
  132. if (extraBrowser && extraBrowserMenuDocksSeparator.isNull())
  133. extraBrowserMenuDocksSeparator = ui->menuDocks->addSeparator();
  134. if (!extraBrowser && !extraBrowserMenuDocksSeparator.isNull())
  135. ui->menuDocks->insertAction(extraBrowserMenuDocksSeparator, dock->toggleViewAction());
  136. else
  137. ui->menuDocks->addAction(dock->toggleViewAction());
  138. if (extraBrowser)
  139. return;
  140. #else
  141. UNUSED_PARAMETER(extraBrowser);
  142. ui->menuDocks->addAction(dock->toggleViewAction());
  143. #endif
  144. extraDockNames.push_back(dock->objectName());
  145. extraDocks.push_back(std::shared_ptr<QDockWidget>(dock));
  146. }
  147. void OBSBasic::RemoveDockWidget(const QString &name)
  148. {
  149. if (extraDockNames.contains(name)) {
  150. int idx = extraDockNames.indexOf(name);
  151. extraDockNames.removeAt(idx);
  152. extraDocks[idx].reset();
  153. extraDocks.removeAt(idx);
  154. } else if (extraCustomDockNames.contains(name)) {
  155. int idx = extraCustomDockNames.indexOf(name);
  156. extraCustomDockNames.removeAt(idx);
  157. removeDockWidget(extraCustomDocks[idx]);
  158. extraCustomDocks.removeAt(idx);
  159. }
  160. }
  161. bool OBSBasic::IsDockObjectNameUsed(const QString &name)
  162. {
  163. QStringList list;
  164. list << "scenesDock"
  165. << "sourcesDock"
  166. << "mixerDock"
  167. << "transitionsDock"
  168. << "controlsDock"
  169. << "statsDock";
  170. list << extraDockNames;
  171. list << extraCustomDockNames;
  172. return list.contains(name);
  173. }
  174. void OBSBasic::AddCustomDockWidget(QDockWidget *dock)
  175. {
  176. // Prevent the object name from being changed
  177. connect(dock, &QObject::objectNameChanged, this, &OBSBasic::RepairCustomExtraDockName);
  178. bool lock = ui->lockDocks->isChecked();
  179. QDockWidget::DockWidgetFeatures features =
  180. lock ? QDockWidget::NoDockWidgetFeatures
  181. : (QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable |
  182. QDockWidget::DockWidgetFloatable);
  183. dock->setFeatures(features);
  184. addDockWidget(Qt::RightDockWidgetArea, dock);
  185. extraCustomDockNames.push_back(dock->objectName());
  186. extraCustomDocks.push_back(dock);
  187. }
  188. void OBSBasic::RepairCustomExtraDockName()
  189. {
  190. QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
  191. int idx = extraCustomDocks.indexOf(dock);
  192. QSignalBlocker block(dock);
  193. if (idx == -1) {
  194. blog(LOG_WARNING, "A custom dock got its object name changed");
  195. return;
  196. }
  197. blog(LOG_WARNING, "The custom dock '%s' got its object name restored", QT_TO_UTF8(extraCustomDockNames[idx]));
  198. dock->setObjectName(extraCustomDockNames[idx]);
  199. }