X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fprojectlist.cpp;h=1b3dcacec6b88cd3ffa10108eff0701f2706e10c;hb=71689ab468fa0f9e798c5895c34d849c2c7705d4;hp=6c77cd7e69d5efe8c881f7819887628307d7e158;hpb=e286ff4854296be6f007ee4c484207777fb261b0;p=kdenlive diff --git a/src/projectlist.cpp b/src/projectlist.cpp index 6c77cd7e..1b3dcace 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -44,6 +44,7 @@ #include "ui_templateclip_ui.h" #include "ui_cutjobdialog_ui.h" +#include "ui_scenecutdialog_ui.h" #include #include @@ -58,6 +59,8 @@ #include #include #include +#include +#include #ifdef USE_NEPOMUK #include @@ -77,6 +80,17 @@ #include #include #include +#include + + +MyMessageWidget::MyMessageWidget(QWidget *parent) : KMessageWidget(parent) {} +MyMessageWidget::MyMessageWidget(const QString &text, QWidget *parent) : KMessageWidget(text, parent) {} + + +bool MyMessageWidget::event(QEvent* ev) { + if (ev->type() == QEvent::Hide || ev->type() == QEvent::Close) emit messageClosing(); + return KMessageWidget::event(ev); +} SmallInfoLabel::SmallInfoLabel(QWidget *parent) : QPushButton(parent) { @@ -278,10 +292,11 @@ ProjectList::ProjectList(QWidget *parent) : m_listView = new ProjectListView(this); layout->addWidget(m_listView); -#if KDE_IS_VERSION(4,7,0) - m_infoMessage = new KMessageWidget; +#if KDE_IS_VERSION(4,7,0) + m_infoMessage = new MyMessageWidget; layout->addWidget(m_infoMessage); m_infoMessage->setCloseButtonVisible(true); + connect(m_infoMessage, SIGNAL(messageClosing()), this, SLOT(slotResetInfoMessage())); //m_infoMessage->setWordWrap(true); m_infoMessage->hide(); m_logAction = new QAction(i18n("Show Log"), this); @@ -295,9 +310,10 @@ ProjectList::ProjectList(QWidget *parent) : connect(this, SIGNAL(processNextThumbnail()), this, SLOT(slotProcessNextThumbnail())); connect(m_listView, SIGNAL(projectModified()), this, SIGNAL(projectModified())); connect(m_listView, SIGNAL(itemSelectionChanged()), this, SLOT(slotClipSelected())); - connect(m_listView, SIGNAL(focusMonitor()), this, SIGNAL(raiseClipMonitor())); - connect(m_listView, SIGNAL(pauseMonitor()), this, SLOT(slotPauseMonitor())); + connect(m_listView, SIGNAL(focusMonitor(bool)), this, SIGNAL(raiseClipMonitor(bool))); + connect(m_listView, SIGNAL(pauseMonitor()), this, SIGNAL(pauseMonitor())); connect(m_listView, SIGNAL(requestMenu(const QPoint &, QTreeWidgetItem *)), this, SLOT(slotContextMenu(const QPoint &, QTreeWidgetItem *))); + connect(m_listView, SIGNAL(addClip()), this, SIGNAL(pauseMonitor())); connect(m_listView, SIGNAL(addClip()), this, SLOT(slotAddClip())); connect(m_listView, SIGNAL(addClip(const QList , const QString &, const QString &)), this, SLOT(slotAddClip(const QList , const QString &, const QString &))); connect(this, SIGNAL(addClip(const QString, const QString &, const QString &)), this, SLOT(slotAddClip(const QString, const QString &, const QString &))); @@ -410,8 +426,8 @@ void ProjectList::setupGeneratorMenu(const QHash& menus) transcodeMenu->setEnabled(false); m_transcodeAction = transcodeMenu; } - if (menus.contains("stabilizeMenu") && menus.value("stabilizeMenu") ){ - QMenu* stabilizeMenu=menus.value("stabilizeMenu"); + if (menus.contains("clipActionsMenu") && menus.value("clipActionsMenu") ){ + QMenu* stabilizeMenu=menus.value("clipActionsMenu"); m_menu->addMenu(stabilizeMenu); if (stabilizeMenu->isEmpty()) stabilizeMenu->setEnabled(false); @@ -518,7 +534,7 @@ void ProjectList::editClipSelection(QList list) if (clip->getProperty("transparency").isEmpty() || clip->getProperty("transparency").toInt() == 0) { if (transparency == "-") { // first non transparent image - transparency = "0"; + transparency = '0'; } else if (transparency == "1") { // we have transparent and non transparent clips @@ -528,7 +544,7 @@ void ProjectList::editClipSelection(QList list) else { if (transparency == "-") { // first transparent image - transparency = "1"; + transparency = '1'; } else if (transparency == "0") { // we have transparent and non transparent clips @@ -571,7 +587,7 @@ void ProjectList::editClipSelection(QList list) kDebug() << "Result: " << p.key() << " = " << p.value(); }*/ if (clipList.isEmpty()) { - emit displayMessage(i18n("No available clip selected"), -2); + emit displayMessage(i18n("No available clip selected"), -2); } else emit showClipProperties(clipList, commonproperties); } @@ -733,6 +749,10 @@ void ProjectList::slotMissingClip(const QString &id) if (item) { item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled); int height = m_listView->iconSize().height(); + if (m_render == NULL) { + kDebug() << "********* ERROR, NULL RENDR"; + return; + } int width = (int)(height * m_render->dar()); QPixmap pixmap = qVariantValue(item->data(0, Qt::DecorationRole)); if (pixmap.isNull()) { @@ -746,10 +766,6 @@ void ProjectList::slotMissingClip(const QString &id) item->setData(0, Qt::DecorationRole, pixmap); if (item->referencedClip()) { item->referencedClip()->setPlaceHolder(true); - if (m_render == NULL) { - kDebug() << "********* ERROR, NULL RENDR"; - return; - } Mlt::Producer *newProd = m_render->invalidProducer(id); if (item->referencedClip()->getProducer()) { Mlt::Properties props(newProd->get_properties()); @@ -888,7 +904,7 @@ void ProjectList::adjustProxyActions(ProjectItem *clip) const void ProjectList::adjustStabilizeActions(ProjectItem *clip) const { - if (clip == NULL || clip->type() != PROJECTCLIPTYPE || clip->clipType() == COLOR || clip->clipType() == TEXT || clip->clipType() == PLAYLIST || clip->clipType() == SLIDESHOW) { + if (clip == NULL || clip->type() != PROJECTCLIPTYPE || clip->clipType() == COLOR || clip->clipType() == TEXT || clip->clipType() == SLIDESHOW) { m_stabilizeAction->setEnabled(false); return; } @@ -932,16 +948,17 @@ void ProjectList::slotUpdateClipProperties(const QString &id, QMap setEnabled(false); const QString parent = clip->getProperty("groupid"); + QString groupName = clip->getProperty("groupname"); ProjectItem *item = NULL; monitorItemEditing(false); if (!parent.isEmpty()) { FolderProjectItem *parentitem = getFolderItemById(parent); if (!parentitem) { QStringList text; - QString groupName = clip->getProperty("groupname"); //kDebug() << "Adding clip to new group: " << groupName; if (groupName.isEmpty()) groupName = i18n("Folder"); text << groupName; @@ -1307,6 +1324,10 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties) //item->setFlags(Qt::ItemIsSelectable); m_listView->processLayout(); QDomElement e = clip->toXML().cloneNode().toElement(); + if (!groupName.isEmpty()) { + e.setAttribute("groupId", parent); + e.setAttribute("group", groupName); + } e.removeAttribute("file_hash"); resetThumbsProducer(clip); m_render->getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true); @@ -1340,7 +1361,7 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties) QList cuts = clip->cutZones(); if (!cuts.isEmpty()) { for (int i = 0; i < cuts.count(); i++) { - SubProjectItem *sub = new SubProjectItem(item, cuts.at(i).zone.x(), cuts.at(i).zone.y(), cuts.at(i).description); + SubProjectItem *sub = new SubProjectItem(m_render->dar(), item, cuts.at(i).zone.x(), cuts.at(i).zone.y(), cuts.at(i).description); if (!clip->getClipHash().isEmpty()) { QString cachedPixmap = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "thumbs/" + clip->getClipHash() + '#' + QString::number(cuts.at(i).zone.x()) + ".png"; if (QFile::exists(cachedPixmap)) { @@ -1465,7 +1486,7 @@ void ProjectList::getCachedThumbnail(SubProjectItem *item) DocClipBase *clip = parentItem->referencedClip(); if (!clip) return; int pos = item->zone().x(); - QString cachedPixmap = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "thumbs/" + clip->getClipHash() + "#" + QString::number(pos) + ".png"; + QString cachedPixmap = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "thumbs/" + clip->getClipHash() + '#' + QString::number(pos) + ".png"; if (QFile::exists(cachedPixmap)) { QPixmap pix(cachedPixmap); if (pix.isNull()) { @@ -1598,10 +1619,16 @@ void ProjectList::updateAllClips(bool displayRatioChanged, bool fpsChanged, QStr QString ProjectList::getExtensions() { // Build list of mime types - QStringList mimeTypes = QStringList() << "application/x-kdenlive" << "application/x-kdenlivetitle" << "video/mlt-playlist" << "text/plain" - << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "video/mp4" << "video/quicktime" << "video/webm" - << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "audio/x-aiff" << "audio/aiff" << "application/ogg" << "application/mxf" << "application/x-shockwave-flash" - << "image/gif" << "image/jpeg" << "image/png" << "image/x-tga" << "image/x-bmp" << "image/svg+xml" << "image/tiff" << "image/x-xcf" << "image/x-xcf-gimp" << "image/x-vnd.adobe.photoshop" << "image/x-pcx" << "image/x-exr"; + QStringList mimeTypes = QStringList() << "application/x-kdenlive" << "application/x-kdenlivetitle" << "video/mlt-playlist" << "text/plain"; + + // Video mimes + mimeTypes << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "video/mp4" << "video/quicktime" << "video/webm" << "video/3gpp" << "video/mp2t"; + + // Audio mimes + mimeTypes << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "audio/x-aiff" << "audio/aiff" << "application/ogg" << "application/mxf" << "application/x-shockwave-flash" << "audio/ac3"; + + // Image mimes + mimeTypes << "image/gif" << "image/jpeg" << "image/png" << "image/x-tga" << "image/x-bmp" << "image/svg+xml" << "image/tiff" << "image/x-xcf" << "image/x-xcf-gimp" << "image/x-vnd.adobe.photoshop" << "image/x-pcx" << "image/x-exr"; QString allExtensions; foreach(const QString & mimeType, mimeTypes) { @@ -1713,9 +1740,15 @@ void ProjectList::slotAddClip(const QList givenList, const QString &group if (givenList.isEmpty() && !list.isEmpty()) { QStringList groupInfo = getGroup(); - m_doc->slotAddClipList(list, groupInfo.at(0), groupInfo.at(1)); + QMap data; + data.insert("group", groupInfo.at(0)); + data.insert("groupId", groupInfo.at(1)); + m_doc->slotAddClipList(list, data); } else if (!list.isEmpty()) { - m_doc->slotAddClipList(list, groupName, groupId); + QMap data; + data.insert("group", groupName); + data.insert("groupId", groupId); + m_doc->slotAddClipList(list, data); } if (!foldersList.isEmpty()) { @@ -1732,8 +1765,12 @@ void ProjectList::slotAddClip(const QList givenList, const QString &group folder = getFolderItemByName(folderName); } } - if (folder) - m_doc->slotAddClipList(urls, folder->groupName(), folder->clipId()); + if (folder) { + QMap data; + data.insert("group", folder->groupName()); + data.insert("groupId", folder->clipId()); + m_doc->slotAddClipList(urls, data); + } else m_doc->slotAddClipList(urls); } } @@ -1965,6 +2002,23 @@ void ProjectList::setDocument(KdenliveDoc *doc) connect(m_doc->clipManager(), SIGNAL(missingClip(const QString &)), this, SLOT(slotMissingClip(const QString &))); connect(m_doc->clipManager(), SIGNAL(availableClip(const QString &)), this, SLOT(slotAvailableClip(const QString &))); connect(m_doc->clipManager(), SIGNAL(checkAllClips(bool, bool, QStringList)), this, SLOT(updateAllClips(bool, bool, QStringList))); + connect(m_doc->clipManager(), SIGNAL(thumbReady(const QString &, int, QImage)), this, SLOT(slotSetThumbnail(const QString &, int, QImage))); +} + +void ProjectList::slotSetThumbnail(const QString &id, int framePos, QImage img) +{ + QString fullid = id + '#' + QString::number(framePos); + ProjectItem *pItem = NULL; + QTreeWidgetItem *item = getAnyItemById(fullid); + if (item && item->parent()) pItem = static_cast (item->parent()); + if (!item && framePos == 0) pItem = getItemById(id); + if (!item && !pItem) return; + if (item) item->setData(0, Qt::DecorationRole, QPixmap::fromImage(img)); + else if (pItem) pItem->setData(0, Qt::DecorationRole, QPixmap::fromImage(img)); + if (pItem) { + QString hash = pItem->getClipHash(); + if (!hash.isEmpty()) m_doc->cacheImage(hash + '#' + QString::number(framePos), img); + } } QList ProjectList::documentClipList() const @@ -2077,12 +2131,12 @@ void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update) int dwidth = (int)(height * m_render->dar() + 0.5); if (clip->clipType() == AUDIO) pix = KIcon("audio-x-generic").pixmap(QSize(dwidth, height)); - else if (clip->clipType() == IMAGE) + else if (clip->clipType() == IMAGE) { img = KThumb::getFrame(item->referencedClip()->getProducer(), 0, swidth, dwidth, height); + } else { img = item->referencedClip()->extractImage(frame, dwidth, height); } - if (!pix.isNull() || !img.isNull()) { monitorItemEditing(false); if (!img.isNull()) { @@ -2145,7 +2199,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce if (clip->getProperty("proxy").isEmpty()) { KUrl proxyPath = m_doc->projectFolder(); proxyPath.addPath("proxy/"); - proxyPath.addPath(clip->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"))); + proxyPath.addPath(clip->getClipHash() + '.' + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"))); QMap newProps; // insert required duration for proxy if (t != IMAGE) newProps.insert("proxy_out", clip->producerProperty("out")); @@ -2281,7 +2335,15 @@ void ProjectList::slotReplyGetImage(const QString &clipId, const QImage &img) { ProjectItem *item = getItemById(clipId); if (item && !img.isNull()) { - QPixmap pix = QPixmap::fromImage(img); + QPixmap pix(img.width(), img.height()); + pix.fill(Qt::transparent); + QPainter p(&pix); + p.setRenderHint(QPainter::Antialiasing, true); + QPainterPath path; + path.addRoundedRect(0.5, 0.5, pix.width() - 1, pix.height() - 1, 2, 2); + p.setClipPath(path); + p.drawImage(0, 0, img); + p.end(); processThumbOverlays(item, pix); monitorItemEditing(false); item->setData(0, Qt::DecorationRole, pix); @@ -2532,17 +2594,14 @@ void ProjectList::addClipCut(const QString &id, int in, int out, const QString d DocClipBase *base = clip->referencedClip(); base->addCutZone(in, out); monitorItemEditing(false); - SubProjectItem *sub = new SubProjectItem(clip, in, out, desc); + SubProjectItem *sub = new SubProjectItem(m_render->dar(), clip, in, out, desc); if (newItem && desc.isEmpty() && !m_listView->isColumnHidden(1)) { if (!clip->isExpanded()) clip->setExpanded(true); m_listView->scrollToItem(sub); m_listView->editItem(sub, 1); } - QImage img = clip->referencedClip()->extractImage(in, (int)(sub->sizeHint(0).height() * m_render->dar()), sub->sizeHint(0).height() - 2); - sub->setData(0, Qt::DecorationRole, QPixmap::fromImage(img)); - QString hash = clip->getClipHash(); - if (!hash.isEmpty()) m_doc->cacheImage(hash + '#' + QString::number(in), img); + m_doc->clipManager()->requestThumbs(QString('#' + id), QList () << in); monitorItemEditing(true); } emit projectModified(); @@ -2690,8 +2749,12 @@ void ProjectList::slotCreateProxy(const QString id) slotGotProxy(path); return; } - - ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << item->clipUrl().path() << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight())); + QString sourcePath = item->clipUrl().path(); + if (item->clipType() == PLAYLIST) { + // Special case: playlists use the special 'consumer' producer to support resizing + sourcePath.prepend("consumer:"); + } + ProxyJob *job = new ProxyJob(item->clipType(), id, QStringList() << path << sourcePath << item->referencedClip()->producerProperty("_exif_orientation") << m_doc->getDocumentProperty("proxyparams").simplified() << QString::number(m_render->frameRenderWidth()) << QString::number(m_render->renderHeight())); if (job->isExclusive() && hasPendingJob(item, job->jobType)) { delete job; return; @@ -2708,7 +2771,7 @@ void ProjectList::slotCutClipJob(const QString &id, QPoint zone) if (!item|| item->referencedClip()->isPlaceHolder()) return; QString source = item->clipUrl().path(); QString ext = source.section('.', -1); - QString dest = source.section('.', 0, -2) + "_" + QString::number(zone.x()) + "." + ext; + QString dest = source.section('.', 0, -2) + '_' + QString::number(zone.x()) + '.' + ext; double clipFps = item->referencedClip()->getProperty("fps").toDouble(); if (clipFps == 0) clipFps = m_fps; @@ -2726,7 +2789,7 @@ void ProjectList::slotCutClipJob(const QString &id, QPoint zone) Ui::CutJobDialog_UI ui; ui.setupUi(d); ui.extra_params->setVisible(false); - ui.add_clip->setChecked(KdenliveSettings::add_clip_cut()); + ui.add_clip->setChecked(KdenliveSettings::add_new_clip()); ui.file_url->fileDialog()->setOperationMode(KFileDialog::Saving); ui.extra_params->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5); ui.file_url->setUrl(KUrl(dest)); @@ -2759,11 +2822,11 @@ void ProjectList::slotCutClipJob(const QString &id, QPoint zone) } } QString extraParams = ui.extra_params->toPlainText().simplified(); - KdenliveSettings::setAdd_clip_cut(ui.add_clip->isChecked()); + KdenliveSettings::setAdd_new_clip(ui.add_clip->isChecked()); delete d; QStringList jobParams; - jobParams << dest << item->clipUrl().path() << timeIn << timeOut << QString::number(duration) << QString::number(KdenliveSettings::add_clip_cut()); + jobParams << dest << item->clipUrl().path() << timeIn << timeOut << QString::number(duration) << QString::number(KdenliveSettings::add_new_clip()); if (!extraParams.isEmpty()) jobParams << extraParams; CutClipJob *job = new CutClipJob(item->clipType(), id, jobParams); if (job->isExclusive() && hasPendingJob(item, job->jobType)) { @@ -2807,24 +2870,27 @@ void ProjectList::slotTranscodeClipJob(const QString &condition, QString params, ui.extra_params->setVisible(false); d->adjustSize(); ui.button_more->setIcon(KIcon("configure")); - ui.add_clip->setChecked(KdenliveSettings::add_clip_cut()); - ui.extra_params->setPlainText(params.simplified().section(" ", 0, -2)); + ui.add_clip->setChecked(KdenliveSettings::add_new_clip()); + ui.extra_params->setPlainText(params.simplified().section(' ', 0, -2)); QString mess = desc; - mess.append(" " + i18np("(%1 clip)", "(%1 clips)", ids.count())); + mess.append(' ' + i18np("(%1 clip)", "(%1 clips)", ids.count())); ui.info_label->setText(mess); if (d->exec() != QDialog::Accepted) { delete d; return; } params = ui.extra_params->toPlainText().simplified(); - KdenliveSettings::setAdd_clip_cut(ui.add_clip->isChecked()); - + KdenliveSettings::setAdd_new_clip(ui.add_clip->isChecked()); + int index = 0; foreach(const QString &id, ids) { ProjectItem *item = getItemById(id); if (!item || !item->referencedClip()) continue; QString src = item->clipUrl().path(); QString dest; - if (ids.count() > 1) dest = params.section(' ', -1).replace("%1", src); + if (ids.count() > 1) { + dest = destinations.at(index); + index++; + } else dest = ui.file_url->url().path(); QStringList jobParams; jobParams << dest << src << QString() << QString(); @@ -2833,7 +2899,7 @@ void ProjectList::slotTranscodeClipJob(const QString &condition, QString params, int max = item->clipMaxDuration(); QString duration = QString::number(max); jobParams << duration; - jobParams << QString::number(KdenliveSettings::add_clip_cut()); + jobParams << QString::number(KdenliveSettings::add_new_clip()); jobParams << params; CutClipJob *job = new CutClipJob(item->clipType(), id, jobParams); if (job->isExclusive() && hasPendingJob(item, job->jobType)) { @@ -2939,11 +3005,14 @@ void ProjectList::slotProcessJobs() } connect(job, SIGNAL(jobProgress(QString, int, int)), this, SIGNAL(processLog(QString, int, int))); connect(job, SIGNAL(cancelRunningJob(const QString, stringMap)), this, SIGNAL(cancelRunningJob(const QString, stringMap))); - connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap))); if (job->jobType == MLTJOB) { MeltJob *jb = static_cast (job); - jb->setProducer(currentClip->getProducer()); + jb->setProducer(currentClip->getProducer(), currentClip->fileURL()); + if (jb->isProjectFilter()) + connect(job, SIGNAL(gotFilterJobResults(QString,int, int, stringMap,stringMap)), this, SLOT(slotGotFilterJobResults(QString,int, int,stringMap,stringMap))); + else + connect(job, SIGNAL(gotFilterJobResults(QString,int, int, stringMap,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int,stringMap,stringMap))); } job->startJob(); if (job->jobStatus == JOBDONE) { @@ -2989,7 +3058,7 @@ void ProjectList::updateProxyConfig() QMap oldProps;// = clip->properties(); oldProps.insert("proxy", QString()); QMap newProps; - newProps.insert("proxy", proxydir + item->referencedClip()->getClipHash() + "." + m_doc->getDocumentProperty("proxyextension")); + newProps.insert("proxy", proxydir + item->referencedClip()->getClipHash() + '.' + m_doc->getDocumentProperty("proxyextension")); new EditClipCommand(this, clip->getId(), oldProps, newProps, true, command); } } @@ -3093,7 +3162,7 @@ void ProjectList::slotProxyCurrentItem(bool doProxy, ProjectItem *itemToProxy) //oldProps = clip->properties(); if (doProxy) { newProps.clear(); - QString path = proxydir + clip->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension")); + QString path = proxydir + clip->getClipHash() + '.' + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension")); // insert required duration for proxy newProps.insert("proxy_out", clip->producerProperty("out")); newProps.insert("proxy", path); @@ -3287,14 +3356,11 @@ void ProjectList::slotUpdateJobStatus(ProjectItem *item, int type, int status, c item->setJobStatus((JOBTYPE) type, (CLIPJOBSTATUS) status); if (status != JOBCRASHED) return; #if KDE_IS_VERSION(4,7,0) - m_infoMessage->animatedHide(); - m_errorLog.clear(); - m_infoMessage->setText(label); - m_infoMessage->setWordWrap(label.length() > 35); - m_infoMessage->setMessageType(KMessageWidget::Warning); QList actions = m_infoMessage->actions(); - for (int i = 0; i < actions.count(); i++) { - m_infoMessage->removeAction(actions.at(i)); + if (m_infoMessage->isHidden()) { + m_infoMessage->setText(label); + m_infoMessage->setWordWrap(m_infoMessage->text().length() > 35); + m_infoMessage->setMessageType(KMessageWidget::Warning); } if (!actionName.isEmpty()) { @@ -3305,27 +3371,47 @@ void ProjectList::slotUpdateJobStatus(ProjectItem *item, int type, int status, c action = coll->action(actionName); if (action) break; } - if (action) m_infoMessage->addAction(action); + if (action && !actions.contains(action)) m_infoMessage->addAction(action); } if (!details.isEmpty()) { - m_errorLog = details; - m_infoMessage->addAction(m_logAction); + m_errorLog.append(details); + if (!actions.contains(m_logAction)) m_infoMessage->addAction(m_logAction); } m_infoMessage->animatedShow(); +#else + // warning for KDE < 4.7 + KPassivePopup *passivePop = new KPassivePopup( this ); + passivePop->setAutoDelete(true); + connect(passivePop, SIGNAL(clicked()), this, SLOT(slotClosePopup())); + m_errorLog.append(details); + KVBox *vb = new KVBox( passivePop ); + KHBox *vh1 = new KHBox( vb ); + KIcon icon("dialog-warning"); + QLabel *iconLabel = new QLabel(vh1); + iconLabel->setPixmap(icon.pixmap(m_listView->iconSize())); + (void) new QLabel( label, vh1); + KHBox *box = new KHBox( vb ); + QPushButton *but = new QPushButton( "Show log", box ); + connect(but, SIGNAL(clicked(bool)), this, SLOT(slotShowJobLog())); + + passivePop->setView( vb ); + passivePop->show(); + #endif } void ProjectList::slotShowJobLog() { -#if KDE_IS_VERSION(4,7,0) KDialog d(this); d.setButtons(KDialog::Close); QTextEdit t(&d); - t.setPlainText(m_errorLog); + for (int i = 0; i < m_errorLog.count(); i++) { + if (i > 0) t.insertHtml("


"); + t.insertPlainText(m_errorLog.at(i)); + } t.setReadOnly(true); d.setMainWidget(&t); d.exec(); -#endif } QStringList ProjectList::getPendingJobs(const QString &id) @@ -3351,19 +3437,19 @@ void ProjectList::discardJobs(const QString &id, JOBTYPE type) { } } -void ProjectList::slotStartFilterJob(ItemInfo info, const QString&id, const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties) +void ProjectList::slotStartFilterJob(ItemInfo info, const QString&id, const QString&filterName, const QString&filterParams, const QString&consumer, const QString&consumerParams, const QMap &extraParams) { ProjectItem *item = getItemById(id); if (!item) return; QStringList jobParams; jobParams << QString::number(info.cropStart.frames(m_fps)) << QString::number((info.cropStart + info.cropDuration).frames(m_fps)); - jobParams << QString() << filterName << filterParams << consumer << consumerParams << properties << QString::number(info.startPos.frames(m_fps)) << QString::number(info.track) << finalFilterName; - MeltJob *job = new MeltJob(item->clipType(), id, jobParams); + jobParams << QString() << filterName << filterParams << consumer << consumerParams << QString::number(info.startPos.frames(m_fps)) << QString::number(info.track); + MeltJob *job = new MeltJob(item->clipType(), id, jobParams, extraParams); if (job->isExclusive() && hasPendingJob(item, job->jobType)) { delete job; return; } - job->description = i18n("Filter %1", finalFilterName); + job->description = i18n("Filter %1", extraParams.value("finalfilter")); m_jobList.append(job); setJobStatus(item, job->jobType, JOBWAITING, 0, job->statusMessage()); slotCheckJobProcess(); @@ -3384,14 +3470,55 @@ void ProjectList::startClipFilterJob(const QString &filterName, const QString &c else { destination = item->clipUrl().directory(); } - QPointer d = new ClipStabilize(destination, ids.count(), filterName); - if (d->exec() == QDialog::Accepted) { - processClipJob(ids, d->destination(), d->autoAddClip(), d->params(), d->desc()); + if (filterName == "motion_est") { + // Show config dialog + QPointer d = new QDialog(this); + Ui::SceneCutDialog_UI ui; + ui.setupUi(d); + // Set up categories + for (int i = 0; i < 5; ++i) { + ui.marker_type->insertItem(i, i18n("Category %1", i)); + ui.marker_type->setItemData(i, CommentedTime::markerColor(i), Qt::DecorationRole); + } + ui.marker_type->setCurrentIndex(KdenliveSettings::default_marker_type()); + if (d->exec() != QDialog::Accepted) { + delete d; + return; + } + // Autosplit filter + QStringList jobParams; + // Producer params + jobParams << QString(); + // Filter params, use a smaller region of the image to speed up operation + jobParams << filterName << "bounding=\"25%x25%:25%x25\" shot_change_list=0"; + // Consumer + jobParams << "null" << "all=1 terminate_on_pause=1 real_time=-1"; + QMap extraParams; + extraParams.insert("key", "shot_change_list"); + extraParams.insert("projecttreefilter", "1"); + if (ui.add_markers->isChecked()) { + // We want to create markers + extraParams.insert("addmarkers", QString::number(ui.marker_type->currentIndex())); + } + if (ui.cut_scenes->isChecked()) { + // We want to cut scenes + extraParams.insert("cutscenes", "1"); + } + delete d; + processClipJob(ids, QString(), false, jobParams, i18n("Auto split"), extraParams); + } + else { + QPointer d = new ClipStabilize(destination, ids.count(), filterName); + if (d->exec() == QDialog::Accepted) { + QMap extraParams; + extraParams.insert("producer_profile", "1"); + processClipJob(ids, d->destination(), d->autoAddClip(), d->params(), d->desc(), extraParams); + } + delete d; } - delete d; } -void ProjectList::processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description) +void ProjectList::processClipJob(QStringList ids, const QString&destination, bool autoAdd, QStringList jobParams, const QString &description, QMap extraParams) { QStringList preParams; // in and out @@ -3408,20 +3535,23 @@ void ProjectList::processClipJob(QStringList ids, const QString&destination, boo foreach(const QString&id, ids) { ProjectItem *item = getItemById(id); if (!item) continue; + QStringList jobArgs; + jobArgs << preParams; if (ids.count() == 1) { - consumer += ":" + destination; + jobArgs << consumer + ':' + destination; } else { - consumer += ":" + destination + item->clipUrl().fileName() + ".mlt"; + jobArgs << consumer + ':' + destination + item->clipUrl().fileName() + ".mlt"; } - preParams << consumer << jobParams; + jobArgs << jobParams; - MeltJob *job = new MeltJob(item->clipType(), id, preParams); + MeltJob *job = new MeltJob(item->clipType(), id, jobArgs, extraParams); if (autoAdd) { job->setAddClipToProject(true); kDebug()<<"// ADDING TRUE"; } else kDebug()<<"// ADDING FALSE!!!"; + if (job->isExclusive() && hasPendingJob(item, job->jobType)) { delete job; return; @@ -3466,4 +3596,84 @@ void ProjectList::updatePalette() m_listView->updateStyleSheet(); } +void ProjectList::slotResetInfoMessage() +{ +#if KDE_IS_VERSION(4,7,0) + m_errorLog.clear(); + QList actions = m_infoMessage->actions(); + for (int i = 0; i < actions.count(); i++) { + m_infoMessage->removeAction(actions.at(i)); + } +#endif +} + +void ProjectList::slotClosePopup() +{ + m_errorLog.clear(); +} + +void ProjectList::slotGotFilterJobResults(QString id, int , int , stringMap results, stringMap filterInfo) +{ + // Currently, only the first value of results is used + kDebug()<<"// FILTER RES:\n"<setText(i18n("Auto Split Clip")); + foreach (QString pos, value) { + if (!pos.contains("=")) continue; + int newPos = pos.section("=", 0, 0).toInt(); + // Don't use scenes shorter than 1 second + if (newPos - cutPos < 24) continue; + (void) new AddClipCutCommand(this, id, cutPos, newPos, QString(), true, false, command); + cutPos = newPos; + } + if (command->childCount() == 0) + delete command; + else m_commandStack->push(command); + } + if (markersType >= 0) { + // Add markers from returned data + dataProcessed = true; + int cutPos = 0; + QUndoCommand *command = new QUndoCommand(); + command->setText(i18n("Add Markers")); + QList markersList; + int index = 1; + foreach (QString pos, value) { + if (!pos.contains("=")) continue; + int newPos = pos.section("=", 0, 0).toInt(); + // Don't use scenes shorter than 1 second + if (newPos - cutPos < 24) continue; + CommentedTime m(GenTime(newPos, m_fps), QString::number(index), markersType); + markersList << m; + index++; + cutPos = newPos; + } + emit addMarkers(id, markersList); + } + if (!dataProcessed || filterInfo.contains("storedata")) { + // Store returned data as clip extra data + clip->referencedClip()->setAnalysisData(filterInfo.contains("displaydataname") ? filterInfo.value("displaydataname") : key, results.value(key)); + emit updateAnalysisData(clip->referencedClip()); + } +} + + #include "projectlist.moc"