File indexing completed on 2024-04-28 04:52:15
0001 /* 0002 SPDX-FileCopyrightText: 2008 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "slideshowclip.h" 0008 #include "bin/projectclip.h" 0009 #include "core.h" 0010 #include "kdenlivesettings.h" 0011 #include "mainwindow.h" 0012 0013 #include <KFileItem> 0014 #include <KLocalizedString> 0015 #include <KRecentDirs> 0016 0017 #include "kdenlive_debug.h" 0018 #include <QDir> 0019 #include <QFontDatabase> 0020 #include <QStandardPaths> 0021 #include <QtMath> 0022 0023 SlideshowClip::SlideshowClip(const Timecode &tc, QString clipFolder, ProjectClip *clip, QWidget *parent) 0024 : QDialog(parent) 0025 , m_count(0) 0026 , m_timecode(tc) 0027 , m_thumbJob(nullptr) 0028 { 0029 setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0030 m_view.setupUi(this); 0031 setWindowTitle(i18nc("@title:window", "Add Image Sequence")); 0032 if (clip) { 0033 m_view.clip_name->setText(clip->name()); 0034 m_view.groupBox->setHidden(true); 0035 } else { 0036 m_view.clip_name->setText(i18n("Image Sequence")); 0037 } 0038 m_view.folder_url->setMode(KFile::Directory); 0039 m_view.folder_url->setUrl(QUrl::fromLocalFile(KRecentDirs::dir(QStringLiteral(":KdenliveSlideShowFolder")))); 0040 m_view.icon_list->setIconSize(QSize(50, 50)); 0041 m_view.show_thumbs->setChecked(KdenliveSettings::showslideshowthumbs()); 0042 0043 connect(m_view.show_thumbs, &QCheckBox::stateChanged, this, &SlideshowClip::slotEnableThumbs); 0044 connect(m_view.slide_fade, &QCheckBox::stateChanged, this, &SlideshowClip::slotEnableLuma); 0045 connect(m_view.luma_fade, &QCheckBox::stateChanged, this, &SlideshowClip::slotEnableLumaFile); 0046 0047 // WARNING: keep in sync with project/clipproperties.cpp 0048 m_view.image_type->addItem(QStringLiteral("JPG (*.jpg)"), QStringLiteral("jpg")); 0049 m_view.image_type->addItem(QStringLiteral("JPEG (*.jpeg)"), QStringLiteral("jpeg")); 0050 m_view.image_type->addItem(QStringLiteral("PNG (*.png)"), QStringLiteral("png")); 0051 m_view.image_type->addItem(QStringLiteral("SVG (*.svg)"), QStringLiteral("svg")); 0052 m_view.image_type->addItem(QStringLiteral("BMP (*.bmp)"), QStringLiteral("bmp")); 0053 m_view.image_type->addItem(QStringLiteral("GIF (*.gif)"), QStringLiteral("gif")); 0054 m_view.image_type->addItem(QStringLiteral("TGA (*.tga)"), QStringLiteral("tga")); 0055 m_view.image_type->addItem(QStringLiteral("TIF (*.tif)"), QStringLiteral("tif")); 0056 m_view.image_type->addItem(QStringLiteral("TIFF (*.tiff)"), QStringLiteral("tiff")); 0057 m_view.image_type->addItem(QStringLiteral("Open EXR (*.exr)"), QStringLiteral("exr")); 0058 m_view.image_type->addItem(i18n("Preview from CR2 (*.cr2)"), QStringLiteral("cr2")); 0059 m_view.image_type->addItem(i18n("Preview from ARW (*.arw)"), QStringLiteral("arw")); 0060 m_view.animation->addItem(i18n("None"), QString()); 0061 0062 KConfig conf(QStringLiteral("slideanimations.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation); 0063 KConfigGroup group(&conf, "slides"); 0064 QMap<QString, QString> slideTranslations; 0065 slideTranslations.insert(QStringLiteral("Pan"), i18nc("Image Pan", "Pan")); 0066 slideTranslations.insert(QStringLiteral("Pan and zoom"), i18n("Pan and zoom")); 0067 slideTranslations.insert(QStringLiteral("Zoom"), i18n("Zoom")); 0068 QStringList animValues = group.keyList(); 0069 for (const auto &val : animValues) { 0070 if (slideTranslations.contains(val)) { 0071 m_view.animation->addItem(slideTranslations.value(val), val); 0072 } else { 0073 m_view.animation->addItem(val, val); 0074 } 0075 } 0076 0077 m_view.clip_duration->setInputMask(m_timecode.mask()); 0078 m_view.luma_duration->setInputMask(m_timecode.mask()); 0079 m_view.luma_duration->setText(m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps())))); 0080 0081 if (clipFolder.isEmpty()) { 0082 clipFolder = QDir::homePath(); 0083 } 0084 m_view.folder_url->setUrl(QUrl::fromLocalFile(QFileInfo(clipFolder).dir().absolutePath())); 0085 0086 m_view.clip_duration_format->addItem(i18n("hh:mm:ss:ff")); 0087 m_view.clip_duration_format->addItem(i18n("Frames")); 0088 connect(m_view.clip_duration_format, SIGNAL(activated(int)), this, SLOT(slotUpdateDurationFormat(int))); 0089 m_view.clip_duration_frames->setHidden(true); 0090 m_view.luma_duration_frames->setHidden(true); 0091 if (clip) { 0092 QString url = clip->url(); 0093 if (QFileInfo(url).fileName().startsWith(QLatin1String(".all."))) { 0094 // the image sequence is defined by MIME type 0095 m_view.method_mime->setChecked(true); 0096 m_view.folder_url->setText(QFileInfo(url).absolutePath()); 0097 QString filter = QFileInfo(url).fileName(); 0098 QString ext = filter.section(QLatin1Char('.'), -1); 0099 int ix = m_view.image_type->findData(ext); 0100 if (ix > -1) { 0101 m_view.image_type->setCurrentIndex(ix); 0102 } 0103 } else { 0104 // the image sequence is defined by pattern 0105 m_view.method_pattern->setChecked(true); 0106 m_view.pattern_url->setText(url); 0107 } 0108 } else { 0109 // Using clipfolder file path 0110 QFileInfo file(clipFolder); 0111 QString extension = KdenliveSettings::slideshowmimeextension(); 0112 if (file.isFile()) { 0113 extension = file.suffix(); 0114 m_view.folder_url->setText(file.dir().absolutePath()); 0115 } 0116 if (!extension.isEmpty()) { 0117 int ix = m_view.image_type->findData(extension); 0118 if (ix > -1) { 0119 m_view.image_type->setCurrentIndex(ix); 0120 } 0121 } 0122 m_view.pattern_url->setUrl(QUrl::fromLocalFile(clipFolder)); 0123 m_view.method_mime->setChecked(KdenliveSettings::slideshowbymime()); 0124 slotMethodChanged(m_view.method_mime->isChecked()); 0125 parseFolder(); 0126 } 0127 connect(m_view.method_mime, &QAbstractButton::toggled, this, &SlideshowClip::slotMethodChanged); 0128 connect(m_view.image_type, SIGNAL(currentIndexChanged(int)), this, SLOT(parseFolder())); 0129 connect(m_view.folder_url, &KUrlRequester::textChanged, this, &SlideshowClip::parseFolder); 0130 connect(m_view.pattern_url, &KUrlRequester::textChanged, this, &SlideshowClip::parseFolder); 0131 0132 // Fill luma list 0133 m_view.luma_file->setIconSize(QSize(50, 30)); 0134 QStringList values; 0135 if (pCore->getCurrentFrameSize().width() > 1000) { 0136 // HD project 0137 values = MainWindow::m_lumaFiles.value(QStringLiteral("16_9")); 0138 } else if (pCore->getCurrentFrameSize().height() > 1000) { 0139 values = MainWindow::m_lumaFiles.value(QStringLiteral("9_16")); 0140 } else if (pCore->getCurrentFrameSize().height() == pCore->getCurrentFrameSize().width()) { 0141 values = MainWindow::m_lumaFiles.value(QStringLiteral("square")); 0142 } else if (pCore->getCurrentFrameSize().height() == 480) { 0143 values = MainWindow::m_lumaFiles.value(QStringLiteral("NTSC")); 0144 } else { 0145 values = MainWindow::m_lumaFiles.value(QStringLiteral("PAL")); 0146 } 0147 values.removeDuplicates(); 0148 0149 QStringList names; 0150 for (const QString &value : qAsConst(values)) { 0151 names.append(QUrl(value).fileName()); 0152 } 0153 for (int i = 0; i < values.count(); i++) { 0154 const QString &entry = values.at(i); 0155 // Create thumbnails 0156 if (!entry.isEmpty() && (entry.endsWith(QLatin1String(".png")) || entry.endsWith(QLatin1String(".pgm")))) { 0157 if (MainWindow::m_lumacache.contains(entry)) { 0158 m_view.luma_file->addItem(QPixmap::fromImage(MainWindow::m_lumacache.value(entry)), names.at(i), entry); 0159 } else { 0160 QImage pix(entry); 0161 if (!pix.isNull()) { 0162 MainWindow::m_lumacache.insert(entry, pix.scaled(50, 30, Qt::KeepAspectRatio, Qt::SmoothTransformation)); 0163 m_view.luma_file->addItem(QPixmap::fromImage(MainWindow::m_lumacache.value(entry)), names.at(i), entry); 0164 } 0165 } 0166 } 0167 } 0168 0169 if (clip) { 0170 m_view.slide_loop->setChecked(clip->getProducerIntProperty(QStringLiteral("loop")) != 0); 0171 m_view.slide_crop->setChecked(clip->getProducerIntProperty(QStringLiteral("crop")) != 0); 0172 m_view.slide_fade->setChecked(clip->getProducerIntProperty(QStringLiteral("fade")) != 0); 0173 m_view.luma_softness->setValue(clip->getProducerIntProperty(QStringLiteral("softness"))); 0174 QString anim = clip->getProducerProperty(QStringLiteral("animation")); 0175 if (!anim.isEmpty()) { 0176 int ix = m_view.animation->findData(anim); 0177 m_view.animation->setCurrentIndex(qMax(0, ix)); 0178 } else { 0179 m_view.animation->setCurrentIndex(0); 0180 } 0181 m_view.low_pass->setChecked(clip->getProducerProperty(QStringLiteral("low-pass")) == QLatin1String("1")); 0182 int ttl = clip->getProducerIntProperty(QStringLiteral("ttl")); 0183 m_view.clip_duration->setText(tc.getTimecodeFromFrames(ttl)); 0184 m_view.clip_duration_frames->setValue(ttl); 0185 m_view.luma_duration->setText(tc.getTimecodeFromFrames(clip->getProducerIntProperty(QStringLiteral("luma_duration")))); 0186 QString lumaFile = clip->getProducerProperty(QStringLiteral("luma_file")); 0187 if (!lumaFile.isEmpty()) { 0188 m_view.luma_fade->setChecked(true); 0189 m_view.luma_file->setCurrentIndex(m_view.luma_file->findData(lumaFile)); 0190 } else { 0191 m_view.luma_file->setEnabled(false); 0192 } 0193 slotEnableLuma(m_view.slide_fade->checkState()); 0194 slotEnableLumaFile(m_view.luma_fade->checkState()); 0195 parseFolder(); 0196 } 0197 m_view.low_pass->setEnabled(!m_view.animation->currentData().isNull()); 0198 connect(m_view.animation, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, 0199 [&]() { m_view.low_pass->setEnabled(!m_view.animation->currentData().isNull()); }); 0200 // adjustSize(); 0201 } 0202 0203 SlideshowClip::~SlideshowClip() 0204 { 0205 delete m_thumbJob; 0206 } 0207 0208 void SlideshowClip::slotEnableLuma(int state) 0209 { 0210 bool enable = false; 0211 if (state == Qt::Checked) { 0212 enable = true; 0213 } 0214 m_view.luma_duration->setEnabled(enable); 0215 m_view.luma_duration_frames->setEnabled(enable); 0216 m_view.luma_fade->setEnabled(enable); 0217 if (enable) { 0218 m_view.luma_file->setEnabled(m_view.luma_fade->isChecked()); 0219 } else { 0220 m_view.luma_file->setEnabled(false); 0221 } 0222 m_view.label_softness->setEnabled(m_view.luma_fade->isChecked() && enable); 0223 m_view.luma_softness->setEnabled(m_view.label_softness->isEnabled()); 0224 } 0225 0226 void SlideshowClip::slotEnableThumbs(int state) 0227 { 0228 if (state == Qt::Checked) { 0229 KdenliveSettings::setShowslideshowthumbs(true); 0230 slotGenerateThumbs(); 0231 } else { 0232 KdenliveSettings::setShowslideshowthumbs(false); 0233 if (m_thumbJob) { 0234 disconnect(m_thumbJob, &KIO::PreviewJob::gotPreview, this, &SlideshowClip::slotSetPixmap); 0235 m_thumbJob->kill(); 0236 m_thumbJob->deleteLater(); 0237 m_thumbJob = nullptr; 0238 } 0239 } 0240 } 0241 0242 void SlideshowClip::slotEnableLumaFile(int state) 0243 { 0244 bool enable = false; 0245 if (state == Qt::Checked) { 0246 enable = true; 0247 } 0248 m_view.luma_file->setEnabled(enable); 0249 m_view.luma_softness->setEnabled(enable); 0250 m_view.label_softness->setEnabled(enable); 0251 } 0252 0253 void SlideshowClip::parseFolder() 0254 { 0255 m_view.icon_list->clear(); 0256 bool isMime = m_view.method_mime->isChecked(); 0257 QString path = isMime ? m_view.folder_url->url().toLocalFile() : m_view.pattern_url->url().adjusted(QUrl::RemoveFilename).toLocalFile(); 0258 QDir dir(path); 0259 if (path.isEmpty() || !dir.exists()) { 0260 m_count = 0; 0261 m_view.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); 0262 m_view.label_info->setText(QString()); 0263 return; 0264 } 0265 0266 QIcon unknownicon(QStringLiteral("unknown")); 0267 QStringList result; 0268 QStringList filters; 0269 QString filter; 0270 if (isMime) { 0271 // TODO: improve jpeg image detection with extension like jpeg, requires change in MLT image producers 0272 filter = m_view.image_type->currentData().toString(); 0273 filters << QStringLiteral("*.") + filter; 0274 dir.setNameFilters(filters); 0275 result = dir.entryList(QDir::Files); 0276 } else { 0277 int offset = 0; 0278 QString path_pattern = m_view.pattern_url->text(); 0279 QDir abs_dir = QFileInfo(m_view.pattern_url->text()).absoluteDir(); 0280 result = abs_dir.entryList(QDir::Files); 0281 // find pattern 0282 if (path_pattern.contains(QLatin1Char('?'))) { 0283 // New MLT syntax 0284 if (path_pattern.section(QLatin1Char('?'), 1).contains(QLatin1Char(':'))) { 0285 // Old deprecated format 0286 offset = path_pattern.section(QLatin1Char(':'), -1).toInt(); 0287 } else { 0288 offset = path_pattern.section(QLatin1Char('='), -1).toInt(); 0289 } 0290 path_pattern = path_pattern.section(QLatin1Char('?'), 0, 0); 0291 } 0292 filter = QFileInfo(path_pattern).fileName(); 0293 QString ext = filter.section(QLatin1Char('.'), -1); 0294 if (filter.contains(QLatin1Char('%'))) { 0295 filter = filter.section(QLatin1Char('%'), 0, -2); 0296 } else { 0297 filter = filter.section(QLatin1Char('.'), 0, -2); 0298 while (!filter.isEmpty() && filter.at(filter.count() - 1).isDigit()) { 0299 filter.remove(filter.count() - 1, 1); 0300 } 0301 } 0302 qDebug() << " / /" << path_pattern << " / " << ext << " / " << filter; 0303 QString regexp = QLatin1Char('^') + filter + QStringLiteral("\\d+\\.") + ext + QLatin1Char('$'); 0304 static const QRegularExpression rx(QRegularExpression::anchoredPattern(regexp)); 0305 QStringList entries; 0306 for (const QString &p : qAsConst(result)) { 0307 if (rx.match(p).hasMatch()) { 0308 if (offset > 0) { 0309 // make sure our image is in the range we want (> begin) 0310 int ix = p.section(filter, 1).section('.', 0, 0).toInt(); 0311 if (ix < offset) { 0312 continue; 0313 } 0314 } 0315 entries << p; 0316 } 0317 } 0318 result = entries; 0319 } 0320 for (const QString &p : qAsConst(result)) { 0321 auto *item = new QListWidgetItem(unknownicon, p); 0322 item->setData(Qt::UserRole, dir.filePath(p)); 0323 m_view.icon_list->addItem(item); 0324 } 0325 m_count = m_view.icon_list->count(); 0326 m_view.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_count > 0); 0327 if (m_count == 0) { 0328 m_view.label_info->setText(i18n("No image found")); 0329 } else { 0330 m_view.label_info->setText(i18np("1 image found", "%1 images found", m_count)); 0331 } 0332 if (m_view.show_thumbs->isChecked()) { 0333 slotGenerateThumbs(); 0334 } 0335 m_view.icon_list->setCurrentRow(0); 0336 } 0337 0338 void SlideshowClip::slotGenerateThumbs() 0339 { 0340 delete m_thumbJob; 0341 KFileItemList fileList; 0342 for (int i = 0; i < m_view.icon_list->count(); ++i) { 0343 QListWidgetItem *item = m_view.icon_list->item(i); 0344 if (item) { 0345 QString path = item->data(Qt::UserRole).toString(); 0346 if (!path.isEmpty()) { 0347 KFileItem f(QUrl::fromLocalFile(path)); 0348 f.setDelayedMimeTypes(true); 0349 fileList.append(f); 0350 } 0351 } 0352 } 0353 m_thumbJob = new KIO::PreviewJob(fileList, QSize(50, 50)); 0354 m_thumbJob->setScaleType(KIO::PreviewJob::Scaled); 0355 m_thumbJob->setAutoDelete(false); 0356 connect(m_thumbJob, &KIO::PreviewJob::gotPreview, this, &SlideshowClip::slotSetPixmap); 0357 m_thumbJob->start(); 0358 } 0359 0360 void SlideshowClip::slotSetPixmap(const KFileItem &fileItem, const QPixmap &pix) 0361 { 0362 for (int i = 0; i < m_view.icon_list->count(); ++i) { 0363 QListWidgetItem *item = m_view.icon_list->item(i); 0364 if (item) { 0365 QString path = item->data(Qt::UserRole).toString(); 0366 if (path == fileItem.url().toLocalFile()) { 0367 item->setIcon(QIcon(pix)); 0368 item->setData(Qt::UserRole, QString()); 0369 break; 0370 } 0371 } 0372 } 0373 } 0374 0375 QString SlideshowClip::selectedPath() 0376 { 0377 QStringList list; 0378 QUrl url; 0379 if (m_view.method_mime->isChecked()) { 0380 url = m_view.folder_url->url(); 0381 } else { 0382 url = m_view.pattern_url->url(); 0383 } 0384 QString path = selectedPath(url, m_view.method_mime->isChecked(), QStringLiteral(".all.") + m_view.image_type->currentData().toString(), &list); 0385 m_count = list.count(); 0386 // qCDebug(KDENLIVE_LOG)<<"// SELECTED PATH: "<<path; 0387 return path; 0388 } 0389 0390 // static 0391 int SlideshowClip::getFrameNumberFromPath(const QUrl &path) 0392 { 0393 QString filter = path.fileName(); 0394 filter = filter.section(QLatin1Char('.'), 0, -2); 0395 int ix = filter.size() - 1; 0396 while (ix >= 0 && filter.at(ix).isDigit()) { 0397 ix--; 0398 } 0399 return filter.remove(0, ix + 1).toInt(); 0400 } 0401 0402 // static 0403 QString SlideshowClip::selectedPath(const QUrl &url, bool isMime, QString extension, QStringList *list) 0404 { 0405 QString folder; 0406 if (isMime) { 0407 folder = url.toLocalFile(); 0408 if (!folder.endsWith(QLatin1Char('/'))) { 0409 folder.append(QLatin1Char('/')); 0410 } 0411 // Check how many files we have 0412 QDir dir(folder); 0413 QStringList filters; 0414 filters << QStringLiteral("*.") + extension.section(QLatin1Char('.'), -1); 0415 dir.setNameFilters(filters); 0416 *list = dir.entryList(QDir::Files); 0417 } else { 0418 folder = url.adjusted(QUrl::RemoveFilename).toLocalFile(); 0419 QString filter = url.fileName(); 0420 QString ext = QLatin1Char('.') + filter.section(QLatin1Char('.'), -1); 0421 filter = filter.section(QLatin1Char('.'), 0, -2); 0422 int fullSize = filter.size(); 0423 QString firstFrameData = filter; 0424 0425 while (filter.size() > 0 && filter.at(filter.size() - 1).isDigit()) { 0426 filter.chop(1); 0427 } 0428 0429 // Find number of digits in sequence 0430 int precision = fullSize - filter.size(); 0431 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0432 int firstFrame = firstFrameData.rightRef(precision).toInt(); 0433 #else 0434 int firstFrame = QStringView(firstFrameData).right(precision).toInt(); 0435 #endif 0436 // Check how many files we have 0437 QDir dir(folder); 0438 QString path; 0439 int gap = 0; 0440 for (int i = firstFrame; gap < 100; ++i) { 0441 path = filter + QString::number(i).rightJustified(precision, QLatin1Char('0'), false) + ext; 0442 if (dir.exists(path)) { 0443 (*list).append(folder + path); 0444 gap = 0; 0445 } else { 0446 gap++; 0447 } 0448 } 0449 extension = filter + QStringLiteral("%0") + QString::number(precision) + QLatin1Char('d') + ext; 0450 if (firstFrame > 0) { 0451 extension.append(QStringLiteral("?begin=%1").arg(firstFrame)); 0452 } 0453 } 0454 // qCDebug(KDENLIVE_LOG) << "// FOUND " << (*list).count() << " items for " << url.toLocalFile(); 0455 return folder + extension; 0456 } 0457 0458 QString SlideshowClip::clipName() const 0459 { 0460 return m_view.clip_name->text(); 0461 } 0462 0463 QString SlideshowClip::clipDuration() const 0464 { 0465 if (m_view.clip_duration_format->currentIndex() == 1) { 0466 // we are in frames mode 0467 return m_timecode.getTimecodeFromFrames(m_view.clip_duration_frames->value()); 0468 } 0469 return m_view.clip_duration->text(); 0470 } 0471 0472 int SlideshowClip::imageCount() const 0473 { 0474 return m_count; 0475 } 0476 0477 int SlideshowClip::softness() const 0478 { 0479 return m_view.luma_softness->value(); 0480 } 0481 0482 bool SlideshowClip::loop() const 0483 { 0484 return m_view.slide_loop->isChecked(); 0485 } 0486 0487 bool SlideshowClip::crop() const 0488 { 0489 return m_view.slide_crop->isChecked(); 0490 } 0491 0492 bool SlideshowClip::fade() const 0493 { 0494 return m_view.slide_fade->isChecked(); 0495 } 0496 0497 QString SlideshowClip::lumaDuration() const 0498 { 0499 if (m_view.clip_duration_format->currentIndex() == 1) { 0500 // we are in frames mode 0501 return m_timecode.getTimecodeFromFrames(m_view.luma_duration_frames->value()); 0502 } 0503 return m_view.luma_duration->text(); 0504 } 0505 0506 QString SlideshowClip::lumaFile() const 0507 { 0508 if (!m_view.luma_fade->isChecked() || !m_view.luma_file->isEnabled()) { 0509 return QString(); 0510 } 0511 return m_view.luma_file->itemData(m_view.luma_file->currentIndex()).toString(); 0512 } 0513 0514 QString SlideshowClip::animation() const 0515 { 0516 if (m_view.animation->currentData().isNull()) { 0517 return QString(); 0518 } 0519 return m_view.animation->currentData().toString(); 0520 } 0521 0522 void SlideshowClip::slotUpdateDurationFormat(int ix) 0523 { 0524 bool framesFormat = ix == 1; 0525 if (framesFormat) { 0526 // switching to frames count, update widget 0527 m_view.clip_duration_frames->setValue(m_timecode.getFrameCount(m_view.clip_duration->text())); 0528 m_view.luma_duration_frames->setValue(m_timecode.getFrameCount(m_view.luma_duration->text())); 0529 } else { 0530 // switching to timecode format 0531 m_view.clip_duration->setText(m_timecode.getTimecodeFromFrames(m_view.clip_duration_frames->value())); 0532 m_view.luma_duration->setText(m_timecode.getTimecodeFromFrames(m_view.luma_duration_frames->value())); 0533 } 0534 m_view.clip_duration_frames->setHidden(!framesFormat); 0535 m_view.clip_duration->setHidden(framesFormat); 0536 m_view.luma_duration_frames->setHidden(!framesFormat); 0537 m_view.luma_duration->setHidden(framesFormat); 0538 } 0539 0540 void SlideshowClip::slotMethodChanged(bool active) 0541 { 0542 if (active) { 0543 // User wants MIME type image sequence 0544 m_view.clip_duration->setText(m_timecode.reformatSeparators(KdenliveSettings::image_duration())); 0545 m_view.stackedWidget->setCurrentIndex(0); 0546 KdenliveSettings::setSlideshowbymime(true); 0547 } else { 0548 // User wants pattern image sequence 0549 m_view.clip_duration->setText(m_timecode.reformatSeparators(KdenliveSettings::sequence_duration())); 0550 m_view.stackedWidget->setCurrentIndex(1); 0551 KdenliveSettings::setSlideshowbymime(false); 0552 } 0553 parseFolder(); 0554 } 0555 0556 int SlideshowClip::lowPass() const 0557 { 0558 return m_view.low_pass->isEnabled() && m_view.low_pass->isChecked() ? 1 : 0; 0559 } 0560 0561 // static 0562 QString SlideshowClip::animationToGeometry(const QString &animation, int &ttl) 0563 { 0564 // load animation profiles 0565 KConfig conf(QStringLiteral("slideanimations.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation); 0566 KConfigGroup group(&conf, "slides"); 0567 QString geometry; 0568 if (group.hasKey(animation)) { 0569 geometry = group.readEntry(animation); 0570 } 0571 int frames = geometry.count(QLatin1String("%d=")); 0572 int frameNumber = ttl - 1; 0573 QString str = QStringLiteral("%d"); 0574 for (int i = 0; i < frames; i++) { 0575 geometry.replace(geometry.indexOf(str), 2, QString::number(frameNumber)); 0576 frameNumber = qFloor((i + 3) / 2) * ttl; 0577 frameNumber -= (i % 2); 0578 } 0579 return geometry; 0580 } 0581 0582 const QString SlideshowClip::extension() const 0583 { 0584 return m_view.image_type->currentData().toString(); 0585 }