#include <mlt++/Mlt.h>
-const double DOCUMENTVERSION = 0.85;
+const double DOCUMENTVERSION = 0.86;
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, QMap <QString, QString> properties, const QPoint tracks, Render *render, KTextEdit *notes, MainWindow *parent, KProgressDialog *progressDialog) :
+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) :
QObject(parent),
m_autosave(NULL),
m_url(url),
m_documentProperties["proxyminsize"] = QString::number(KdenliveSettings::proxyminsize());
m_documentProperties["generateimageproxy"] = QString::number((int) KdenliveSettings::generateimageproxy());
m_documentProperties["proxyimageminsize"] = QString::number(KdenliveSettings::proxyimageminsize());
-
+#if QT_VERSION >= 0x040700
+ m_documentProperties["documentid"] = QString::number(QDateTime::currentMSecsSinceEpoch());
+#else
+ QDateTime date = QDateTime::currentDateTime();
+ m_documentProperties["documentid"] = QString::number(date.toTime_t());
+#endif
+
// Load properties
QMapIterator<QString, QString> i(properties);
while (i.hasNext()) {
i.next();
m_documentProperties[i.key()] = i.value();
}
+
+ *openBackup = false;
if (!url.isEmpty()) {
QString tmpFile;
success = KIO::NetAccess::download(url.path(), tmpFile, parent);
- if (!success) // The file cannot be opened
- KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
+ if (!success) {
+ // The file cannot be opened
+ if (KMessageBox::warningContinueCancel(parent, i18n("Cannot open the project file, error is:\n%1\nDo you want to open a backup file?", KIO::NetAccess::lastErrorString()), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
+ *openBackup = true;
+ }
+ //KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
+ }
else {
QFile file(tmpFile);
QString errorMsg;
file.close();
KIO::NetAccess::removeTempFile(tmpFile);
- if (!success) // It is corrupted
- KMessageBox::error(parent, errorMsg);
+ 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);
+ }
else {
parent->slotGotProgressInfo(i18n("Validating"), 0);
qApp->processEvents();
if (!success) {
// It is not a project file
parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file", m_url.path()), 100);
+ if (KMessageBox::warningContinueCancel(parent, i18n("File %1 is not a valid project file.\nDo you want to open a backup file?", m_url.path()), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
+ *openBackup = true;
+ }
} else {
/*
* Validate the file against the current version (upgrade
// Something went wrong, or a new file was requested: create a new project
if (!success) {
- m_url = KUrl();
+ m_url.clear();
setProfilePath(profileName);
m_document = createEmptyDocument(tracks.x(), tracks.y());
}
kDebug() << "ERROR; CANNOT CREATE AUTOSAVE FILE";
}
kDebug() << "// AUTOSAVE FILE: " << m_autosave->fileName();
- saveSceneList(m_autosave->fileName(), m_render->sceneList(), QStringList());
+ saveSceneList(m_autosave->fileName(), m_render->sceneList(), QStringList(), true);
}
}
return QPoint(m_documentProperties.value("zonein").toInt(), m_documentProperties.value("zoneout").toInt());
}
-bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene, const QStringList expandedFolders)
+QDomDocument KdenliveDoc::xmlSceneList(const QString &scene, const QStringList expandedFolders)
{
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, scene list is corrupted.", path));
- return false;
+ //scenelist is corrupted
+ return sceneList;
}
QDomElement addedXml = sceneList.createElement("kdenlivedoc");
addedXml.appendChild(sceneList.importNode(m_clipManager->groupsXml(), true));
//wes.appendChild(doc.importNode(kdenliveData, true));
+ return sceneList;
+}
+bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene, const QStringList expandedFolders, bool autosave)
+{
+ QDomDocument sceneList = xmlSceneList(scene, expandedFolders);
+ if (sceneList.isNull()) {
+ //Make sure we don't save if scenelist is corrupted
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1, scene list is corrupted.", path));
+ return false;
+ }
+
+ // Backup current version
+ if (!autosave) backupLastSavedVersion(path);
QFile file(path);
+
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
kWarning() << "////// ERROR writing to file: " << path;
KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1", path));
return false;
}
file.close();
+ if (!autosave) {
+ cleanupBackupFiles();
+ QFileInfo info(file);
+ QString fileName = KUrl(path).fileName().section('.', 0, -2);
+ fileName.append("-" + m_documentProperties.value("documentid"));
+ fileName.append(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
+ fileName.append(".kdenlive.png");
+ KUrl backupFile = m_projectFolder;
+ backupFile.addPath(".backup/");
+ backupFile.addPath(fileName);
+ emit saveTimelinePreview(backupFile.path());
+ }
return true;
}
emit progressInfo(QString(), -1);
}*/
-void KdenliveDoc::checkProjectClips()
+void KdenliveDoc::checkProjectClips(bool displayRatioChanged)
{
if (m_render == NULL) return;
- m_clipManager->resetProducersList(m_render->producersList());
+ m_clipManager->resetProducersList(m_render->producersList(), displayRatioChanged);
}
Render *KdenliveDoc::renderer()
return result;
}
+// static
+double KdenliveDoc::getDisplayRatio(const QString &path)
+{
+ QFile file(path);
+ QDomDocument doc;
+ if (!file.open(QIODevice::ReadOnly)) {
+ kWarning() << "ERROR, CANNOT READ: " << path;
+ return 0;
+ }
+ if (!doc.setContent(&file)) {
+ kWarning() << "ERROR, CANNOT READ: " << path;
+ file.close();
+ return 0;
+ }
+ file.close();
+ QDomNodeList list = doc.elementsByTagName("profile");
+ if (list.isEmpty()) return 0;
+ QDomElement profile = list.at(0).toElement();
+ double den = profile.attribute("display_aspect_den").toDouble();
+ if (den > 0) return profile.attribute("display_aspect_num").toDouble() / den;
+ return 0;
+}
+
+void KdenliveDoc::backupLastSavedVersion(const QString &path)
+{
+ // Ensure backup folder exists
+ if (path.isEmpty()) return;
+ QFile file(path);
+ KUrl backupFile = m_projectFolder;
+ backupFile.addPath(".backup/");
+ 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(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
+ fileName.append(".kdenlive");
+ backupFile.addPath(fileName);
+
+ if (file.exists()) {
+ // delete previous backup if it was done less than 60 seconds ago
+ QFile::remove(backupFile.path());
+ if (!QFile::copy(path, backupFile.path())) {
+ KMessageBox::information(kapp->activeWindow(), i18n("Cannot create backup copy:\n%1", backupFile.path()));
+ }
+ }
+}
+
+void KdenliveDoc::cleanupBackupFiles()
+{
+ KUrl backupFile = m_projectFolder;
+ backupFile.addPath(".backup/");
+ QDir dir(backupFile.path());
+ QString projectFile = url().fileName().section('.', 0, -2);
+ projectFile.append("-" + m_documentProperties.value("documentid"));
+ projectFile.append("-??");
+ projectFile.append("??");
+ projectFile.append("-??");
+ projectFile.append("-??");
+ projectFile.append("-??");
+ projectFile.append("-??.kdenlive");
+
+ QStringList filter;
+ backupFile.addPath(projectFile);
+ filter << projectFile;
+ dir.setNameFilters(filter);
+ QFileInfoList resultList = dir.entryInfoList(QDir::Files, QDir::Time);
+
+ QDateTime d = QDateTime::currentDateTime();
+ QStringList hourList;
+ QStringList dayList;
+ QStringList weekList;
+ QStringList oldList;
+ for (int i = 0; i < resultList.count(); i++) {
+ if (d.secsTo(resultList.at(i).lastModified()) < 3600) {
+ // files created in the last hour
+ hourList.append(resultList.at(i).absoluteFilePath());
+ }
+ else if (d.secsTo(resultList.at(i).lastModified()) < 43200) {
+ // files created in the day
+ dayList.append(resultList.at(i).absoluteFilePath());
+ }
+ else if (d.daysTo(resultList.at(i).lastModified()) < 8) {
+ // files created in the week
+ weekList.append(resultList.at(i).absoluteFilePath());
+ }
+ else {
+ // older files
+ oldList.append(resultList.at(i).absoluteFilePath());
+ }
+ }
+ if (hourList.count() > 20) {
+ int step = hourList.count() / 10;
+ for (int i = 0; i < hourList.count(); i += step) {
+ kDebug()<<"REMOVE AT: "<<i<<", COUNT: "<<hourList.count();
+ hourList.removeAt(i);
+ i--;
+ }
+ } else hourList.clear();
+ if (dayList.count() > 20) {
+ int step = dayList.count() / 10;
+ for (int i = 0; i < dayList.count(); i += step) {
+ dayList.removeAt(i);
+ i--;
+ }
+ } else dayList.clear();
+ if (weekList.count() > 20) {
+ int step = weekList.count() / 10;
+ for (int i = 0; i < weekList.count(); i += step) {
+ weekList.removeAt(i);
+ i--;
+ }
+ } else weekList.clear();
+ if (oldList.count() > 20) {
+ int step = oldList.count() / 10;
+ for (int i = 0; i < oldList.count(); i += step) {
+ oldList.removeAt(i);
+ i--;
+ }
+ } else oldList.clear();
+
+ QString f;
+ while (hourList.count() > 0) {
+ f = hourList.takeFirst();
+ QFile::remove(f);
+ QFile::remove(f + ".png");
+ }
+ while (dayList.count() > 0) {
+ f = dayList.takeFirst();
+ QFile::remove(f);
+ QFile::remove(f + ".png");
+ }
+ while (weekList.count() > 0) {
+ f = weekList.takeFirst();
+ QFile::remove(f);
+ QFile::remove(f + ".png");
+ }
+ while (oldList.count() > 0) {
+ f = oldList.takeFirst();
+ QFile::remove(f);
+ QFile::remove(f + ".png");
+ }
+}
+
#include "kdenlivedoc.moc"