X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fdocumentchecker.cpp;h=a89ddc13a243a05030b97b267d890fd23c5fbce1;hb=86c076b216a77db8ac8900086d0579a27f0ca490;hp=e3444c03a9a88e44bb0bac539a888bb2b65d9a8c;hpb=87de4cac546a70345ea550388f62093e5957aca1;p=kdenlive diff --git a/src/documentchecker.cpp b/src/documentchecker.cpp index e3444c03..a89ddc13 100644 --- a/src/documentchecker.cpp +++ b/src/documentchecker.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -74,10 +75,14 @@ bool DocumentChecker::hasErrorInClips() int clipType; QDomElement e; QString resource; + int max; QDomNodeList documentProducers = m_doc.elementsByTagName("producer"); QList wrongDurationClips; QList missingProxies; - for (int i = 0; i < m_info.count(); i++) { + m_safeImages.clear(); + m_safeFonts.clear(); + max = m_info.count(); + for (int i = 0; i < max; i++) { e = m_info.item(i).toElement(); clipType = e.attribute("type").toInt(); if (clipType == COLOR) continue; @@ -85,10 +90,13 @@ bool DocumentChecker::hasErrorInClips() QString id = e.attribute("id"); int duration = e.attribute("duration").toInt(); int mltDuration = -1; + QDomElement mltProd; + QString prodId; // 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"); + int prodsCount = documentProducers.count(); + for (int j = 0; j < prodsCount; j++) { + mltProd = documentProducers.at(j).toElement(); + 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); @@ -118,7 +126,7 @@ bool DocumentChecker::hasErrorInClips() //TODO: Check is clip template is missing (xmltemplate) or hash changed QStringList images = TitleWidget::extractImageList(e.attribute("xmldata")); QStringList fonts = TitleWidget::extractFontList(e.attribute("xmldata")); - checkMissingImages(images, fonts, e.attribute("id"), e.attribute("name")); + checkMissingImagesAndFonts(images, fonts, e.attribute("id"), e.attribute("name")); continue; } resource = e.attribute("resource"); @@ -142,20 +150,29 @@ bool DocumentChecker::hasErrorInClips() } } + // Get list of used Luma files QStringList missingLumas; + QStringList filesToCheck; + QString filePath; QString root = m_doc.documentElement().attribute("root"); if (!root.isEmpty()) root = KUrl(root).path(KUrl::AddTrailingSlash); QDomNodeList trans = m_doc.elementsByTagName("transition"); - for (int i = 0; i < trans.count(); i++) { + max = trans.count(); + for (int i = 0; i < max; i++) { QString luma = getProperty(trans.at(i).toElement(), "luma"); - if (!luma.isEmpty()) { - QString lumaPath = luma; - if (!lumaPath.startsWith('/')) lumaPath.prepend(root); - if (!QFile::exists(lumaPath) && !missingLumas.contains(luma)) { - missingLumas.append(luma); - } + if (!luma.isEmpty() && !filesToCheck.contains(luma)) + filesToCheck.append(luma); + } + // Check existence of luma files + foreach (const QString lumafile, filesToCheck) { + filePath = lumafile; + if (!filePath.startsWith('/')) filePath.prepend(root); + if (!QFile::exists(filePath)) { + missingLumas.append(lumafile); } } + + if (m_missingClips.isEmpty() && missingLumas.isEmpty() && wrongDurationClips.isEmpty() && missingProxies.isEmpty()) return false; @@ -172,7 +189,8 @@ bool DocumentChecker::hasErrorInClips() } m_ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - for (int i = 0; i < m_missingClips.count(); i++) { + max = m_missingClips.count(); + for (int i = 0; i < max; i++) { e = m_missingClips.at(i).toElement(); QString clipType; int t = e.attribute("type").toInt(); @@ -250,8 +268,9 @@ bool DocumentChecker::hasErrorInClips() m_ui.recursiveSearch->setEnabled(!m_missingClips.isEmpty() || !missingLumas.isEmpty()); m_ui.usePlaceholders->setEnabled(!m_missingClips.isEmpty()); m_ui.fixDuration->setEnabled(!wrongDurationClips.isEmpty()); - - for (int i = 0; i < wrongDurationClips.count(); i++) { + + max = wrongDurationClips.count(); + for (int i = 0; i < max; i++) { e = wrongDurationClips.at(i).toElement(); QString clipType; int t = e.attribute("type").toInt(); @@ -300,7 +319,8 @@ bool DocumentChecker::hasErrorInClips() item->setToolTip(0, i18n("Missing proxy")); } - for (int i = 0; i < missingProxies.count(); i++) { + max = missingProxies.count(); + for (int i = 0; i < max; i++) { e = missingProxies.at(i).toElement(); QString clipType; QString realPath = e.attribute("resource"); @@ -309,7 +329,8 @@ bool DocumentChecker::hasErrorInClips() QDomNodeList properties; QDomElement mltProd; QDomElement property; - for (int j = 0; j < documentProducers.count(); j++) { + int prodsCount = documentProducers.count(); + for (int j = 0; j < prodsCount; j++) { mltProd = documentProducers.at(j).toElement(); QString prodId = mltProd.attribute("id"); bool slowmotion = false; @@ -337,8 +358,7 @@ bool DocumentChecker::hasErrorInClips() if (missingProxies.count() > 0) { // original doc was modified - QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); - QDomElement infoXml = infoXmlNode.toElement(); + QDomElement infoXml = m_doc.elementsByTagName("kdenlivedoc").at(0).toElement(); infoXml.setAttribute("modified", "1"); } @@ -393,9 +413,10 @@ void DocumentChecker::slotSearchClips() bool fixed = false; m_ui.recursiveSearch->setEnabled(false); QTreeWidgetItem *child = m_ui.treeWidget->topLevelItem(ix); + QDir searchDir(newpath); while (child) { if (child->data(0, statusRole).toInt() == CLIPMISSING) { - QString clipPath = searchFileRecursively(QDir(newpath), child->data(0, sizeRole).toString(), child->data(0, hashRole).toString()); + QString clipPath = searchFileRecursively(searchDir, child->data(0, sizeRole).toString(), child->data(0, hashRole).toString()); if (!clipPath.isEmpty()) { fixed = true; child->setText(1, clipPath); @@ -403,7 +424,7 @@ void DocumentChecker::slotSearchClips() child->setData(0, statusRole, CLIPOK); } } else if (child->data(0, statusRole).toInt() == LUMAMISSING) { - QString fileName = searchLuma(child->data(0, idRole).toString()); + QString fileName = searchLuma(searchDir, child->data(0, idRole).toString()); if (!fileName.isEmpty()) { fixed = true; child->setText(1, fileName); @@ -411,40 +432,74 @@ void DocumentChecker::slotSearchClips() child->setData(0, statusRole, LUMAOK); } } + else if (child->data(0, typeRole).toInt() == TITLE_IMAGE_ELEMENT && child->data(0, statusRole).toInt() == CLIPPLACEHOLDER) { + // Search missing title images + QString missingFileName = KUrl(child->text(1)).fileName(); + QString newPath = searchPathRecursively(searchDir, missingFileName); + if (!newPath.isEmpty()) { + // File found + fixed = true; + child->setText(1, newPath); + child->setIcon(0, KIcon("dialog-ok")); + child->setData(0, statusRole, CLIPOK); + } + } ix++; 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(); + QDomElement infoXml = m_doc.elementsByTagName("kdenlivedoc").at(0).toElement(); infoXml.setAttribute("modified", "1"); } checkStatus(); } -QString DocumentChecker::searchLuma(QString file) const +QString DocumentChecker::searchLuma(const QDir &dir, const QString &file) const { KUrl searchPath(KdenliveSettings::mltpath()); + QString fname = KUrl(file).fileName(); if (file.contains("PAL")) searchPath.cd("../lumas/PAL"); else searchPath.cd("../lumas/NTSC"); - QString result = searchPath.path(KUrl::AddTrailingSlash) + KUrl(file).fileName(); + QString result = searchPath.path(KUrl::AddTrailingSlash) + fname; if (QFile::exists(result)) return result; // try to find luma in application path searchPath.clear(); searchPath = KUrl(QCoreApplication::applicationDirPath()); searchPath.cd("../share/apps/kdenlive/lumas"); - result = searchPath.path(KUrl::AddTrailingSlash) + KUrl(file).fileName(); + result = searchPath.path(KUrl::AddTrailingSlash) + fname; if (QFile::exists(result)) return result; - return QString(); + // Try in Kdenlive's standard KDE path + result = KStandardDirs::locate("appdata", "lumas/" + fname); + if (!result.isEmpty()) return result; + // Try in user's chosen folder + return searchPathRecursively(dir, fname); } +QString DocumentChecker::searchPathRecursively(const QDir &dir, const QString &fileName) const +{ + QString foundFileName; + QStringList filters; + filters << fileName; + QDir searchDir(dir); + searchDir.setNameFilters(filters); + QStringList filesAndDirs = searchDir.entryList(QDir::Files | QDir::Readable); + if (!filesAndDirs.isEmpty()) return searchDir.absoluteFilePath(filesAndDirs.at(0)); + searchDir.setNameFilters(QStringList()); + filesAndDirs = searchDir.entryList(QDir::Dirs | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot); + for (int i = 0; i < filesAndDirs.size() && foundFileName.isEmpty(); i++) { + foundFileName = searchPathRecursively(searchDir.absoluteFilePath(filesAndDirs.at(i)), fileName); + if (!foundFileName.isEmpty()) + break; + } + return foundFileName; +} QString DocumentChecker::searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash) const { @@ -677,8 +732,7 @@ void DocumentChecker::slotFixDuration() ix++; child = m_ui.treeWidget->topLevelItem(ix); } - QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); - QDomElement infoXml = infoXmlNode.toElement(); + QDomElement infoXml = m_doc.elementsByTagName("kdenlivedoc").at(0).toElement(); infoXml.setAttribute("modified", "1"); m_ui.fixDuration->setEnabled(false); checkStatus(); @@ -740,8 +794,8 @@ void DocumentChecker::slotDeleteSelected() QDomNodeList producers = m_doc.elementsByTagName("producer"); QDomNodeList infoproducers = m_doc.elementsByTagName("kdenlive_producer"); - QDomElement mlt = m_doc.firstChildElement("mlt"); - QDomElement kdenlivedoc = mlt.firstChildElement("kdenlivedoc"); + QDomNode mlt = m_doc.elementsByTagName("mlt").at(0); + QDomNode kdenlivedoc = m_doc.elementsByTagName("kdenlivedoc").at(0); for (int i = 0, j = 0; i < infoproducers.count() && j < deletedIds.count(); i++) { e = infoproducers.item(i).toElement(); @@ -778,17 +832,17 @@ void DocumentChecker::slotDeleteSelected() } } } - QDomNode infoXmlNode = m_doc.elementsByTagName("kdenlivedoc").at(0); - QDomElement infoXml = infoXmlNode.toElement(); + QDomElement infoXml = m_doc.elementsByTagName("kdenlivedoc").at(0).toElement(); infoXml.setAttribute("modified", "1"); checkStatus(); } } -void DocumentChecker::checkMissingImages(QStringList images, QStringList fonts, QString id, QString baseClip) +void DocumentChecker::checkMissingImagesAndFonts(QStringList images, QStringList fonts, const QString &id, const QString &baseClip) { QDomDocument doc; foreach(const QString &img, images) { + if (m_safeImages.contains(img)) continue; if (!KIO::NetAccess::exists(KUrl(img), KIO::NetAccess::SourceSide, 0)) { QDomElement e = doc.createElement("missingclip"); e.setAttribute("type", TITLE_IMAGE_ELEMENT); @@ -797,11 +851,12 @@ void DocumentChecker::checkMissingImages(QStringList images, QStringList fonts, e.setAttribute("name", baseClip); m_missingClips.append(e); } + else m_safeImages.append(img); } - kDebug() << "/ / / CHK FONTS: " << fonts; foreach(const QString &fontelement, fonts) { + if (m_safeFonts.contains(fontelement)) continue; QFont f(fontelement); - kDebug() << "/ / / CHK FONTS: " << fontelement << " = " << QFontInfo(f).family(); + //kDebug() << "/ / / CHK FONTS: " << fontelement << " = " << QFontInfo(f).family(); if (fontelement != QFontInfo(f).family()) { QDomElement e = doc.createElement("missingclip"); e.setAttribute("type", TITLE_FONT_ELEMENT); @@ -810,6 +865,7 @@ void DocumentChecker::checkMissingImages(QStringList images, QStringList fonts, e.setAttribute("name", baseClip); m_missingClips.append(e); } + else m_safeFonts.append(fontelement); } }