File indexing completed on 2024-05-05 04:52:53
0001 /* 0002 SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "generators.h" 0008 #include "assets/abstractassetsrepository.hpp" 0009 #include "doc/kthumb.h" 0010 #include "effects/effectsrepository.hpp" 0011 #include "kdenlivesettings.h" 0012 #include "widgets/timecodedisplay.h" 0013 0014 #include <QDialogButtonBox> 0015 #include <QDir> 0016 #include <QDomDocument> 0017 #include <QFileDialog> 0018 #include <QLabel> 0019 #include <QStandardPaths> 0020 #include <QVBoxLayout> 0021 0022 #include "core.h" 0023 #include "klocalizedstring.h" 0024 #include "profiles/profilemodel.hpp" 0025 #include <KMessageBox> 0026 #include <KRecentDirs> 0027 #include <memory> 0028 #include <mlt++/MltConsumer.h> 0029 #include <mlt++/MltProducer.h> 0030 #include <mlt++/MltProfile.h> 0031 #include <mlt++/MltTractor.h> 0032 0033 Generators::Generators(const QString &path, QWidget *parent) 0034 : QDialog(parent) 0035 , m_producer(nullptr) 0036 , m_timePos(nullptr) 0037 , m_container(nullptr) 0038 , m_preview(nullptr) 0039 { 0040 QDomDocument doc; 0041 if (!Xml::docContentFromFile(doc, path, false)) { 0042 return; 0043 } 0044 0045 QDomElement base = doc.documentElement(); 0046 if (base.tagName() == QLatin1String("generator")) { 0047 QString generatorTag = base.attribute(QStringLiteral("tag")); 0048 setWindowTitle(i18n(base.firstChildElement(QStringLiteral("name")).text().toUtf8().data())); 0049 auto *lay = new QVBoxLayout(this); 0050 m_preview = new QLabel; 0051 m_preview->setMinimumSize(1, 1); 0052 lay->addWidget(m_preview); 0053 m_producer = new Mlt::Producer(pCore->getProjectProfile(), generatorTag.toUtf8().constData()); 0054 m_pixmap = QPixmap::fromImage(KThumb::getFrame(m_producer, 0, pCore->getCurrentProfile()->width(), pCore->getCurrentProfile()->height())); 0055 m_preview->setPixmap(m_pixmap.scaledToWidth(m_preview->width())); 0056 auto *hlay = new QHBoxLayout; 0057 hlay->addWidget(new QLabel(i18n("Duration:"))); 0058 m_timePos = new TimecodeDisplay(this); 0059 if (base.hasAttribute(QStringLiteral("updateonduration"))) { 0060 connect(m_timePos, &TimecodeDisplay::timeCodeEditingFinished, this, &Generators::updateDuration); 0061 } 0062 hlay->addWidget(m_timePos); 0063 lay->addLayout(hlay); 0064 QWidget *frameWidget = new QWidget; 0065 lay->addWidget(frameWidget); 0066 0067 m_view = new AssetParameterView(frameWidget); 0068 lay->addWidget(m_view); 0069 QString tag = base.attribute(QStringLiteral("tag"), QString()); 0070 0071 auto prop = std::make_unique<Mlt::Properties>(m_producer->get_properties()); 0072 m_assetModel.reset(new AssetParameterModel(std::move(prop), base, tag, ObjectId())); // NOLINT 0073 m_view->setModel(m_assetModel, QSize(1920, 1080), false); 0074 connect(m_assetModel.get(), &AssetParameterModel::modelChanged, this, [this]() { updateProducer(); }); 0075 0076 lay->addStretch(10); 0077 QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); 0078 connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0079 connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0080 lay->addWidget(buttonBox); 0081 m_timePos->setValue(KdenliveSettings::color_duration()); 0082 } 0083 } 0084 0085 void Generators::updateProducer() 0086 { 0087 int w = m_pixmap.width(); 0088 int h = m_pixmap.height(); 0089 m_pixmap = QPixmap::fromImage(KThumb::getFrame(m_producer, 0, w, h)); 0090 m_preview->setPixmap(m_pixmap.scaledToWidth(m_preview->width())); 0091 } 0092 0093 void Generators::resizeEvent(QResizeEvent *event) 0094 { 0095 QDialog::resizeEvent(event); 0096 m_preview->setPixmap(m_pixmap.scaledToWidth(m_preview->width())); 0097 } 0098 0099 Generators::~Generators() 0100 { 0101 delete m_timePos; 0102 } 0103 0104 // static 0105 void Generators::getGenerators(const QStringList &producers, QMenu *menu) 0106 { 0107 const QStringList generatorFolders = 0108 QStandardPaths::locateAll(QStandardPaths::AppDataLocation, QStringLiteral("generators"), QStandardPaths::LocateDirectory); 0109 const QStringList filters = QStringList() << QStringLiteral("*.xml"); 0110 QStringList parsedGenerators; 0111 for (const QString &folder : generatorFolders) { 0112 QDir directory(folder); 0113 const QStringList filesnames = directory.entryList(filters, QDir::Files); 0114 for (const QString &fname : filesnames) { 0115 if (parsedGenerators.contains(fname)) { 0116 continue; 0117 } 0118 parsedGenerators << fname; 0119 QPair<QString, QString> result = parseGenerator(directory.absoluteFilePath(fname), producers); 0120 if (!result.first.isEmpty()) { 0121 QAction *action = menu->addAction(i18n(result.first.toUtf8().data())); 0122 action->setData(result.second); 0123 } 0124 } 0125 } 0126 } 0127 0128 // static 0129 QPair<QString, QString> Generators::parseGenerator(const QString &path, const QStringList &producers) 0130 { 0131 QPair<QString, QString> result; 0132 QDomDocument doc; 0133 if (!Xml::docContentFromFile(doc, path, false)) { 0134 return result; 0135 } 0136 0137 QDomElement base = doc.documentElement(); 0138 if (base.tagName() == QLatin1String("generator")) { 0139 QString generatorTag = base.attribute(QStringLiteral("tag")); 0140 if (producers.contains(generatorTag)) { 0141 result.first = base.firstChildElement(QStringLiteral("name")).text(); 0142 result.second = path; 0143 } 0144 } 0145 return result; 0146 } 0147 0148 void Generators::updateDuration(int duration) 0149 { 0150 m_producer->set("length", duration); 0151 m_producer->set_in_and_out(0, duration - 1); 0152 updateProducer(); 0153 } 0154 0155 QUrl Generators::getSavedClip(QString clipFolder) 0156 { 0157 if (clipFolder.isEmpty()) { 0158 clipFolder = KRecentDirs::dir(QStringLiteral(":KdenliveClipFolder")); 0159 } 0160 if (clipFolder.isEmpty()) { 0161 clipFolder = QDir::homePath(); 0162 } 0163 QFileDialog fd(this); 0164 fd.setDirectory(clipFolder); 0165 fd.setNameFilter(i18n("MLT Playlist (*.mlt)")); 0166 fd.setAcceptMode(QFileDialog::AcceptSave); 0167 fd.setFileMode(QFileDialog::AnyFile); 0168 fd.setDefaultSuffix(QStringLiteral("mlt")); 0169 if (fd.exec() != QDialog::Accepted || fd.selectedUrls().isEmpty()) { 0170 return QUrl(); 0171 } 0172 QUrl url = fd.selectedUrls().constFirst(); 0173 0174 if (url.isValid()) { 0175 Mlt::Tractor trac(pCore->getProjectProfile()); 0176 m_producer->set("length", m_timePos->getValue()); 0177 m_producer->set_in_and_out(0, m_timePos->getValue() - 1); 0178 trac.set_track(*m_producer, 0); 0179 Mlt::Consumer c(pCore->getProjectProfile(), "xml", url.toLocalFile().toUtf8().constData()); 0180 c.connect(trac); 0181 c.run(); 0182 return url; 0183 } 0184 return QUrl(); 0185 }