SourceSelectButton.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /******************************************************************************
  2. Copyright (C) 2025 by Taylor Giampaolo <[email protected]>
  3. Lain Bailey <[email protected]>
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. ******************************************************************************/
  15. #include "SourceSelectButton.hpp"
  16. #include <utility/ThumbnailManager.hpp>
  17. #include <widgets/OBSBasic.hpp>
  18. #include <QDrag>
  19. #include <QFrame>
  20. #include <QMimeData>
  21. #include <QPainter>
  22. #include <QStyleOptionButton>
  23. SourceSelectButton::SourceSelectButton(obs_source_t *source_, QWidget *parent) : QFrame(parent)
  24. {
  25. OBSSource source = source_;
  26. weakSource = OBSGetWeakRef(source);
  27. const char *sourceName = obs_source_get_name(source);
  28. setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
  29. button = new QPushButton(this);
  30. button->setCheckable(true);
  31. button->setAttribute(Qt::WA_Moved);
  32. button->setAccessibleName(sourceName);
  33. button->show();
  34. layout = new QVBoxLayout();
  35. layout->setContentsMargins(0, 0, 0, 0);
  36. layout->setSpacing(0);
  37. setLayout(layout);
  38. label = new QLabel(sourceName);
  39. label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
  40. label->setAttribute(Qt::WA_TransparentForMouseEvents);
  41. label->setObjectName("name");
  42. image = new QLabel(this);
  43. image->setObjectName("thumbnail");
  44. image->setAttribute(Qt::WA_TransparentForMouseEvents);
  45. image->setMinimumSize(160, 90);
  46. image->setMaximumSize(160, 90);
  47. image->setAlignment(Qt::AlignCenter);
  48. std::optional<QPixmap> cachedThumbnail = OBSBasic::Get()->thumbnails()->getCachedThumbnail(source);
  49. if (cachedThumbnail.has_value()) {
  50. thumbnailUpdated(*cachedThumbnail);
  51. } else {
  52. setDefaultThumbnail();
  53. }
  54. layout->addWidget(image);
  55. layout->addWidget(label);
  56. button->setFixedSize(width(), height());
  57. button->move(0, 0);
  58. setFocusPolicy(Qt::StrongFocus);
  59. setFocusProxy(button);
  60. connect(button, &QAbstractButton::pressed, this, &SourceSelectButton::buttonPressed);
  61. }
  62. SourceSelectButton::~SourceSelectButton() {}
  63. QPointer<QPushButton> SourceSelectButton::getButton()
  64. {
  65. return button;
  66. }
  67. QString SourceSelectButton::text()
  68. {
  69. return label->text();
  70. }
  71. void SourceSelectButton::resizeEvent(QResizeEvent *)
  72. {
  73. button->setFixedSize(width(), height());
  74. button->move(0, 0);
  75. }
  76. void SourceSelectButton::moveEvent(QMoveEvent *)
  77. {
  78. button->setFixedSize(width(), height());
  79. button->move(0, 0);
  80. }
  81. void SourceSelectButton::buttonPressed()
  82. {
  83. dragStartPosition = QCursor::pos();
  84. }
  85. void SourceSelectButton::setDefaultThumbnail()
  86. {
  87. OBSSource source = OBSGetStrongRef(weakSource);
  88. if (source) {
  89. const char *id = obs_source_get_id(source);
  90. QIcon icon = OBSBasic::Get()->GetSourceIcon(id);
  91. image->setPixmap(icon.pixmap(45, 45));
  92. }
  93. }
  94. void SourceSelectButton::mouseMoveEvent(QMouseEvent *event)
  95. {
  96. if (!(event->buttons() & Qt::LeftButton)) {
  97. return;
  98. }
  99. if ((event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance()) {
  100. return;
  101. }
  102. QMimeData *mimeData = new QMimeData;
  103. OBSSource source = OBSGetStrongRef(weakSource);
  104. if (source) {
  105. std::string uuid = obs_source_get_uuid(source);
  106. mimeData->setData("application/x-obs-source-uuid", uuid.c_str());
  107. QDrag *drag = new QDrag(this);
  108. drag->setMimeData(mimeData);
  109. drag->setPixmap(this->grab());
  110. drag->exec(Qt::CopyAction);
  111. }
  112. }
  113. void SourceSelectButton::setRectVisible(bool visible)
  114. {
  115. OBSSource source = OBSGetStrongRef(weakSource);
  116. if (!source) {
  117. return;
  118. }
  119. if (rectVisible != visible) {
  120. rectVisible = visible;
  121. if (visible) {
  122. uint32_t flags = obs_source_get_output_flags(source);
  123. bool hasVideo = (flags & OBS_SOURCE_VIDEO) == OBS_SOURCE_VIDEO;
  124. if (hasVideo) {
  125. thumbnail = OBSBasic::Get()->thumbnails()->getThumbnail(source);
  126. connect(thumbnail.get(), &Thumbnail::updateThumbnail, this,
  127. &SourceSelectButton::thumbnailUpdated);
  128. thumbnailUpdated(thumbnail->getPixmap());
  129. }
  130. } else {
  131. thumbnail.reset();
  132. }
  133. }
  134. if (preload && !rectVisible) {
  135. OBSBasic::Get()->thumbnails()->preloadThumbnail(source, this,
  136. [=](QPixmap pixmap) { thumbnailUpdated(pixmap); });
  137. }
  138. preload = false;
  139. }
  140. void SourceSelectButton::setPreload(bool preload)
  141. {
  142. this->preload = preload;
  143. }
  144. void SourceSelectButton::thumbnailUpdated(QPixmap pixmap)
  145. {
  146. if (!pixmap.isNull()) {
  147. image->setPixmap(pixmap.scaled(160, 90, Qt::KeepAspectRatio, Qt::SmoothTransformation));
  148. } else {
  149. setDefaultThumbnail();
  150. }
  151. }