RemuxEntryPathItemDelegate.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /******************************************************************************
  2. Copyright (C) 2014 by Ruwen Hahn <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "RemuxEntryPathItemDelegate.hpp"
  15. #include "RemuxQueueModel.hpp"
  16. #include <OBSApp.hpp>
  17. #include <qt-wrappers.hpp>
  18. #include <QHBoxLayout>
  19. #include <QLineEdit>
  20. #include <QToolButton>
  21. #include "moc_RemuxEntryPathItemDelegate.cpp"
  22. RemuxEntryPathItemDelegate::RemuxEntryPathItemDelegate(bool isOutput, const QString &defaultPath)
  23. : QStyledItemDelegate(),
  24. isOutput(isOutput),
  25. defaultPath(defaultPath)
  26. {
  27. }
  28. QWidget *RemuxEntryPathItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */,
  29. const QModelIndex &index) const
  30. {
  31. RemuxEntryState state = index.model()
  32. ->index(index.row(), RemuxEntryColumn::State)
  33. .data(RemuxEntryRole::EntryStateRole)
  34. .value<RemuxEntryState>();
  35. if (state == RemuxEntryState::Pending || state == RemuxEntryState::InProgress) {
  36. // Never allow modification of rows that are
  37. // in progress.
  38. return Q_NULLPTR;
  39. } else if (isOutput && state != RemuxEntryState::Ready) {
  40. // Do not allow modification of output rows
  41. // that aren't associated with a valid input.
  42. return Q_NULLPTR;
  43. } else if (!isOutput && state == RemuxEntryState::Complete) {
  44. // Don't allow modification of rows that are
  45. // already complete.
  46. return Q_NULLPTR;
  47. } else {
  48. QSizePolicy buttonSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Expanding,
  49. QSizePolicy::ControlType::PushButton);
  50. QWidget *container = new QWidget(parent);
  51. auto browseCallback = [this, container]() {
  52. const_cast<RemuxEntryPathItemDelegate *>(this)->handleBrowse(container);
  53. };
  54. auto clearCallback = [this, container]() {
  55. const_cast<RemuxEntryPathItemDelegate *>(this)->handleClear(container);
  56. };
  57. QHBoxLayout *layout = new QHBoxLayout();
  58. layout->setContentsMargins(0, 0, 0, 0);
  59. layout->setSpacing(0);
  60. QLineEdit *text = new QLineEdit();
  61. text->setObjectName(QStringLiteral("text"));
  62. text->setSizePolicy(QSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding,
  63. QSizePolicy::ControlType::LineEdit));
  64. layout->addWidget(text);
  65. QObject::connect(text, &QLineEdit::editingFinished, this, &RemuxEntryPathItemDelegate::updateText);
  66. QToolButton *browseButton = new QToolButton();
  67. browseButton->setText("...");
  68. browseButton->setSizePolicy(buttonSizePolicy);
  69. layout->addWidget(browseButton);
  70. container->connect(browseButton, &QToolButton::clicked, browseCallback);
  71. // The "clear" button is not shown in output cells
  72. // or the insertion point's input cell.
  73. if (!isOutput && state != RemuxEntryState::Empty) {
  74. QToolButton *clearButton = new QToolButton();
  75. clearButton->setText("X");
  76. clearButton->setSizePolicy(buttonSizePolicy);
  77. layout->addWidget(clearButton);
  78. container->connect(clearButton, &QToolButton::clicked, clearCallback);
  79. }
  80. container->setLayout(layout);
  81. container->setFocusProxy(text);
  82. return container;
  83. }
  84. }
  85. void RemuxEntryPathItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
  86. {
  87. QLineEdit *text = editor->findChild<QLineEdit *>();
  88. text->setText(index.data().toString());
  89. editor->setProperty(PATH_LIST_PROP, QVariant());
  90. }
  91. void RemuxEntryPathItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
  92. const QModelIndex &index) const
  93. {
  94. // We use the PATH_LIST_PROP property to pass a list of
  95. // path strings from the editor widget into the model's
  96. // NewPathsToProcessRole. This is only used when paths
  97. // are selected through the "browse" or "delete" buttons
  98. // in the editor. If the user enters new text in the
  99. // text box, we simply pass that text on to the model
  100. // as normal text data in the default role.
  101. QVariant pathListProp = editor->property(PATH_LIST_PROP);
  102. if (pathListProp.isValid()) {
  103. QStringList list = editor->property(PATH_LIST_PROP).toStringList();
  104. if (isOutput) {
  105. if (list.size() > 0)
  106. model->setData(index, list);
  107. } else
  108. model->setData(index, list, RemuxEntryRole::NewPathsToProcessRole);
  109. } else {
  110. QLineEdit *lineEdit = editor->findChild<QLineEdit *>();
  111. model->setData(index, lineEdit->text());
  112. }
  113. }
  114. void RemuxEntryPathItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
  115. const QModelIndex &index) const
  116. {
  117. RemuxEntryState state = index.model()
  118. ->index(index.row(), RemuxEntryColumn::State)
  119. .data(RemuxEntryRole::EntryStateRole)
  120. .value<RemuxEntryState>();
  121. QStyleOptionViewItem localOption = option;
  122. initStyleOption(&localOption, index);
  123. if (isOutput) {
  124. if (state != Ready) {
  125. QColor background =
  126. localOption.palette.color(QPalette::ColorGroup::Disabled, QPalette::ColorRole::Window);
  127. localOption.backgroundBrush = QBrush(background);
  128. }
  129. }
  130. QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &localOption, painter);
  131. }
  132. void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
  133. {
  134. QString ExtensionPattern = "(*.mp4 *.flv *.mov *.mkv *.ts *.m3u8)";
  135. QLineEdit *text = container->findChild<QLineEdit *>();
  136. QString currentPath = text->text();
  137. if (currentPath.isEmpty())
  138. currentPath = defaultPath;
  139. bool isSet = false;
  140. if (isOutput) {
  141. QString newPath = SaveFile(container, QTStr("Remux.SelectTarget"), currentPath, ExtensionPattern);
  142. if (!newPath.isEmpty()) {
  143. container->setProperty(PATH_LIST_PROP, QStringList() << newPath);
  144. isSet = true;
  145. }
  146. } else {
  147. QStringList paths = OpenFiles(container, QTStr("Remux.SelectRecording"), currentPath,
  148. QTStr("Remux.OBSRecording") + QString(" ") + ExtensionPattern);
  149. if (!paths.empty()) {
  150. container->setProperty(PATH_LIST_PROP, paths);
  151. isSet = true;
  152. }
  153. #ifdef __APPLE__
  154. // TODO: Revisit when QTBUG-42661 is fixed
  155. container->window()->raise();
  156. #endif
  157. }
  158. if (isSet)
  159. emit commitData(container);
  160. }
  161. void RemuxEntryPathItemDelegate::handleClear(QWidget *container)
  162. {
  163. // An empty string list will indicate that the entry is being
  164. // blanked and should be deleted.
  165. container->setProperty(PATH_LIST_PROP, QStringList());
  166. emit commitData(container);
  167. }
  168. void RemuxEntryPathItemDelegate::updateText()
  169. {
  170. QLineEdit *lineEdit = dynamic_cast<QLineEdit *>(sender());
  171. QWidget *editor = lineEdit->parentWidget();
  172. emit commitData(editor);
  173. }