X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fkdenlivedoc.cpp;h=2e0b13aca5df3ed8b5a4d12e90ed9d758113e10b;hb=08a49ce40071207043020d0d8f3c804703ee7af8;hp=0c927b71a3d3ba9319aa7a1f62c9035e50e489af;hpb=c931f2b6e300e5c24f76ea4d1608d6213f7ef00a;p=kdenlive diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index 0c927b71..2e0b13ac 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,6 +77,8 @@ 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); @@ -85,14 +86,13 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup if (!success) // It is corrupted KMessageBox::error(parent, errorMsg); else { - parent->slotGotProgressInfo(i18n("Validating file %1", m_url.path()), 0); + 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()), 0); - } - else { + 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 @@ -100,7 +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 file %1", m_url.path()), 0); + parent->slotGotProgressInfo(i18n("Loading"), 0); QDomElement mlt = m_document.firstChildElement("mlt"); QDomElement infoXml = mlt.firstChildElement("kdenlivedoc"); @@ -134,6 +134,7 @@ 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(); @@ -144,19 +145,8 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup 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"); @@ -171,7 +161,6 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup } } addClipInfo(e, orig, prodId); - kDebug() << "// KDENLIVE PRODUCER: " << prodId; } } if (m_abortLoading) { @@ -280,10 +269,16 @@ QDomDocument KdenliveDoc::createEmptyDocument(int videotracks, int audiotracks) m_tracksList.clear(); + // Tracks are added «backwards», so we need to reverse the track numbering + // mbt 331: http://www.kdenlive.org/mantis/view.php?id=331 + // Better default names for tracks: Audio 1 etc. instead of blank numbers for (int i = 0; i < audiotracks; i++) { + audioTrack.trackName = QString("Audio ") + QString::number(audiotracks - i); m_tracksList.append(audioTrack); + } for (int i = 0; i < videotracks; i++) { + videoTrack.trackName = QString("Video ") + QString::number(videotracks - i); m_tracksList.append(videoTrack); } return createEmptyDocument(m_tracksList); @@ -353,7 +348,7 @@ QDomDocument KdenliveDoc::createEmptyDocument(QList tracks) QDomElement blank0 = doc.createElement("entry"); blank0.setAttribute("in", "0"); - blank0.setAttribute("out", "0"); + blank0.setAttribute("out", "1"); blank0.setAttribute("producer", "black"); playlist.appendChild(blank0); @@ -370,13 +365,13 @@ QDomDocument KdenliveDoc::createEmptyDocument(QList tracks) track0.setAttribute("producer", "black_track"); tractor.appendChild(track0); - // create audio tracks + // create audio and video tracks 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) + if (tracks.at(i - 1).type == AUDIOTRACK) { track.setAttribute("hide", "video"); - else if (tracks.at(i - 1).isBlind) + } else if (tracks.at(i - 1).isBlind) track.setAttribute("hide", "video"); if (tracks.at(i - 1).isMute) track.setAttribute("hide", "audio"); @@ -492,6 +487,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); @@ -526,7 +526,7 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene) // tracks info QDomElement tracksinfo = sceneList.createElement("tracksinfo"); - foreach(const TrackInfo &info, m_tracksList) { + foreach(const TrackInfo & info, m_tracksList) { QDomElement trackinfo = sceneList.createElement("trackinfo"); if (info.type == AUDIOTRACK) trackinfo.setAttribute("type", "audio"); trackinfo.setAttribute("mute", info.isMute); @@ -724,12 +724,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; @@ -751,7 +745,6 @@ void KdenliveDoc::setRenderer(Render *render) { void KdenliveDoc::checkProjectClips() { - kDebug() << "+++++++++++++ + + + + CHK PCLIPS"; if (m_render == NULL) return; m_clipManager->resetProducersList(m_render->producersList()); } @@ -890,10 +883,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 { @@ -901,7 +894,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 { @@ -940,7 +933,6 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem) } } - void KdenliveDoc::setNewClipResource(const QString &id, const QString &path) { QDomNodeList prods = m_document.elementsByTagName("producer"); @@ -975,7 +967,7 @@ QString KdenliveDoc::searchFileRecursively(const QDir &dir, const QString &match * 1 MB = 1 second per 450 files (or faster) * 10 MB = 9 seconds per 450 files (or faster) */ - if (file.size() > 1000000*2) { + if (file.size() > 1000000 * 2) { fileData = file.read(1000000); if (file.seek(file.size() - 1000000)) fileData.append(file.readAll()); @@ -1033,14 +1025,6 @@ void KdenliveDoc::addClipInfo(QDomElement elem, QDomElement orig, QString clipId } } -void KdenliveDoc::deleteProjectClip(QStringList ids) -{ - for (int i = 0; i < ids.size(); ++i) { - emit deleteTimelineClip(ids.at(i)); - } - m_clipManager->slotDeleteClips(ids); - setModified(true); -} void KdenliveDoc::deleteClip(const QString &clipId) { @@ -1050,7 +1034,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); } @@ -1072,6 +1056,13 @@ DocClipBase *KdenliveDoc::getBaseClip(const QString &clipId) return m_clipManager->getClipById(clipId); } +void KdenliveDoc::slotCreateXmlClip(const QString &name, const QDomElement xml, QString group, const QString &groupId) +{ + m_clipManager->slotAddXmlClipFile(name, xml, group, groupId); + setModified(true); + emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); +} + void KdenliveDoc::slotCreateColorClip(const QString &name, const QString &color, const QString &duration, QString group, const QString &groupId) { m_clipManager->slotAddColorClipFile(name, color, duration, group, groupId); @@ -1092,7 +1083,7 @@ 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) { - m_clipManager->slotAddTextClipFile(i18n("Title clip"), dia_ui->duration(), dia_ui->xml().toString(), group, groupId); + m_clipManager->slotAddTextClipFile(i18n("Title clip"), dia_ui->outPoint(), dia_ui->xml().toString(), group, groupId); setModified(true); emit selectLastAddedClip(QString::number(m_clipManager->lastClipId())); } @@ -1173,7 +1164,7 @@ QPoint KdenliveDoc::getTracksCount() const { int audio = 0; int video = 0; - foreach(const TrackInfo &info, m_tracksList) { + foreach(const TrackInfo & info, m_tracksList) { if (info.type == VIDEOTRACK) video++; else audio++; } @@ -1198,36 +1189,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)