visibility-item-widget.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "visibility-item-widget.hpp"
  2. #include "visibility-checkbox.hpp"
  3. #include "locked-checkbox.hpp"
  4. #include "qt-wrappers.hpp"
  5. #include "obs-app.hpp"
  6. #include <QListWidget>
  7. #include <QLineEdit>
  8. #include <QHBoxLayout>
  9. #include <QMessageBox>
  10. #include <QLabel>
  11. VisibilityItemWidget::VisibilityItemWidget(obs_source_t *source_)
  12. : source (source_),
  13. enabledSignal (obs_source_get_signal_handler(source), "enable",
  14. OBSSourceEnabled, this),
  15. renamedSignal (obs_source_get_signal_handler(source), "rename",
  16. OBSSourceRenamed, this)
  17. {
  18. const char *name = obs_source_get_name(source);
  19. bool enabled = obs_source_enabled(source);
  20. vis = new VisibilityCheckBox();
  21. vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
  22. /* Fix for non-apple systems where the spacing would be too big */
  23. #ifndef __APPLE__
  24. vis->setMaximumSize(16, 16);
  25. #endif
  26. vis->setChecked(enabled);
  27. label = new QLabel(QT_UTF8(name));
  28. label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  29. QHBoxLayout *itemLayout = new QHBoxLayout();
  30. itemLayout->addWidget(vis);
  31. itemLayout->addWidget(label);
  32. itemLayout->setContentsMargins(5, 2, 5, 2);
  33. setLayout(itemLayout);
  34. setStyleSheet("background-color: rgba(255, 255, 255, 0);");
  35. connect(vis, SIGNAL(clicked(bool)),
  36. this, SLOT(VisibilityClicked(bool)));
  37. }
  38. VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
  39. : item (item_),
  40. source (obs_sceneitem_get_source(item)),
  41. renamedSignal (obs_source_get_signal_handler(source), "rename",
  42. OBSSourceRenamed, this)
  43. {
  44. const char *name = obs_source_get_name(source);
  45. bool enabled = obs_sceneitem_visible(item);
  46. bool locked = obs_sceneitem_locked(item);
  47. obs_scene_t *scene = obs_sceneitem_get_scene(item);
  48. obs_source_t *sceneSource = obs_scene_get_source(scene);
  49. vis = new VisibilityCheckBox();
  50. vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
  51. /* Fix for non-apple systems where the spacing would be too big */
  52. #ifndef __APPLE__
  53. vis->setMaximumSize(16, 16);
  54. #endif
  55. vis->setChecked(enabled);
  56. lock = new LockedCheckBox();
  57. lock->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
  58. /* Fix for non-apple systems where the spacing would be too big */
  59. #ifndef __APPLE__
  60. lock->setMaximumSize(16, 16);
  61. #endif
  62. lock->setChecked(locked);
  63. label = new QLabel(QT_UTF8(name));
  64. label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  65. #ifdef __APPLE__
  66. vis->setAttribute(Qt::WA_LayoutUsesWidgetRect);
  67. lock->setAttribute(Qt::WA_LayoutUsesWidgetRect);
  68. #endif
  69. QHBoxLayout *itemLayout = new QHBoxLayout();
  70. itemLayout->addWidget(vis);
  71. itemLayout->addWidget(lock);
  72. itemLayout->addWidget(label);
  73. itemLayout->setContentsMargins(5, 2, 5, 2);
  74. itemLayout->setSpacing(2);
  75. setLayout(itemLayout);
  76. setStyleSheet("background-color: rgba(255, 255, 255, 0);");
  77. signal_handler_t *signal = obs_source_get_signal_handler(sceneSource);
  78. signal_handler_connect(signal, "remove", OBSSceneRemove, this);
  79. signal_handler_connect(signal, "item_remove", OBSSceneItemRemove,
  80. this);
  81. signal_handler_connect(signal, "item_visible", OBSSceneItemVisible,
  82. this);
  83. signal_handler_connect(signal, "item_locked", OBSSceneItemLocked,
  84. this);
  85. connect(vis, SIGNAL(clicked(bool)),
  86. this, SLOT(VisibilityClicked(bool)));
  87. connect(lock, SIGNAL(clicked(bool)),
  88. this, SLOT(LockClicked(bool)));
  89. }
  90. VisibilityItemWidget::~VisibilityItemWidget()
  91. {
  92. DisconnectItemSignals();
  93. }
  94. void VisibilityItemWidget::DisconnectItemSignals()
  95. {
  96. if (!item || sceneRemoved)
  97. return;
  98. obs_scene_t *scene = obs_sceneitem_get_scene(item);
  99. obs_source_t *sceneSource = obs_scene_get_source(scene);
  100. signal_handler_t *signal = obs_source_get_signal_handler(sceneSource);
  101. signal_handler_disconnect(signal, "remove", OBSSceneRemove, this);
  102. signal_handler_disconnect(signal, "item_remove", OBSSceneItemRemove,
  103. this);
  104. signal_handler_disconnect(signal, "item_visible", OBSSceneItemVisible,
  105. this);
  106. signal_handler_disconnect(signal, "item_locked", OBSSceneItemLocked,
  107. this);
  108. sceneRemoved = true;
  109. }
  110. void VisibilityItemWidget::OBSSceneRemove(void *param, calldata_t *data)
  111. {
  112. VisibilityItemWidget *window =
  113. reinterpret_cast<VisibilityItemWidget*>(param);
  114. window->DisconnectItemSignals();
  115. UNUSED_PARAMETER(data);
  116. }
  117. void VisibilityItemWidget::OBSSceneItemRemove(void *param, calldata_t *data)
  118. {
  119. VisibilityItemWidget *window =
  120. reinterpret_cast<VisibilityItemWidget*>(param);
  121. obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(data, "item");
  122. if (item == window->item)
  123. window->DisconnectItemSignals();
  124. }
  125. void VisibilityItemWidget::OBSSceneItemVisible(void *param, calldata_t *data)
  126. {
  127. VisibilityItemWidget *window =
  128. reinterpret_cast<VisibilityItemWidget*>(param);
  129. obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
  130. bool enabled = calldata_bool(data, "visible");
  131. if (window->item == curItem)
  132. QMetaObject::invokeMethod(window, "SourceEnabled",
  133. Q_ARG(bool, enabled));
  134. }
  135. void VisibilityItemWidget::OBSSceneItemLocked(void *param, calldata_t *data)
  136. {
  137. VisibilityItemWidget *window =
  138. reinterpret_cast<VisibilityItemWidget*>(param);
  139. obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
  140. bool locked = calldata_bool(data, "locked");
  141. if (window->item == curItem)
  142. QMetaObject::invokeMethod(window, "SourceLocked",
  143. Q_ARG(bool, locked));
  144. }
  145. void VisibilityItemWidget::OBSSourceEnabled(void *param, calldata_t *data)
  146. {
  147. VisibilityItemWidget *window =
  148. reinterpret_cast<VisibilityItemWidget*>(param);
  149. bool enabled = calldata_bool(data, "enabled");
  150. QMetaObject::invokeMethod(window, "SourceEnabled",
  151. Q_ARG(bool, enabled));
  152. }
  153. void VisibilityItemWidget::OBSSourceRenamed(void *param, calldata_t *data)
  154. {
  155. VisibilityItemWidget *window =
  156. reinterpret_cast<VisibilityItemWidget*>(param);
  157. const char *name = calldata_string(data, "new_name");
  158. QMetaObject::invokeMethod(window, "SourceRenamed",
  159. Q_ARG(QString, QT_UTF8(name)));
  160. }
  161. void VisibilityItemWidget::VisibilityClicked(bool visible)
  162. {
  163. if (item)
  164. obs_sceneitem_set_visible(item, visible);
  165. else
  166. obs_source_set_enabled(source, visible);
  167. }
  168. void VisibilityItemWidget::LockClicked(bool locked)
  169. {
  170. if (item)
  171. obs_sceneitem_set_locked(item, locked);
  172. }
  173. void VisibilityItemWidget::SourceEnabled(bool enabled)
  174. {
  175. if (vis->isChecked() != enabled)
  176. vis->setChecked(enabled);
  177. }
  178. void VisibilityItemWidget::SourceLocked(bool locked)
  179. {
  180. if (lock->isChecked() != locked)
  181. lock->setChecked(locked);
  182. }
  183. void VisibilityItemWidget::SourceRenamed(QString name)
  184. {
  185. if (label && name != label->text())
  186. label->setText(name);
  187. }
  188. void VisibilityItemWidget::SetColor(const QColor &color,
  189. bool active_, bool selected_)
  190. {
  191. /* Do not update unless the state has actually changed */
  192. if (active_ == active && selected_ == selected)
  193. return;
  194. QPalette pal = vis->palette();
  195. pal.setColor(QPalette::WindowText, color);
  196. vis->setPalette(pal);
  197. label->setStyleSheet(QString("color: %1;").arg(color.name()));
  198. active = active_;
  199. selected = selected_;
  200. }
  201. VisibilityItemDelegate::VisibilityItemDelegate(QObject *parent)
  202. : QStyledItemDelegate(parent)
  203. {
  204. }
  205. void VisibilityItemDelegate::paint(QPainter *painter,
  206. const QStyleOptionViewItem &option,
  207. const QModelIndex &index) const
  208. {
  209. QStyledItemDelegate::paint(painter, option, index);
  210. QObject *parentObj = parent();
  211. QListWidget *list = qobject_cast<QListWidget*>(parentObj);
  212. if (!list)
  213. return;
  214. QListWidgetItem *item = list->item(index.row());
  215. VisibilityItemWidget *widget =
  216. qobject_cast<VisibilityItemWidget*>(list->itemWidget(item));
  217. if (!widget)
  218. return;
  219. bool selected = option.state.testFlag(QStyle::State_Selected);
  220. bool active = option.state.testFlag(QStyle::State_Active);
  221. QPalette palette = list->palette();
  222. #if defined(_WIN32) || defined(__APPLE__)
  223. QPalette::ColorGroup group = active ?
  224. QPalette::Active : QPalette::Inactive;
  225. #else
  226. QPalette::ColorGroup group = QPalette::Active;
  227. #endif
  228. #ifdef _WIN32
  229. QPalette::ColorRole highlightRole = QPalette::WindowText;
  230. #else
  231. QPalette::ColorRole highlightRole = QPalette::HighlightedText;
  232. #endif
  233. QPalette::ColorRole role;
  234. if (selected && active)
  235. role = highlightRole;
  236. else
  237. role = QPalette::WindowText;
  238. widget->SetColor(palette.color(group, role), active, selected);
  239. }
  240. void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
  241. obs_source_t *source)
  242. {
  243. VisibilityItemWidget *baseWidget = new VisibilityItemWidget(source);
  244. item->setSizeHint(baseWidget->sizeHint());
  245. list->setItemWidget(item, baseWidget);
  246. }
  247. void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
  248. obs_sceneitem_t *sceneItem)
  249. {
  250. VisibilityItemWidget *baseWidget = new VisibilityItemWidget(sceneItem);
  251. item->setSizeHint(baseWidget->sizeHint());
  252. list->setItemWidget(item, baseWidget);
  253. }