const double DOCUMENTVERSION = 0.88;
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, QMap <QString, QString> properties, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent, KProgressDialog *progressDialog) :
+KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, QMap <QString, QString> properties, QMap <QString, QString> metadata, const QPoint &tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent, KProgressDialog *progressDialog) :
QObject(parent),
m_autosave(NULL),
m_url(url),
m_clipManager = new ClipManager(this);
m_autoSaveTimer = new QTimer(this);
m_autoSaveTimer->setSingleShot(true);
+ connect(m_clipManager, SIGNAL(displayMessage(QString, int)), parent, SLOT(slotGotProgressInfo(QString,int)));
bool success = false;
// init default document properties
- m_documentProperties["zoom"] = "7";
- m_documentProperties["verticalzoom"] = "1";
- m_documentProperties["zonein"] = "0";
+ m_documentProperties["zoom"] = '7';
+ m_documentProperties["verticalzoom"] = '1';
+ m_documentProperties["zonein"] = '0';
m_documentProperties["zoneout"] = "100";
m_documentProperties["enableproxy"] = QString::number((int) KdenliveSettings::enableproxy());
m_documentProperties["proxyparams"] = KdenliveSettings::proxyparams();
i.next();
m_documentProperties[i.key()] = i.value();
}
+
+ // Load metadata
+ QMapIterator<QString, QString> j(metadata);
+ while (j.hasNext()) {
+ j.next();
+ m_documentMetadata[j.key()] = j.value();
+ }
if (QLocale().decimalPoint() != QLocale::system().decimalPoint()) {
setlocale(LC_NUMERIC, "");
systemLocale.setNumberOptions(QLocale::OmitGroupSeparator);
QLocale::setDefault(systemLocale);
// locale conversion might need to be redone
- initEffects::parseEffectFiles();
+ initEffects::parseEffectFiles(setlocale(LC_NUMERIC, NULL));
}
*openBackup = false;
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);
+ int line;
+ int col;
+ QDomImplementation::setInvalidDataPolicy(QDomImplementation::DropInvalidChars);
+ success = m_document.setContent(&file, false, &errorMsg, &line, &col);
+ file.close();
if (!success) {
// It is corrupted
- if (KMessageBox::warningContinueCancel(parent, i18n("Cannot open the project file, error is:\n%1\nDo you want to open a backup file?", errorMsg), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
- *openBackup = true;
- }
- //KMessageBox::error(parent, errorMsg);
+ int answer = KMessageBox::warningYesNoCancel (parent, i18n("Cannot open the project file, error is:\n%1 (line %2, col %3)\nDo you want to open a backup file?", errorMsg, line, col), i18n("Error opening file"), KGuiItem(i18n("Open Backup")), KGuiItem(i18n("Recover")));
+ if (answer == KMessageBox::Yes) {
+ *openBackup = true;
+ }
+ else if (answer == KMessageBox::No) {
+ // Try to recover broken file produced by Kdenlive 0.9.4
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ int correction = 0;
+ QString playlist = file.readAll();
+ while (!success && correction < 2) {
+ int errorPos = 0;
+ line--;
+ col = col - 2;
+ for (int j = 0; j < line && errorPos < playlist.length(); j++) {
+ errorPos = playlist.indexOf("\n", errorPos);
+ errorPos++;
+ }
+ errorPos += col;
+ if (errorPos >= playlist.length()) break;
+ playlist.remove(errorPos, 1);
+ line = 0;
+ col = 0;
+ success = m_document.setContent(playlist, false, &errorMsg, &line, &col);
+ correction++;
+ }
+ if (!success) {
+ KMessageBox::sorry(parent, i18n("Cannot recover this project file"));
+ }
+ else {
+ // Document was modified, ask for backup
+ QDomElement mlt = m_document.documentElement();
+ QDomElement info = mlt.firstChildElement("kdenlivedoc");
+ if (!info.isNull()) info.setAttribute("modified", 1);
+ }
+ }
+ }
}
- else {
+ if (success) {
parent->slotGotProgressInfo(i18n("Validating"), 0);
qApp->processEvents();
- DocumentValidator validator(m_document);
+ DocumentValidator validator(m_document, url);
success = validator.isProject();
if (!success) {
// It is not a project file
projectTrack.isBlind = e.attribute("blind").toInt();
projectTrack.isLocked = e.attribute("locked").toInt();
projectTrack.trackName = e.attribute("trackname");
+ projectTrack.effectsList = EffectsList(true);
m_tracksList.append(projectTrack);
}
}
int maxchild = markerslist.count();
for (int k = 0; k < maxchild; k++) {
e = markerslist.at(k).toElement();
- if (e.tagName() == "marker")
- m_clipManager->getClipById(e.attribute("id"))->addSnapMarker(GenTime(e.attribute("time").toDouble()), e.attribute("comment"));
+ if (e.tagName() == "marker") {
+ CommentedTime marker(GenTime(e.attribute("time").toDouble()), e.attribute("comment"), e.attribute("type").toInt());
+ DocClipBase *baseClip = m_clipManager->getClipById(e.attribute("id"));
+ if (baseClip) baseClip->addSnapMarker(marker);
+ else kDebug()<< " / / Warning, missing clip: "<< e.attribute("id");
+ }
}
infoXml.removeChild(markers);
}
QDomNamedNodeMap props = docproperties.attributes();
for (int i = 0; i < props.count(); i++)
m_documentProperties.insert(props.item(i).nodeName(), props.item(i).nodeValue());
+ docproperties = infoXml.firstChildElement("documentmetadata");
+ props = docproperties.attributes();
+ for (int i = 0; i < props.count(); i++)
+ m_documentMetadata.insert(props.item(i).nodeName(), props.item(i).nodeValue());
if (validator.isModified()) setModified(true);
kDebug() << "Reading file: " << url.path() << ", found clips: " << producers.count();
}
}
}
+ KIO::NetAccess::removeTempFile(tmpFile);
}
}
//kDebug() << "// SETTING SCENE LIST:\n\n" << m_document.toString();
connect(m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
+ connect(m_render, SIGNAL(addClip(const KUrl &, stringMap)), this, SLOT(slotAddClipFile(const KUrl &, stringMap)));
}
KdenliveDoc::~KdenliveDoc()
audioTrack.isLocked = false;
audioTrack.trackName = QString("Audio ") + QString::number(audiotracks - i);
audioTrack.duration = 0;
+ audioTrack.effectsList = EffectsList(true);
m_tracksList.append(audioTrack);
}
videoTrack.isLocked = false;
videoTrack.trackName = QString("Video ") + QString::number(videotracks - i);
videoTrack.duration = 0;
+ videoTrack.effectsList = EffectsList(true);
m_tracksList.append(videoTrack);
}
return createEmptyDocument(m_tracksList);
}
docproperties.setAttribute("position", m_render->seekPosition().frames(m_fps));
addedXml.appendChild(docproperties);
+
+ QDomElement docmetadata = sceneList.createElement("documentmetadata");
+ QMapIterator<QString, QString> j(m_documentMetadata);
+ while (j.hasNext()) {
+ j.next();
+ docmetadata.setAttribute(j.key(), j.value());
+ }
+ addedXml.appendChild(docmetadata);
QDomElement docnotes = sceneList.createElement("documentnotes");
QDomText value = sceneList.createTextNode(m_notesWidget->toHtml());
QDomElement e;
QList <DocClipBase*> list = m_clipManager->documentClipList();
for (int i = 0; i < list.count(); i++) {
- e = list.at(i)->toXML();
+ e = list.at(i)->toXML(true);
e.setTagName("kdenlive_producer");
addedXml.appendChild(sceneList.importNode(e, true));
QList < CommentedTime > marks = list.at(i)->commentedSnapMarkers();
marker.setAttribute("time", marks.at(j).time().ms() / 1000);
marker.setAttribute("comment", marks.at(j).comment());
marker.setAttribute("id", e.attribute("id"));
+ marker.setAttribute("type", marks.at(j).markerType());
markers.appendChild(marker);
}
}
cleanupBackupFiles();
QFileInfo info(file);
QString fileName = KUrl(path).fileName().section('.', 0, -2);
- fileName.append("-" + m_documentProperties.value("documentid"));
+ fileName.append('-' + m_documentProperties.value("documentid"));
fileName.append(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
fileName.append(".kdenlive.png");
KUrl backupFile = m_projectFolder;
KStandardDirs::makeDir(url.path());
KStandardDirs::makeDir(url.path(KUrl::AddTrailingSlash) + "titles/");
KStandardDirs::makeDir(url.path(KUrl::AddTrailingSlash) + "thumbs/");
- if (KMessageBox::questionYesNo(kapp->activeWindow(), i18n("You have changed the project folder. Do you want to copy the cached data from %1 to the new folder %2?").arg(m_projectFolder.path(), url.path())) == KMessageBox::Yes) moveProjectData(url);
+ if (KMessageBox::questionYesNo(kapp->activeWindow(), i18n("You have changed the project folder. Do you want to copy the cached data from %1 to the new folder %2?", m_projectFolder.path(), url.path())) == KMessageBox::Yes) moveProjectData(url);
m_projectFolder = url;
updateProjectFolderPlacesEntry();
extension = KUrl(path).fileName();
path = KUrl(path).directory();
}
-
- if (path.isEmpty() == false && QFile::exists(path) == false && elem.attribute("type").toInt() != TEXT && !elem.hasAttribute("placeholder")) {
+ if (elem.hasAttribute("_missingsource")) {
+ // Clip has proxy but missing original source
+ }
+ else 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();
const QString size = elem.attribute("file_size");
const QString hash = elem.attribute("file_hash");
QDomNamedNodeMap attributes = elem.attributes();
for (int i = 0; i < attributes.count(); i++) {
QString attrname = attributes.item(i).nodeName();
- if (attrname != "resource")
+ if (attrname != "resource")
properties.insert(attrname, attributes.item(i).nodeValue());
- kDebug() << attrname << " = " << attributes.item(i).nodeValue();
+ //kDebug() << attrname << " = " << attributes.item(i).nodeValue();
}
clip->setProperties(properties);
emit addProjectClip(clip, false);
QMap<QString, QString> meta;
for (QDomNode m = orig.firstChild(); !m.isNull(); m = m.nextSibling()) {
QString name = m.toElement().attribute("name");
- if (name.startsWith("meta.attr"))
- meta.insert(name.section('.', 2, 3), m.firstChild().nodeValue());
+ if (name.startsWith("meta.attr")) {
+ if (name.endsWith(".markup")) name = name.section('.', 0, -2);
+ meta.insert(name.section('.', 2, -1), m.firstChild().nodeValue());
+ }
}
if (!meta.isEmpty()) {
if (clip == NULL)
emit signalDeleteProjectClip(clipId);
}
-void KdenliveDoc::slotAddClipList(const KUrl::List urls, const QString &group, const QString &groupId)
+void KdenliveDoc::slotAddClipList(const KUrl::List urls, stringMap data)
{
- m_clipManager->slotAddClipList(urls, group, groupId);
+ m_clipManager->slotAddClipList(urls, data);
//emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
setModified(true);
}
-void KdenliveDoc::slotAddClipFile(const KUrl &url, const QString &group, const QString &groupId)
+void KdenliveDoc::slotAddClipFile(const KUrl &url, stringMap data)
{
- m_clipManager->slotAddClipFile(url, group, groupId);
+ m_clipManager->slotAddClipFile(url, data);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
setModified(true);
}
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
-void KdenliveDoc::slotCreateSlideshowClipFile(const QString &name, const QString &path, int count, const QString &duration,
- const bool loop, const bool crop, const bool fade,
- const QString &luma_duration, const QString &luma_file, const int softness,
- const QString &animation, QString group, const QString &groupId)
+void KdenliveDoc::slotCreateSlideshowClipFile(QMap <QString, QString> properties, QString group, const QString &groupId)
{
- m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop,
- crop, fade, luma_duration,
- luma_file, softness,
- animation, group, groupId);
+ m_clipManager->slotAddSlideshowClipFile(properties, group, groupId);
setModified(true);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
{
QString titlesFolder = projectFolder().path(KUrl::AddTrailingSlash) + "titles/";
KStandardDirs::makeDir(titlesFolder);
- TitleWidget *dia_ui = new TitleWidget(templatePath, m_timecode, titlesFolder, m_render, kapp->activeWindow());
+ QPointer<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->outPoint(), dia_ui->xml().toString(), group, groupId);
+ m_clipManager->slotAddTextClipFile(i18n("Title clip"), dia_ui->duration(), dia_ui->xml().toString(), group, groupId);
setModified(true);
emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
}
return QPoint(video, audio);
}
-void KdenliveDoc::cachePixmap(const QString &fileId, const QPixmap &pix) const
+void KdenliveDoc::cacheImage(const QString &fileId, const QImage &img) const
{
- pix.save(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/" + fileId + ".png");
+ img.save(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/" + fileId + ".png");
}
bool KdenliveDoc::checkDocumentClips(QDomNodeList infoproducers)
kWarning() << "Remove Track effect outisde of range";
return;
}
- QString index;
- QString toRemove = effect.attribute("kdenlive_ix");
+ int index;
+ int toRemove = effect.attribute("kdenlive_ix").toInt();
for (int i = 0; i < m_tracksList.at(ix).effectsList.count(); ++i) {
- index = m_tracksList.at(ix).effectsList.at(i).attribute("kdenlive_ix");
+ index = m_tracksList.at(ix).effectsList.at(i).attribute("kdenlive_ix").toInt();
if (toRemove == index) {
- m_tracksList[ix].effectsList.removeAt(i);
- i--;
- } else if (index.toInt() > toRemove.toInt()) {
- m_tracksList[ix].effectsList.item(i).setAttribute("kdenlive_ix", index.toInt() - 1);
+ m_tracksList[ix].effectsList.removeAt(toRemove);
+ break;
}
}
}
kWarning() << "Set Track effect outisde of range";
return;
}
- if (effectIndex < 0 || effectIndex > (m_tracksList.at(trackIndex).effectsList.count() - 1) || effect.isNull()) {
+ if (effectIndex <= 0 || effectIndex > (m_tracksList.at(trackIndex).effectsList.count()) || effect.isNull()) {
kDebug() << "Invalid effect index: " << effectIndex;
return;
}
- effect.setAttribute("kdenlive_ix", effectIndex + 1);
- m_tracksList[trackIndex].effectsList.replace(effectIndex, effect);
+ m_tracksList[trackIndex].effectsList.removeAt(effect.attribute("kdenlive_ix").toInt());
+ effect.setAttribute("kdenlive_ix", effectIndex);
+ m_tracksList[trackIndex].effectsList.insert(effect);
+ //m_tracksList[trackIndex].effectsList.updateEffect(effect);
+}
+
+void KdenliveDoc::enableTrackEffects(int trackIndex, QList <int> effectIndexes, bool disable)
+{
+ if (trackIndex < 0 || trackIndex >= m_tracksList.count()) {
+ kWarning() << "Set Track effect outisde of range";
+ return;
+ }
+ EffectsList list = m_tracksList.at(trackIndex).effectsList;
+ QDomElement effect;
+ for (int i = 0; i < effectIndexes.count(); i++) {
+ effect = list.itemFromIndex(effectIndexes.at(i));
+ if (!effect.isNull()) effect.setAttribute("disable", (int) disable);
+ }
}
const EffectsList KdenliveDoc::getTrackEffects(int ix)
return QDomElement();
}
EffectsList list = m_tracksList.at(trackIndex).effectsList;
- if (effectIndex > list.count() - 1 || effectIndex < 0 || list.at(effectIndex).isNull()) return QDomElement();
- return list.at(effectIndex).cloneNode().toElement();
+ if (effectIndex > list.count() || effectIndex < 1 || list.itemFromIndex(effectIndex).isNull()) return QDomElement();
+ return list.itemFromIndex(effectIndex).cloneNode().toElement();
+}
+
+int KdenliveDoc::hasTrackEffect(int trackIndex, const QString &tag, const QString &id) const
+{
+ if (trackIndex < 0 || trackIndex >= m_tracksList.count()) {
+ kWarning() << "Get Track effect outisde of range";
+ return -1;
+ }
+ EffectsList list = m_tracksList.at(trackIndex).effectsList;
+ return list.hasEffect(tag, id);
}
bool KdenliveDoc::saveCustomEffects(QDomNodeList customeffects)
KIO::NetAccess::mkdir(backupFile, kapp->activeWindow());
QString fileName = KUrl(path).fileName().section('.', 0, -2);
QFileInfo info(file);
- fileName.append("-" + m_documentProperties.value("documentid"));
+ fileName.append('-' + m_documentProperties.value("documentid"));
fileName.append(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
fileName.append(".kdenlive");
backupFile.addPath(fileName);
backupFile.addPath(".backup/");
QDir dir(backupFile.path());
QString projectFile = url().fileName().section('.', 0, -2);
- projectFile.append("-" + m_documentProperties.value("documentid"));
+ projectFile.append('-' + m_documentProperties.value("documentid"));
projectFile.append("-??");
projectFile.append("??");
projectFile.append("-??");
}
}
+const QMap <QString, QString> KdenliveDoc::metadata() const
+{
+ return m_documentMetadata;
+}
+
+void KdenliveDoc::setMetadata(const QMap <QString, QString> meta)
+{
+ setModified(true);
+ m_documentMetadata = meta;
+}
+
#include "kdenlivedoc.moc"