From: Jean-Baptiste Mardelle Date: Mon, 13 Jun 2011 19:38:17 +0000 (+0000) Subject: Check for clip duration mismatch on project opening X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=28f706cb03057ab961c38e4e4c817c3d9cd6e7f2;p=kdenlive Check for clip duration mismatch on project opening svn path=/trunk/kdenlive/; revision=5711 --- diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index f7b88493..a0c11e5c 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -511,8 +511,8 @@ void DocClipBase::setProducer(Mlt::Producer *producer, bool reset, bool readProp updated = true; } } - if (updated && readPropertiesFromProducer) - setDuration(GenTime(producer->get_length(), KdenliveSettings::project_fps())); + if (updated && readPropertiesFromProducer && (m_clipType != COLOR && m_clipType != IMAGE && m_clipType != TEXT)) + setDuration(GenTime(producer->get_length(), KdenliveSettings::project_fps())); //m_clipProducer = producer; //m_clipProducer->set("transparency", m_properties.value("transparency").toInt()); } diff --git a/src/documentchecker.cpp b/src/documentchecker.cpp index a9981711..a43378e7 100644 --- a/src/documentchecker.cpp +++ b/src/documentchecker.cpp @@ -52,6 +52,8 @@ const int typeOriginalResource = Qt::UserRole + 5; const int CLIPMISSING = 0; const int CLIPOK = 1; const int CLIPPLACEHOLDER = 2; +const int CLIPWRONGDURATION = 3; + const int LUMAMISSING = 10; const int LUMAOK = 11; const int LUMAPLACEHOLDER = 12; @@ -65,17 +67,39 @@ DocumentChecker::DocumentChecker(QDomNodeList infoproducers, QDomDocument doc): } -bool DocumentChecker::hasMissingClips() +bool DocumentChecker::hasErrorInClips() { int clipType; QDomElement e; - QString id; QString resource; + QDomNodeList documentProducers = m_doc.elementsByTagName("producer"); + QList wrongDurationClips; QList missingClips; for (int i = 0; i < m_info.count(); i++) { e = m_info.item(i).toElement(); clipType = e.attribute("type").toInt(); if (clipType == COLOR) continue; + if (clipType != TEXT && clipType != IMAGE) { + QString id = e.attribute("id"); + int duration = e.attribute("duration").toInt(); + // Check that the duration is in sync between Kdenlive's info and MLT's playlist + for (int j = 0; j < documentProducers.count(); j++) { + QDomElement mltProd = documentProducers.at(j).toElement(); + QString prodId = mltProd.attribute("id"); + // Don't check slowmotion clips for now... (TODO?) + if (prodId.startsWith("slowmotion")) continue; + if (prodId.contains("_")) prodId = prodId.section("_", 0, 0); + if (prodId != id) continue; + int mltDuration = mltProd.attribute("out").toInt() + 1; + if (mltDuration != duration && !e.hasAttribute("_mismatch")) { + // Duration mismatch + e.setAttribute("_mismatch", mltDuration); + if (!wrongDurationClips.contains(e)) wrongDurationClips.append(e); + kDebug() << "WRONG DURTAION: "<setData(0, typeRole, t); item->setData(0, idRole, e.attribute("id")); + item->setToolTip(0, i18n("Missing item")); + } + + if (missingClips.count() > 0) { + if (wrongDurationClips.count() > 0) { + m_ui.infoLabel->setText(i18n("The project file contains missing clips or files and clip duration mismatch")); + } + else { + m_ui.infoLabel->setText(i18n("The project file contains missing clips or files")); + } + } + else if (wrongDurationClips.count() > 0) { + m_ui.infoLabel->setText(i18n("The project file contains clips with duration mismatch")); } + m_ui.removeSelected->setEnabled(!missingClips.isEmpty()); + m_ui.recursiveSearch->setEnabled(!missingClips.isEmpty()); + m_ui.usePlaceholders->setEnabled(!missingClips.isEmpty()); + m_ui.fixDuration->setEnabled(!wrongDurationClips.isEmpty()); + + for (int i = 0; i < wrongDurationClips.count(); i++) { + e = wrongDurationClips.at(i).toElement(); + QString clipType; + int t = e.attribute("type").toInt(); + switch (t) { + case AV: + clipType = i18n("Video clip"); + break; + case VIDEO: + clipType = i18n("Mute video clip"); + break; + case AUDIO: + clipType = i18n("Audio clip"); + break; + case PLAYLIST: + clipType = i18n("Playlist clip"); + break; + case IMAGE: + clipType = i18n("Image clip"); + break; + case SLIDESHOW: + clipType = i18n("Slideshow clip"); + break; + default: + clipType = i18n("Video clip"); + } + QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget, QStringList() << clipType); + item->setIcon(0, KIcon("timeadjust")); + item->setText(1, e.attribute("resource")); + item->setData(0, hashRole, e.attribute("file_hash")); + item->setData(0, sizeRole, e.attribute("_mismatch")); + e.removeAttribute("_mismatch"); + item->setData(0, statusRole, CLIPWRONGDURATION); + item->setData(0, typeRole, t); + item->setData(0, idRole, e.attribute("id")); + item->setToolTip(0, i18n("Duration mismatch")); + } + connect(m_ui.recursiveSearch, SIGNAL(pressed()), this, SLOT(slotSearchClips())); connect(m_ui.usePlaceholders, SIGNAL(pressed()), this, SLOT(slotPlaceholders())); connect(m_ui.removeSelected, SIGNAL(pressed()), this, SLOT(slotDeleteSelected())); + connect(m_ui.fixDuration, SIGNAL(pressed()), this, SLOT(slotFixDuration())); connect(m_ui.treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotEditItem(QTreeWidgetItem *, int))); connect(m_ui.treeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(slotCheckButtons())); //adjustSize(); @@ -230,12 +310,14 @@ void DocumentChecker::slotSearchClips() QString newpath = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///clipfolder"), kapp->activeWindow(), i18n("Clips folder")); if (newpath.isEmpty()) return; int ix = 0; + bool fixed = false; m_ui.recursiveSearch->setEnabled(false); QTreeWidgetItem *child = m_ui.treeWidget->topLevelItem(ix); while (child) { if (child->data(0, statusRole).toInt() == CLIPMISSING) { QString clipPath = searchFileRecursively(QDir(newpath), child->data(0, sizeRole).toString(), child->data(0, hashRole).toString()); if (!clipPath.isEmpty()) { + fixed = true; child->setText(1, clipPath); child->setIcon(0, KIcon("dialog-ok")); child->setData(0, statusRole, CLIPOK); @@ -243,6 +325,7 @@ void DocumentChecker::slotSearchClips() } else if (child->data(0, statusRole).toInt() == LUMAMISSING) { QString fileName = searchLuma(child->data(0, idRole).toString()); if (!fileName.isEmpty()) { + fixed = true; child->setText(1, fileName); child->setIcon(0, KIcon("dialog-ok")); child->setData(0, statusRole, LUMAOK); @@ -252,6 +335,12 @@ void DocumentChecker::slotSearchClips() child = m_ui.treeWidget->topLevelItem(ix); } m_ui.recursiveSearch->setEnabled(true); + if (fixed) { + // original doc was modified + QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); + QDomElement infoXml = infoXmlNode.toElement(); + infoXml.setAttribute("modified", "1"); + } checkStatus(); } @@ -460,6 +549,33 @@ void DocumentChecker::slotPlaceholders() checkStatus(); } +void DocumentChecker::slotFixDuration() +{ + int ix = 0; + QTreeWidgetItem *child = m_ui.treeWidget->topLevelItem(ix); + while (child) { + if (child->data(0, statusRole).toInt() == CLIPWRONGDURATION) { + child->setData(0, statusRole, CLIPOK); + child->setIcon(0, KIcon("dialog-ok")); + QString id = child->data(0, idRole).toString(); + for (int i = 0; i < m_info.count(); i++) { + QDomElement e = m_info.at(i).toElement(); + if (e.attribute("id") == id) { + e.setAttribute("duration", child->data(0, sizeRole).toString()); + break; + } + } + } + ix++; + child = m_ui.treeWidget->topLevelItem(ix); + } + QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); + QDomElement infoXml = infoXmlNode.toElement(); + infoXml.setAttribute("modified", "1"); + m_ui.fixDuration->setEnabled(false); + checkStatus(); +} + void DocumentChecker::checkStatus() { @@ -467,7 +583,8 @@ void DocumentChecker::checkStatus() int ix = 0; QTreeWidgetItem *child = m_ui.treeWidget->topLevelItem(ix); while (child) { - if (child->data(0, statusRole).toInt() == CLIPMISSING || child->data(0, statusRole).toInt() == LUMAMISSING) { + int status = child->data(0, statusRole).toInt(); + if (status == CLIPMISSING || status == LUMAMISSING || status == CLIPWRONGDURATION) { status = false; break; } @@ -536,6 +653,9 @@ void DocumentChecker::slotDeleteSelected() } } } + QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); + QDomElement infoXml = infoXmlNode.toElement(); + infoXml.setAttribute("modified", "1"); checkStatus(); } } diff --git a/src/documentchecker.h b/src/documentchecker.h index 4994579f..dd77cf20 100644 --- a/src/documentchecker.h +++ b/src/documentchecker.h @@ -36,7 +36,7 @@ class DocumentChecker: public QObject public: explicit DocumentChecker(QDomNodeList infoproducers, QDomDocument doc); ~DocumentChecker(); - bool hasMissingClips(); + bool hasErrorInClips(); private slots: void acceptDialog(); @@ -49,6 +49,8 @@ private slots: QString searchLuma(QString file) const; void checkMissingImages(QList &missingClips, QStringList images, QStringList fonts, QString id, QString baseClip); void slotCheckButtons(); + /** @brief Fix duration mismatch issues. */ + void slotFixDuration(); private: QDomNodeList m_info; diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index cfd2a31c..229c4e02 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -1357,7 +1357,7 @@ QString KdenliveDoc::getLadspaFile() const bool KdenliveDoc::checkDocumentClips(QDomNodeList infoproducers) { DocumentChecker d(infoproducers, m_document); - return (d.hasMissingClips() == false); + return (d.hasErrorInClips() == false); /* int clipType; QDomElement e; diff --git a/src/trackview.cpp b/src/trackview.cpp index badcd4dc..9b187f05 100644 --- a/src/trackview.cpp +++ b/src/trackview.cpp @@ -452,7 +452,7 @@ void TrackView::parseDocument(QDomDocument doc) slotRebuildTrackHeaders(); if (!m_documentErrors.isNull()) KMessageBox::sorry(this, m_documentErrors); - if (infoXml.hasAttribute("upgraded")) { + if (infoXml.hasAttribute("upgraded") || infoXml.hasAttribute("modified")) { // Our document was upgraded, create a backup copy just in case QString baseFile = m_doc->url().path().section(".kdenlive", 0, 0); int ct = 0; @@ -461,8 +461,13 @@ void TrackView::parseDocument(QDomDocument doc) ct++; backupFile = baseFile + "_backup" + QString::number(ct) + ".kdenlive"; } + QString message; + if (infoXml.hasAttribute("upgraded")) + message = i18n("Your project file was upgraded to the latest Kdenlive document version.\nTo make sure you don't lose data, a backup copy called %1 was created.", backupFile); + else + message = i18n("Your project file was modified by Kdenlive.\nTo make sure you don't lose data, a backup copy called %1 was created.", backupFile); if (KIO::NetAccess::file_copy(m_doc->url(), KUrl(backupFile), this)) - KMessageBox::information(this, i18n("Your project file was upgraded to the latest Kdenlive document version.\nTo make sure you don't lose data, a backup copy called %1 was created.", backupFile)); + KMessageBox::information(this, message); else KMessageBox::information(this, i18n("Your project file was upgraded to the latest Kdenlive document version, but it was not possible to create a backup copy.", backupFile)); } diff --git a/src/widgets/missingclips_ui.ui b/src/widgets/missingclips_ui.ui index 903cfc83..6cd8c358 100644 --- a/src/widgets/missingclips_ui.ui +++ b/src/widgets/missingclips_ui.ui @@ -6,19 +6,29 @@ 0 0 - 762 - 270 + 800 + 265 - Missing clips + Clip Problems - + + + + + + + + true + + QAbstractItemView::ExtendedSelection + false @@ -57,7 +67,21 @@ + + + + Remove selected clips + + + + + + Fix duration mismatch + + + + Qt::Horizontal @@ -67,13 +91,6 @@ - - - - Remove selected clips - - -