X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fkdenlivedoc.cpp;h=dd88c3b575b95f522e9d0859fe6e5440596b289a;hb=ead7176d2ab818ec3a1275aeca2b2fc0c1ea1276;hp=4d4a451d363a0c6ea8c1594120a738b955643e47;hpb=d43383d14efb17899c439d85c257f5be5d2a118e;p=kdenlive diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index 4d4a451d..dd88c3b5 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -42,10 +42,11 @@ #include #include #include +#include #include -const double DOCUMENTVERSION = 0.84; +const double DOCUMENTVERSION = 0.85; KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, const QPoint tracks, Render *render, MainWindow *parent) : QObject(parent), @@ -55,8 +56,6 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup m_commandStack(new QUndoStack(undoGroup)), m_modified(false), m_projectFolder(projectFolder), - m_documentLoadingStep(0.0), - m_documentLoadingProgress(0), m_abortLoading(false) { m_clipManager = new ClipManager(this); @@ -78,17 +77,22 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup else { QFile file(tmpFile); QString errorMsg; + QDomImplementation impl; + impl.setInvalidDataPolicy(QDomImplementation::DropInvalidChars); success = m_document.setContent(&file, false, &errorMsg); file.close(); KIO::NetAccess::removeTempFile(tmpFile); + if (!success) // It is corrupted KMessageBox::error(parent, errorMsg); else { + parent->slotGotProgressInfo(i18n("Validating"), 0); DocumentValidator validator(m_document); success = validator.isProject(); - if (!success) // It is not a project file - parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file.", m_url.path()), 100); - else { + if (!success) { + // It is not a project file + parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file", m_url.path()), 0); + } else { /* * Validate the file against the current version (upgrade * and recover it if needed). It is NOT a passive operation @@ -96,6 +100,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup // TODO: backup the document or alert the user? success = validator.validate(DOCUMENTVERSION); if (success) { // Let the validator handle error messages + parent->slotGotProgressInfo(i18n("Loading"), 0); QDomElement mlt = m_document.firstChildElement("mlt"); QDomElement infoXml = mlt.firstChildElement("kdenlivedoc"); @@ -129,29 +134,19 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup } QDomNodeList producers = m_document.elementsByTagName("producer"); QDomNodeList infoproducers = m_document.elementsByTagName("kdenlive_producer"); + parent->slotGotProgressInfo(i18n("Check missing clips"), 0); if (checkDocumentClips(infoproducers) == false) m_abortLoading = true; const int max = producers.count(); const int infomax = infoproducers.count(); - QDomNodeList folders = m_document.elementsByTagName("folder"); + QDomNodeList folders = m_document.elementsByTagName("folder"); for (int i = 0; i < folders.count(); i++) { e = folders.item(i).cloneNode().toElement(); m_clipManager->addFolder(e.attribute("id"), e.attribute("name")); } - if (max > 0) { - m_documentLoadingStep = 100.0 / (max + infomax + m_document.elementsByTagName("entry").count()); - parent->slotGotProgressInfo(i18n("Loading project clips"), (int) m_documentLoadingProgress); - } - - for (int i = 0; i < infomax && !m_abortLoading; i++) { e = infoproducers.item(i).cloneNode().toElement(); - if (m_documentLoadingStep > 0) { - m_documentLoadingProgress += m_documentLoadingStep; - parent->slotGotProgressInfo(QString(), (int) m_documentLoadingProgress); - //qApp->processEvents(); - } QString prodId = e.attribute("id"); if (!e.isNull() && prodId != "black" && !prodId.startsWith("slowmotion") && !m_abortLoading) { e.setTagName("producer"); @@ -166,7 +161,6 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup } } addClipInfo(e, orig, prodId); - kDebug() << "// KDENLIVE PRODUCER: " << prodId; } } if (m_abortLoading) { @@ -248,7 +242,7 @@ KdenliveDoc::~KdenliveDoc() int KdenliveDoc::setSceneList() { - m_render->resetProfile(); + m_render->resetProfile(KdenliveSettings::current_profile()); if (m_render->setSceneList(m_document.toString(), m_documentProperties.value("position").toInt()) == -1) { // INVALID MLT Consumer, something is wrong return -1; @@ -256,18 +250,11 @@ int KdenliveDoc::setSceneList() m_documentProperties.remove("position"); // m_document xml is now useless, clear it m_document.clear(); - checkProjectClips(); return 0; } -QDomDocument KdenliveDoc::createEmptyDocument(const int videotracks, const int audiotracks) +QDomDocument KdenliveDoc::createEmptyDocument(int videotracks, int audiotracks) { - // Creating new document - QDomDocument doc; - QDomElement mlt = doc.createElement("mlt"); - doc.appendChild(mlt); - - TrackInfo videoTrack; videoTrack.type = VIDEOTRACK; videoTrack.isMute = false; @@ -280,6 +267,25 @@ QDomDocument KdenliveDoc::createEmptyDocument(const int videotracks, const int a audioTrack.isBlind = true; audioTrack.isLocked = false; + m_tracksList.clear(); + + for (int i = 0; i < audiotracks; i++) { + m_tracksList.append(audioTrack); + } + for (int i = 0; i < videotracks; i++) { + m_tracksList.append(videoTrack); + } + return createEmptyDocument(m_tracksList); +} + +QDomDocument KdenliveDoc::createEmptyDocument(QList tracks) +{ + // Creating new document + QDomDocument doc; + QDomElement mlt = doc.createElement("mlt"); + doc.appendChild(mlt); + + // Create black producer // For some unknown reason, we have to build the black producer here and not in renderer.cpp, otherwise // the composite transitions with the black track are corrupted. @@ -336,12 +342,12 @@ QDomDocument KdenliveDoc::createEmptyDocument(const int videotracks, const int a QDomElement blank0 = doc.createElement("entry"); blank0.setAttribute("in", "0"); - blank0.setAttribute("out", "0"); + blank0.setAttribute("out", "1"); blank0.setAttribute("producer", "black"); playlist.appendChild(blank0); // create playlists - int total = audiotracks + videotracks + 1; + int total = tracks.count() + 1; for (int i = 1; i < total; i++) { QDomElement playlist = doc.createElement("playlist"); @@ -354,20 +360,16 @@ QDomDocument KdenliveDoc::createEmptyDocument(const int videotracks, const int a tractor.appendChild(track0); // create audio tracks - for (int i = 1; i < audiotracks + 1; i++) { - QDomElement track = doc.createElement("track"); - track.setAttribute("producer", "playlist" + QString::number(i)); - track.setAttribute("hide", "video"); - tractor.appendChild(track); - m_tracksList.append(audioTrack); - } - - // create video tracks - for (int i = audiotracks + 1; i < total; i++) { + for (int i = 1; i < total; i++) { QDomElement track = doc.createElement("track"); track.setAttribute("producer", "playlist" + QString::number(i)); + if (tracks.at(i - 1).type == AUDIOTRACK) + track.setAttribute("hide", "video"); + else if (tracks.at(i - 1).isBlind) + track.setAttribute("hide", "video"); + if (tracks.at(i - 1).isMute) + track.setAttribute("hide", "audio"); tractor.appendChild(track); - m_tracksList.append(videoTrack); } for (int i = 2; i < total ; i++) { @@ -479,6 +481,11 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene) QDomDocument sceneList; sceneList.setContent(scene, true); QDomElement mlt = sceneList.firstChildElement("mlt"); + if (mlt.isNull() || !mlt.hasChildNodes()) { + //Make sure we don't save if scenelist is corrupted + KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1", path)); + return false; + } QDomElement addedXml = sceneList.createElement("kdenlivedoc"); mlt.appendChild(addedXml); @@ -640,11 +647,12 @@ MltVideoProfile KdenliveDoc::mltProfile() const return m_profile; } -void KdenliveDoc::setProfilePath(QString path) +bool KdenliveDoc::setProfilePath(QString path) { if (path.isEmpty()) path = KdenliveSettings::default_profile(); if (path.isEmpty()) path = "dv_pal"; m_profile = ProfilesDialog::getVideoProfile(path); + bool current_fps = m_fps; if (m_profile.path.isEmpty()) { // Profile not found, use embedded profile QDomElement profileInfo = m_document.elementsByTagName("profileinfo").at(0).toElement(); @@ -697,6 +705,7 @@ void KdenliveDoc::setProfilePath(QString path) kDebug() << "Kdenlive document, init timecode from path: " << path << ", " << m_fps; if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(m_fps, true); else m_timecode.setFormat(m_fps); + return (current_fps != m_fps); } double KdenliveDoc::dar() @@ -709,12 +718,6 @@ void KdenliveDoc::setThumbsProgress(const QString &message, int progress) emit progressInfo(message, progress); } -void KdenliveDoc::loadingProgressed() -{ - m_documentLoadingProgress += m_documentLoadingStep; - emit progressInfo(QString(), (int) m_documentLoadingProgress); -} - QUndoStack *KdenliveDoc::commandStack() { return m_commandStack; @@ -865,30 +868,7 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) if (elem.attribute("type").toInt() == SLIDESHOW) { extension = KUrl(path).fileName(); path = KUrl(path).directory(); - } /*else if (elem.attribute("type").toInt() == TEXT && QFile::exists(path) == false) { - kDebug() << "// TITLE: " << elem.attribute("name") << " Preview file: " << elem.attribute("resource") << " DOES NOT EXIST"; - QString titlename = elem.attribute("name"); - QString titleresource; - if (titlename.isEmpty()) { - QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder()); - titlename = titleInfo.at(0); - titleresource = titleInfo.at(1); - elem.setAttribute("name", titlename); - kDebug() << "// New title set to: " << titlename; - } else { - titleresource = TitleWidget::getFreeTitleInfo(projectFolder()).at(1); - //titleresource = TitleWidget::getTitleResourceFromName(projectFolder(), titlename); - } - TitleWidget *dia_ui = new TitleWidget(KUrl(), KUrl(titleresource).directory(), m_render, kapp->activeWindow()); - QDomDocument doc; - doc.setContent(elem.attribute("xmldata")); - dia_ui->setXml(doc); - QImage pix = dia_ui->renderedPixmap(); - pix.save(titleresource); - elem.setAttribute("resource", titleresource); - setNewClipResource(clipId, titleresource); - delete dia_ui; - }*/ + } if (path.isEmpty() == false && QFile::exists(path) == false && elem.attribute("type").toInt() != TEXT && !elem.hasAttribute("placeholder")) { kDebug() << "// FOUND MISSING CLIP: " << path << ", TYPE: " << elem.attribute("type").toInt(); @@ -898,10 +878,10 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) int action = KMessageBox::No; if (!size.isEmpty() && !hash.isEmpty()) { if (!m_searchFolder.isEmpty()) newpath = searchFileRecursively(m_searchFolder, size, hash); - else action = (KMessageBox::ButtonCode) KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search automatically")), KGuiItem(i18n("Keep as placeholder"))); + else action = (KMessageBox::ButtonCode) KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search automatically")), KGuiItem(i18n("Keep as placeholder"))); } else { if (elem.attribute("type").toInt() == SLIDESHOW) { - int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder"))); + int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder"))); if (res == KMessageBox::Yes) newpath = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///clipfolder"), kapp->activeWindow(), i18n("Looking for %1", path)); else { @@ -909,7 +889,7 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) action = res; } } else { - int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder"))); + int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder"))); if (res == KMessageBox::Yes) newpath = KFileDialog::getOpenFileName(KUrl("kfiledialog:///clipfolder"), QString(), kapp->activeWindow(), i18n("Looking for %1", path)); else { @@ -944,12 +924,10 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) if (createClipItem) { emit addProjectClip(clip); - qApp->processEvents(); - m_render->getFileProperties(clip->toXML(), clip->getId(), true); + //qApp->processEvents(); } } - void KdenliveDoc::setNewClipResource(const QString &id, const QString &path) { QDomNodeList prods = m_document.elementsByTagName("producer"); @@ -1042,14 +1020,6 @@ void KdenliveDoc::addClipInfo(QDomElement elem, QDomElement orig, QString clipId } } -void KdenliveDoc::deleteProjectClip(QList ids) -{ - for (int i = 0; i < ids.size(); ++i) { - emit deleteTimelineClip(ids.at(i)); - m_clipManager->slotDeleteClip(ids.at(i)); - } - setModified(true); -} void KdenliveDoc::deleteClip(const QString &clipId) { @@ -1059,7 +1029,7 @@ void KdenliveDoc::deleteClip(const QString &clipId) void KdenliveDoc::slotAddClipList(const KUrl::List urls, const QString group, const QString &groupId) { m_clipManager->slotAddClipList(urls, group, groupId); - emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); + //emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); setModified(true); } @@ -1101,10 +1071,6 @@ void KdenliveDoc::slotCreateTextClip(QString group, const QString &groupId, cons KStandardDirs::makeDir(titlesFolder); TitleWidget *dia_ui = new TitleWidget(templatePath, m_timecode, titlesFolder, m_render, kapp->activeWindow()); if (dia_ui->exec() == QDialog::Accepted) { - /*QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder()); - QImage pix = dia_ui->renderedPixmap(); - pix.save(titleInfo.at(1));*/ - //dia_ui->saveTitle(path + ".kdenlivetitle"); m_clipManager->slotAddTextClipFile(i18n("Title clip"), dia_ui->duration(), dia_ui->xml().toString(), group, groupId); setModified(true); emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); @@ -1121,15 +1087,9 @@ void KdenliveDoc::slotCreateTextTemplateClip(QString group, const QString &group if (path.isEmpty()) return; - QStringList titleInfo = TitleWidget::getFreeTitleInfo(projectFolder(), true); - //TODO: rewrite with new title system (just set resource) - /*TitleWidget *dia_ui = new TitleWidget(path, titlesFolder, m_render, kapp->activeWindow()); - QImage pix = dia_ui->renderedPixmap(); - pix.save(titleInfo.at(1)); - delete dia_ui; - m_clipManager->slotAddTextTemplateClip(titleInfo.at(0), titleInfo.at(1), path, group, groupId); - setModified(true);*/ + m_clipManager->slotAddTextTemplateClip(i18n("Template title clip"), path, group, groupId); + setModified(true); emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); } @@ -1217,36 +1177,39 @@ QString KdenliveDoc::getLadspaFile() const bool KdenliveDoc::checkDocumentClips(QDomNodeList infoproducers) { - int clipType; - QDomElement e; - QString id; - QString resource; - QList missingClips; - for (int i = 0; i < infoproducers.count(); i++) { - e = infoproducers.item(i).toElement(); - clipType = e.attribute("type").toInt(); - if (clipType == COLOR) continue; - if (clipType == TEXT) { - //TODO: Check is clip template is missing (xmltemplate) or hash changed - continue; - } - id = e.attribute("id"); - resource = e.attribute("resource"); - if (clipType == SLIDESHOW) resource = KUrl(resource).directory(); - if (!KIO::NetAccess::exists(KUrl(resource), KIO::NetAccess::SourceSide, 0)) { - // Missing clip found - missingClips.append(e); - } else { - // Check if the clip has changed - if (clipType != SLIDESHOW && e.hasAttribute("file_hash")) { - if (e.attribute("file_hash") != DocClipBase::getHash(e.attribute("resource"))) - e.removeAttribute("file_hash"); + DocumentChecker d(infoproducers, m_document); + return (d.hasMissingClips() == false); + + /* int clipType; + QDomElement e; + QString id; + QString resource; + QList missingClips; + for (int i = 0; i < infoproducers.count(); i++) { + e = infoproducers.item(i).toElement(); + clipType = e.attribute("type").toInt(); + if (clipType == COLOR) continue; + if (clipType == TEXT) { + //TODO: Check is clip template is missing (xmltemplate) or hash changed + continue; + } + id = e.attribute("id"); + resource = e.attribute("resource"); + if (clipType == SLIDESHOW) resource = KUrl(resource).directory(); + if (!KIO::NetAccess::exists(KUrl(resource), KIO::NetAccess::SourceSide, 0)) { + // Missing clip found + missingClips.append(e); + } else { + // Check if the clip has changed + if (clipType != SLIDESHOW && e.hasAttribute("file_hash")) { + if (e.attribute("file_hash") != DocClipBase::getHash(e.attribute("resource"))) + e.removeAttribute("file_hash"); + } } } - } - if (missingClips.isEmpty()) return true; - DocumentChecker d(missingClips, m_document); - return (d.exec() == QDialog::Accepted); + if (missingClips.isEmpty()) return true; + DocumentChecker d(missingClips, m_document); + return (d.exec() == QDialog::Accepted);*/ } void KdenliveDoc::setDocumentProperty(const QString &name, const QString &value)