1 /*
2 SPDX-FileCopyrightText: 2019 Jean-Baptiste Mardelle
3 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
4 */
5
6 #include "buttonparamwidget.hpp"
7 #include "assets/model/assetparametermodel.hpp"
8 #include "jobs/filtertask.h"
9 #include "assets/model/assetcommand.hpp"
10 #include "core.h"
11 #include <mlt++/Mlt.h>
12
13 #include <KMessageWidget>
14 #include <QPushButton>
15 #include <QVBoxLayout>
16 #include <QProgressBar>
17
ButtonParamWidget(std::shared_ptr<AssetParameterModel> model,QModelIndex index,QWidget * parent)18 ButtonParamWidget::ButtonParamWidget(std::shared_ptr<AssetParameterModel> model, QModelIndex index, QWidget *parent)
19 : AbstractParamWidget(std::move(model), index, parent)
20 , m_label(nullptr)
21 {
22 // setup the comment
23 m_buttonName = m_model->data(m_index, Qt::DisplayRole).toString();
24 m_alternatebuttonName = m_model->data(m_index, AssetParameterModel::AlternateNameRole).toString();
25 //QString name = m_model->data(m_index, AssetParameterModel::NameRole).toString();
26 QString comment = m_model->data(m_index, AssetParameterModel::CommentRole).toString();
27 setToolTip(comment);
28 //setEnabled(m_model->getOwnerId().first != ObjectType::TimelineTrack);
29 auto *layout = new QVBoxLayout(this);
30 QVariantList filterData = m_model->data(m_index, AssetParameterModel::FilterJobParamsRole).toList();
31 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
32 QStringList filterAddedParams = m_model->data(m_index, AssetParameterModel::FilterParamsRole).toString().split(QLatin1Char(' '), QString::SkipEmptyParts);
33 #else
34 QStringList filterAddedParams = m_model->data(m_index, AssetParameterModel::FilterParamsRole).toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
35 #endif
36 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
37 QStringList consumerParams = m_model->data(m_index, AssetParameterModel::FilterConsumerParamsRole).toString().split(QLatin1Char(' '), QString::SkipEmptyParts);
38 #else
39 QStringList consumerParams = m_model->data(m_index, AssetParameterModel::FilterConsumerParamsRole).toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
40 #endif
41
42 QString conditionalInfo;
43 QString defaultValue;
44 for (const QVariant &jobElement : qAsConst(filterData)) {
45 QStringList d = jobElement.toStringList();
46 if (d.size() == 2) {
47 if (d.at(0) == QLatin1String("conditionalinfo")) {
48 conditionalInfo = d.at(1);
49 } else if (d.at(0) == QLatin1String("key")) {
50 m_keyParam = d.at(1);
51 } else if (d.at(0) == QLatin1String("keydefault")) {
52 defaultValue = d.at(1);
53 }
54 }
55 }
56 QVector<QPair<QString, QVariant>> filterParams = m_model->getAllParameters();
57 m_displayConditional = true;
58 for (const auto ¶m : qAsConst(filterParams)) {
59 if (param.first == m_keyParam) {
60 if (!param.second.toString().isEmpty() && param.second.toString().contains(QLatin1Char(';'))) {
61 m_displayConditional = false;
62 }
63 break;
64 }
65 }
66 if (!conditionalInfo.isEmpty()) {
67 m_label = new KMessageWidget(conditionalInfo, this);
68 m_label->setWordWrap(true);
69 layout->addWidget(m_label);
70 m_label->setVisible(m_displayConditional);
71 }
72 layout->setContentsMargins(0, 0, 0, 0);
73 layout->setSpacing(0);
74 m_button = new QPushButton(m_displayConditional ? m_buttonName : m_alternatebuttonName, this);
75 layout->addWidget(m_button);
76 m_progress = new QProgressBar(this);
77 m_progress->setMaximumHeight(m_button->height() / 5);
78 m_progress->setTextVisible(false);
79 layout->addWidget(m_progress);
80 m_progress->setVisible(false);
81 setMinimumHeight(m_button->sizeHint().height() + (m_label != nullptr ? m_label->sizeHint().height() : 0));
82
83 // emit the signal of the base class when appropriate
84 connect(this->m_button, &QPushButton::clicked, this, [&, filterData, filterAddedParams, consumerParams, defaultValue]() {
85 // Trigger job
86 bool isTracker = m_model->getAssetId() == QLatin1String("opencv.tracker");
87 if (!m_displayConditional) {
88 QVector<QPair<QString, QVariant>> values;
89 if (isTracker) {
90 // Tracker needs some special config on reset
91 QString current = m_model->getAsset()->get(m_keyParam.toUtf8().constData());
92 if (!current.isEmpty()) {
93 // Extract first keyframe
94 current = current.section(QLatin1Char('='), 1);
95 current = current.section(QLatin1Char(';'), 0, 0);
96 }
97 if (current.isEmpty()) {
98 if (defaultValue.contains(QLatin1Char('%'))) {
99 QSize pSize = pCore->getCurrentFrameDisplaySize();
100 QStringList numbers = defaultValue.split(QLatin1Char(' '));
101 int ix = 0;
102 for ( QString &val : numbers) {
103 if (val.endsWith(QLatin1Char('%'))) {
104 val.chop(1);
105 double n = val.toDouble()/100.;
106 if (ix %2 == 0) {
107 n *= pSize.width();
108 } else {
109 n *= pSize.height();
110 }
111 ix++;
112 current.append(QString("%1 ").arg(qRound(n)));
113 } else {
114 current.append(QString("%1 ").arg(val));
115 }
116 }
117 } else {
118 current = defaultValue;
119 }
120 }
121 //values << QPair<QString, QVariant>(QString("rect"),current);
122 //values << QPair<QString, QVariant>(QString("_reset"),1);
123 values << QPair<QString, QVariant>(m_keyParam,current);
124 } else {
125 values << QPair<QString, QVariant>(m_keyParam,defaultValue);
126 }
127 auto *command = new AssetUpdateCommand(m_model, values);
128 pCore->pushUndo(command);
129 return;
130 }
131 QVector<QPair<QString, QVariant>> filterLastParams = m_model->getAllParameters();
132 ObjectId owner = m_model->getOwnerId();
133 const QString assetId = m_model->getAssetId();
134 QString binId;
135 int cid = -1;
136 int in = -1;
137 int out = -1;
138 if (owner.first == ObjectType::BinClip) {
139 binId = QString::number(owner.second);
140 } else if (owner.first == ObjectType::TimelineClip) {
141 cid = owner.second;
142 binId = pCore->getTimelineClipBinId(cid);
143 in = pCore->getItemIn(owner);
144 out = in + pCore->getItemDuration(owner);
145 } else if (owner.first == ObjectType::TimelineTrack || owner.first == ObjectType::Master) {
146 in = 0;
147 out = pCore->getItemDuration(owner);
148 binId = QStringLiteral("-1");
149 }
150 std::unordered_map<QString, QVariant> fParams;
151 std::unordered_map<QString, QString> fData;
152 for (const QVariant &jobElement : filterData) {
153 QStringList d = jobElement.toStringList();
154 if (d.size() == 2)
155 fData.insert({d.at(0), d.at(1)});
156 }
157 for (const auto ¶m : qAsConst(filterLastParams)) {
158 if (param.first != m_keyParam) {
159 if (!isTracker || param.first != QLatin1String("rect")) {
160 fParams.insert({param.first, param.second});
161 }
162 } else if (isTracker) {
163 QString initialRect = param.second.toString();
164 if (initialRect.contains(QLatin1Char('='))) {
165 initialRect = initialRect.section(QLatin1Char('='), 1);
166 }
167 if (initialRect.contains(QLatin1Char(';'))) {
168 initialRect = initialRect.section(QLatin1Char(';'), 0, 0);
169 }
170 fParams.insert({QStringLiteral("rect"), initialRect});
171 }
172 }
173 for (const QString &fparam : filterAddedParams) {
174 if (fparam.contains(QLatin1Char('='))) {
175 fParams.insert({fparam.section(QLatin1Char('='), 0, 0), fparam.section(QLatin1Char('='), 1)});
176 }
177 }
178 if (m_progress->value() > 0 && m_progress->value() < 100) {
179 // The task is in progress, abort it
180 pCore->taskManager.discardJobs(owner, AbstractTask::FILTERCLIPJOB);
181 } else {
182 FilterTask::start(owner, binId, m_model, assetId, in, out, assetId, fParams, fData, consumerParams, this);
183 if (m_label) {
184 m_label->setVisible(false);
185 }
186 m_button->setEnabled(false);
187 }
188 });
189 }
190
slotShowComment(bool show)191 void ButtonParamWidget::slotShowComment(bool show)
192 {
193 Q_UNUSED(show);
194 //if (!m_labelComment->text().isEmpty()) {
195 // m_widgetComment->setVisible(show);
196 //}
197 }
198
slotRefresh()199 void ButtonParamWidget::slotRefresh()
200 {
201 QVector<QPair<QString, QVariant>> filterParams = m_model->getAllParameters();
202 m_displayConditional = true;
203 for (const auto ¶m : qAsConst(filterParams)) {
204 if (param.first == m_keyParam && !param.second.isNull() && param.second.toString().contains(QLatin1Char(';'))) {
205 m_displayConditional = false;
206 break;
207 }
208 }
209 if (m_label) {
210 m_label->setVisible(m_displayConditional);
211 }
212 m_button->setEnabled(true);
213 // Check running job percentage
214 int progress = m_model->data(m_index, AssetParameterModel::FilterProgressRole).toInt();
215 if (progress > 0 && progress < 100) {
216 m_progress->setValue(progress);
217 if (!m_progress->isVisible()) {
218 m_button->setText(i18n("Abort processing"));
219 m_progress->setVisible(true);
220 }
221
222 } else {
223 m_button->setText(m_displayConditional ? m_buttonName : m_alternatebuttonName);
224 m_progress->setValue(0);
225 m_progress->setVisible(false);
226 }
227 updateGeometry();
228 }
229
getValue()230 bool ButtonParamWidget::getValue()
231 {
232 return true;
233 }
234
235